void rebuildSignal(int signal) { if(signal == SIGALRM) { // possivel tentativa de reconstrucao do anel if(rebuild() == -1) { puterror("não foi possível reconstruir o anel\n"); putmessage("vai ser feito um reset ao nó\n"); //fechar todas as ligações com predi e succi closeConnection(&succiNode.fd); closeConnection(&prediNode.fd); curNode.id = succiNode.id = prediNode.id = -1; if(iAmStartNode) { //remover anel do servidor unregisterRing(curRing); curRing = -1; iAmStartNode = FALSE; } } } }
int main(int argc, char *argv[]) { int mtype, size, c, list = FALSE, limit = -1, deflt = -1; int fd; char *userlist = 0, *user, **users, *p; short status; struct user_priority *ppri_tbl, *ld_priority_file(); extern char *optarg; extern int optind, opterr, optopt, errno; setlocale(LC_ALL, ""); #if !defined(TEXT_DOMAIN) #define TEXT_DOMAIN "SYS_TEST" #endif (void) textdomain(TEXT_DOMAIN); if(argc == 1) { usage: (void) printf(gettext("usage: \n")); (void) printf(gettext("(assign priority limit to users)\n")); (void) printf(gettext("\tlpusers -q priority -u user-list\n")); (void) printf(gettext( "(assign default priority limit for balance of users)\n")); (void) printf(gettext("\tlpusers -q priority\n")); (void) printf(gettext("(put users back to default priority limit)\n")); (void) printf(gettext("\tlpusers -u user-list\n")); (void) printf(gettext("(assign default priority)\n")); (void) printf(gettext("\tlpusers -d priority\n")); (void) printf(gettext("(examine priority limits, defaults)\n")); (void) printf(gettext("\tlpusers -l\n")); exit(argc == 1); } opterr = 0; /* disable printing of errors by getopt */ while ((c = getopt(argc, argv, "ld:q:u:")) != -1) switch(c) { case 'l': if (list) LP_ERRMSG1(WARNING, E_LP_2MANY, 'l'); list = TRUE; break; case 'd': if (deflt != -1) LP_ERRMSG1(WARNING, E_LP_2MANY, 'd'); deflt = (int)strtol(optarg,&p,10); if (*p || deflt<PRI_MIN || deflt>PRI_MAX) { LP_ERRMSG1(ERROR, E_LP_BADPRI, optarg); exit(1); } break; case 'q': if (limit != -1) LP_ERRMSG1(WARNING, E_LP_2MANY, 'q'); limit = (int)strtol(optarg,&p,10); if (*p || limit<PRI_MIN || limit>PRI_MAX) { LP_ERRMSG1(ERROR, E_LP_BADPRI, optarg); exit(1); } break; case 'u': if (userlist) LP_ERRMSG1(WARNING, E_LP_2MANY, 'u'); userlist = optarg; break; case '?': if (optopt == '?') goto usage; (p = "-X")[1] = optopt; if (strchr("ldqu", optopt)) LP_ERRMSG1(ERROR, E_LP_OPTARG, p); else LP_ERRMSG1(ERROR, E_LP_OPTION, p); exit(1); } if (optind < argc) { LP_ERRMSG1(ERROR, E_LP_EXTRA, argv[optind]); exit(1); } if (((list || deflt != -1) && (limit != -1 || userlist)) || (list && deflt != -1)) { LP_ERRMSG(ERROR, E_LP_OPTCOMB); /* invalid combination of options */ exit(1); } PRIORITY = Lp_Users; /* load existing priorities from file */ if (!(ppri_tbl = ld_priority_file(PRIORITY))) { switch (errno) { case EBADF: LP_ERRMSG1(ERROR, E_LPU_BADFORM, PRIORITY); break; default: LP_ERRMSG2(ERROR, E_LPU_BADFILE, PRIORITY, errno); } exit(1); } if (list) { print_tbl(ppri_tbl); exit (0); } else { if (userlist) { users = getlist(userlist, " \t", ","); if (users) while (user = *users++) { if (del_user(ppri_tbl, user) && (limit == -1)) LP_ERRMSG1(WARNING, E_LPU_NOUSER, user); if (limit != -1) { if (add_user(ppri_tbl, user, limit)) LP_ERRMSG1(WARNING, E_LPU_BADU, user); } } } else if (deflt != -1) ppri_tbl->deflt = deflt; else ppri_tbl->deflt_limit = limit; if ((fd = open_locked(PRIORITY, "w", LPU_MODE)) < 0) { LP_ERRMSG1(ERROR, E_LP_ACCESS, PRIORITY); exit(1); } output_tbl(fd, ppri_tbl); close(fd); } if (mopen()) /* error on mopen == no spooler, exit quietly */ exit(0); (void)putmessage (message, S_LOAD_USER_FILE); if (msend(message)) goto Error; if (mrecv(reply, sizeof(reply)) == -1) goto Error; mtype = getmessage(reply, R_LOAD_USER_FILE, &status); if (mtype != R_LOAD_USER_FILE) { LP_ERRMSG1 (ERROR, E_LP_BADREPLY, mtype); goto NoError; } if (status == 0) goto NoError; Error: LP_ERRMSG (ERROR, E_LPU_NOLOAD); NoError:(void)mclose (); return (0); }
int main(int argc, char const *argv[]) { //inicializacao if(initializeCommunication(argc, argv) != 0) exit(-1); //inicailizacao falhou putdebug("inicialização completa\n"); //inicializar conjunto de ligacoes initializeConnectionSet(); int maxFd = curNode.fd; //descritor com valor mais elevado char buffer[BUFSIZE]; //buffer utilizado para fazer a leitura dos descritores int inputReady = 0; //indica se existe input disponivel para ler int quit = FALSE; while(!quit) { //reinicializar conjunto de fds de leitura FD_ZERO(&readFds); //adicionar ligacoes no conjunto de fds copySet(&readFds); //adicionar listen fd ao conjunto de fds FD_SET(curNode.fd, &readFds); //adicionar stdin ao conjunto de fds FD_SET(STDIN_FILENO, &readFds); putdebug("CurNode - ring: %d id: %d ip: %s port: %s fd: %d", curRing, curNode.id, curNode.ip, curNode.port, curNode.fd); putdebug("SucciNode - id: %d ip: %s port: %s fd: %d", succiNode.id, succiNode.ip, succiNode.port, succiNode.fd); putdebug("PrediNode - id: %d ip: %s port: %s fd: %d", prediNode.id, prediNode.ip, prediNode.port, prediNode.fd); if(maxFd < getMaxConnection()) { maxFd = getMaxConnection(); } //esperar por descritor pronto para ler putmessage("\r> "); inputReady = select(maxFd + 1, &readFds, NULL, NULL, NULL); if(inputReady <= 0) { putdebugError("main", "select falhou"); continue; } if(FD_ISSET(curNode.fd, &readFds)) { //testar se o listen fd esta pronto para leitura struct sockaddr_in addr; socklen_t addrlen = sizeof(addr); bzero(&addr, addrlen); //aceitar ligacao int connectionFd; if( (connectionFd = accept(curNode.fd, (struct sockaddr*)&addr, &addrlen)) == -1) { putdebugError("main", "ligação não foi aceite"); } else { putdebug("nova ligação %d com endereço: %s", connectionFd, inet_ntoa(addr.sin_addr)); //adicionar descritor ao conjunto de descritores de ligacao addConnection(connectionFd); //definir um timeout para as comunicações struct timeval tv; tv.tv_sec = 5; setsockopt(connectionFd, SOL_SOCKET, SO_SNDTIMEO,(struct timeval *)&tv,sizeof(struct timeval)); setsockopt(connectionFd, SOL_SOCKET, SO_RCVTIMEO,(struct timeval *)&tv,sizeof(struct timeval)); } } if(FD_ISSET(STDIN_FILENO, &readFds)) { //testar se o utilizador executou um comando //ler comando do utilizador bzero(buffer, sizeof(buffer)); if(fgets(buffer, BUFSIZE, stdin) != NULL) { //executar comando do utilizador putdebug("processar comando do utilizador"); int errorCode = executeUserCommand(buffer); switch(errorCode) { case 0: putdebug("comando de utilizador processado com sucesso"); break; case -1: putdebugError("main", "falha no processamento do comando de utilizador"); break; case 1: { putmessage("programa vai sair\n"); //fechar todos os sockets int fd = getFirstConnection(); while(fd >= 0) { close(fd); rmConnection(fd); //proxima ligacao fd = getNextConnection(fd); } //fechar socket de escuta e socket do servidor de arranque closeSockets(); quit = TRUE; continue; } } } } //ler fds de ligacoes actuais com o nó int connectionFd = getFirstConnection(); while(connectionFd >= 0) { if(FD_ISSET(connectionFd, &readFds)) { //limpar buffer de rececao bzero(buffer, sizeof(buffer)); //ler mensagem if(readMessage(connectionFd, buffer, sizeof(buffer)) <= 0) { close(connectionFd); //fechar ligacao rmConnection(connectionFd); //remover no do conjunto de ligacoes putdebug("ligacao %d terminada", connectionFd); if(connectionFd == prediNode.fd) { prediNode.fd = -1; prediNode.id = -1; putdebug("ligação terminada com predi"); if(succiNode.fd == -1 && !iAmStartNode) { //estou sozinha mas não sou o nó de arranque //isto significa que houve uma saida abrupta //registar num novo anel if(registerNewRing() == -1) { putdebugError("handleEND", "não foi possível registar novo anel"); return -1; } } } if(connectionFd == succiNode.fd) { succiNode.fd = -1; succiNode.id = -1; putdebug("ligação terminada com succi"); //colocar um alarme de 2 segundos para garnatir que todas as ligações //que são par ser terminadas têm efeito no estado do nó signal(SIGALRM, rebuildSignal); alarm(REBUILD_INTERVAL); } } else { //tratar mensagem recebida putdebug("mensagem recebida pela ligacao %d: %s", connectionFd, buffer); //remover \n int length = strlen(buffer); if(buffer[length - 1] == '\n') buffer[length - 1] = '\0'; if(strcmp(buffer, "ERROR") == 0) { //houve um erro na comunicação TCP puterror("ocorreu um erro na comunicação entre nós\n"); closeConnection(&connectionFd); continue; } if(handleMessage(buffer, connectionFd) == -1) { //notificar quem enviou o pedido que ocorreu um erro char answer[] = "ERROR\n"; sendMessage(connectionFd, answer); if(connectionFd == prediNode.fd) { prediNode.fd = -1; prediNode.id = -1; putdebug("ligação terminada com predi por causa de erro"); } if(connectionFd == succiNode.fd) { succiNode.fd = -1; succiNode.id = -1; putdebug("ligação terminada com succi por causa de erro"); } //terminar ligacao closeConnection(&connectionFd); } } } //proxima ligacao connectionFd = getNextConnection(connectionFd); } } return 0; }
void take_message(void) { int bytes; int i; MESG * md; for (EVER) { /* not really forever...returns are in the loop */ if ((md = mlisten()) == NULL) switch(errno) { case EAGAIN: case EINTR: return; case ENOMEM: mallocfail(); /* NOTREACHED */ default: fail ("Unexpected streams error in mlisten (%s).\n" , PERROR); } /* * Check for a dropped connection to a child. * Normally a child should tell us that it is dying * (with S_SHUTDOWN or S_SEND_CHILD), but it may have * died a fast death. We'll simulate the message we * wanted to get so we can use the same code to clean up. */ if ((md->event & POLLHUP) && !(md->event & POLLIN) || (md->event & (POLLERR|POLLNVAL))) { switch (md->type) { case MD_CHILD: /* * If the message descriptor is found in the * exec table, it must be an interface pgm, * notification, etc. Otherwise, it must be * a network child. */ for (i = 0; Exec_Table[i] != NULL; i++) if (Exec_Table[i]->md == md) break; if (Exec_Table[i] != NULL) { (void) putmessage(Message, S_CHILD_DONE, Exec_Table[i]->key, 0, 0); } else { (void) putmessage(Message, S_SHUTDOWN, 1); } bytes = 1; break; default: bytes = -1; break; } } else { if (md->readfd == -1) { /* something happened to the readfd */ syslog(LOG_DEBUG, "take_message: readfd is -1"); return; } bytes = mread(md, Message, MSGMAX); } switch (bytes) { case -1: if (errno == EINTR) return; else fail ("Unexpected streams error (%s).\n" , PERROR); break; case 0: break; default: if (do_msg(md)) return; break; } } }