static void markInterestingNodes(Node * node) { Connection *connect; Node *destination; MiniConnection *localConnect; Coordinate min_distance = getNodeLength(node) / 2 - BACKTRACK_CUTOFF; // Mark own node setEmptyMiniConnection(node); // Loop thru primary scaffold for (connect = getConnection(node); connect != NULL; connect = getNextConnection(connect)) { destination = getTwinNode(getConnectionDestination(connect)); localConnect = &localScaffold[getNodeID(destination) + nodeCount(graph)]; if (getNodeStatus(destination)) { readjustMiniConnection(destination, localConnect, getConnectionDistance(connect), min_distance, getConnectionVariance(connect), connect, NULL); localConnect->backReference = NULL; } else { resetMiniConnection(destination, localConnect, getConnectionDistance(connect), getConnectionVariance(connect), connect, NULL, true); } integrateDerivativeDistances(connect, min_distance, true); } // Loop thru twin's primary scaffold for (connect = getConnection(getTwinNode(node)); connect != NULL; connect = getNextConnection(connect)) { destination = getConnectionDestination(connect); localConnect = &localScaffold[getNodeID(destination) + nodeCount(graph)]; if (getNodeStatus(destination)) readjustMiniConnection(destination, localConnect, -getConnectionDistance(connect), min_distance, getConnectionVariance(connect), NULL, connect); else resetMiniConnection(destination, localConnect, -getConnectionDistance(connect), getConnectionVariance(connect), NULL, connect, -1); integrateDerivativeDistances(connect, min_distance, false); } }
static void extendComponentFromNode(Node * node) { Connection *connect; //velvetLog("Extending from node %li\n", (long) getNodeID(node)); for (connect = getConnection(node); connect; connect = getNextConnection(connect)) extendComponentToNode(getTwinNode (getConnectionDestination(connect))); for (connect = getConnection(getTwinNode(node)); connect; connect = getNextConnection(connect)) extendComponentToNode(getConnectionDestination(connect)); }
static void propagateComponent(Node * node) { Connection *connect; if (getNodeStatus(node) || !getUniqueness(node)) return; setNodeStatus(node, true); for (connect = getConnection(node); connect != NULL; connect = getNextConnection(connect)) propagateComponent(getConnectionDestination(connect)); for (connect = getConnection(getTwinNode(node)); connect != NULL; connect = getNextConnection(connect)) propagateComponent(getConnectionDestination(connect)); }
static void fillUpComponent(Node * node) { Connection *connect; if (getNodeStatus(node) || !getUniqueness(node)) return; setSingleNodeStatus(node, true); recordNode(node); for (connect = getConnection(node); connect != NULL; connect = getNextConnection(connect)) fillUpComponent(getTwinNode (getConnectionDestination(connect))); for (connect = getConnection(getTwinNode(node)); connect != NULL; connect = getNextConnection(connect)) fillUpComponent(getConnectionDestination(connect)); }
static void setNodeConnectionStatus(Node * node, boolean status) { Connection *connect; for (connect = getConnection(node); connect; connect = getNextConnection(connect)) if (getNodeStatus (getTwinNode(getConnectionDestination(connect)))) setConnectionStatus(connect, status); }
Connection *getReverseActiveConnection(Node * node) { Connection *connect; for (connect = getConnection(getTwinNode(node)); connect; connect = getNextConnection(connect)) if (getNodeStatus(getConnectionDestination(connect))) return connect; return NULL; }
static IDnum getReverseDegree(Node * node) { Connection *connect; IDnum counter = 0; for (connect = getConnection(node); connect; connect = getNextConnection(connect)) if (getNodeStatus(getConnectionDestination(connect))) counter++; return counter; }
static boolean hasNoActiveConnections(Node * node) { Connection *connect; for (connect = getConnection(node); connect; connect = getNextConnection(connect)) if (getNodeStatus (getTwinNode(getConnectionDestination(connect)))) return false; return true; }
static void recenterNode(Node * node, Coordinate oldLength) { IDnum nodeID = getNodeID(node); Connection *connect, *next; Coordinate distance_shift = (getNodeLength(node) - oldLength) / 2; Coordinate min_distance = getNodeLength(node) / 2 - BACKTRACK_CUTOFF; MiniConnection *localConnect; //velvetLog("Recentering node\n"); for (connect = getConnection(node); connect != NULL; connect = next) { next = getNextConnection(connect); incrementConnectionDistance(connect, -distance_shift); if (getConnectionDistance(connect) < min_distance) { //velvetLog("Unrecording %li\n", // -getNodeID(getConnectionDestination(connect))); localConnect = &localScaffold[-getNodeID(getConnectionDestination(connect)) + nodeCount(graph)]; localConnect->frontReference = NULL; unmarkNode(getTwinNode(getConnectionDestination(connect)), localConnect); destroyConnection(connect, nodeID); } else if (getTwinConnection(connect) != NULL) incrementConnectionDistance(getTwinConnection(connect), -distance_shift); } for (connect = getConnection(getTwinNode(node)); connect != NULL; connect = next) { next = getNextConnection(connect); incrementConnectionDistance(connect, distance_shift); if (getTwinConnection(connect) != NULL) incrementConnectionDistance(getTwinConnection(connect), distance_shift); } }
static Connection *getSecondReverseActiveConnection(Node * node) { Connection *connect; boolean firstFound = false; for (connect = getConnection(getTwinNode(node)); connect; connect = getNextConnection(connect)) { if (getNodeStatus(getConnectionDestination(connect))) { if (firstFound) return connect; else firstFound = true; } } return false; }
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; }
static void integrateDerivativeDistances(Connection * connect, Coordinate min_distance, boolean direction) { Node *reference = getConnectionDestination(connect); Node *destination; IDnum destinationID; Coordinate distance, baseDistance; double variance, baseVariance; Connection *connect2; MiniConnection *localConnect; // debug IDnum counter = 0; if (!getUniqueness(reference)) return; //velvetLog("Opposite node %li length %li at %li ± %f\n", getNodeID(reference), getNodeLength(reference), getConnectionDistance(connect), getConnectionVariance(connect)); baseDistance = getConnectionDistance(connect); baseVariance = getConnectionVariance(connect); for (connect2 = getConnection(reference); connect2 != NULL; connect2 = getNextConnection(connect2)) { // Avoid null derivative if (connect2 == getTwinConnection(connect)) continue; destination = getConnectionDestination(connect2); // Beware of directionality if (!direction) destination = getTwinNode(destination); // Derivate values destinationID = getNodeID(destination); // Beware of directionality (bis) if (direction) distance = baseDistance - getConnectionDistance(connect2); else distance = getConnectionDistance(connect2) - baseDistance; variance = getConnectionVariance(connect2) + baseVariance; localConnect = &localScaffold[destinationID + nodeCount(graph)]; // Avoid over-projection if (distance < min_distance) { //velvetLog("Node %li not at distance %li± %f (min %li)\n", destinationID, distance, variance, min_distance); continue; } counter++; if (getNodeStatus(destination)) { readjustMiniConnection(destination, localConnect, distance, min_distance, variance, NULL, NULL); } else resetMiniConnection(destination, localConnect, distance, variance, NULL, NULL, true); //velvetLog("Node %li now at distance %li\n", destinationID, localConnect->distance); } //velvetLog("%li secondary distances added\n", counter); }