📄 leader.cc
字号:
break; case LEADER_FEEDBACK : if (_DEBUG_) printf("%d receive CONFIRM (FEEDBACK) from %d\n", myAddress, from); timer->cancelFeedback(from, cm.round); break; case LEADER_ACTION : timer->cancelAction(from, cm.round); break; }}//// Procedura di gestione del messaggio ACTION.//voidLEADER_Agent::receive_ACTION(NodeAddress from, struct ActionMessage action){ if (_DEBUG_) printf("%d receive ACTION (FROM=%d)\n", myAddress, from); // Azzera l'identita'del nuovo frammento a cui legarsi. leData.action_for_round[leData.round] = true; // Il nodo non e'piu'candidato leData.candidate = false; // // Se lo stored path non e'impostato, il nodo e'di tipo edge e deve legarsi // al frammento massimale precedentemente calcolato. // // FIXME: non sono sicuro se ci va il -1 if (leData.stored_path[leData.round - 1] == -1) { // Imposta il genitore // FIXME insieme a quello a processLEStatus // leData.old_fragment_identity = leData.fragment.ID; // FIXME: Non sono sicuro se ci deve stare il -1 leData.tree.parent = leData.maximal_fragment_node[leData.round - 1]; leData.fragment.ID = leData.maximal_fragment[leData.round - 1].ID; if (_DEBUG_) printf("%d JOIN to %d\n", myAddress, leData.maximal_fragment_node[leData.round - 1]); // // Se il messaggio di INFO da parte del genitore a cui un "edge_node" // si e'legato e'stato ricevuto prima dell'arrivo del messaggio di ACTION, // da parte del candidato per il proprio frammento, // viene simulata la ricezione. // Il criterio non si applica al round 0. // // if (leData.round != 0) { if (leData.maximal_fragment_node_info_message[leData.round].round != -1) if (!isInfoInBuffer(leData.round)) { // Il nodo non aveva ancora mai inviato il messaggio di INFO per // questo round: il nodo nel round precendente si e'legato al frammento di // quel nodo tramite esso. // La vecchia identita'del nodo e'gia'impostata correttamente. // La nuova identita'viene agggiornata per quanto riguarda la dimensione del // frammento. // Il nodo edge legato invia un messaggio di INFO con la dimensione dettatagli // dal frammento a cui e'legato. leData.fragment = leData.maximal_fragment_node_info_message[leData.round].new_fragment; send_INFO(leData.old_fragment_identity, leData.fragment.ID, leData.fragment.size, leData.stored_path[leData.round - 1]); } // } } else { // Se il nodo che riceve il messaggio di ACTION // lo deve propagare allora non deve memorizzare il genitore. leData.tree.parent = -1; send_ACTION (leData.fragment.ID, leData.stored_path[leData.round - 1]); // leData.stored_path = -1; }}//// Procedura di gestione dei messaggi LEADER:// voidLEADER_Agent::receive_LEADER(NodeAddress from, struct LeaderMessage lm, NodeAddress to){ if (_DEBUG_) printf("%d receive LEADER (FROM=%d, PARENT=%d, SIZE=%d, LEVEL=%d)\n", myAddress, from, lm.parent, lm.leader.size, lm.level); // // Se il nodo e'gia'in fase di leader election. // if (status == LEADER_STATUS_LEADER) { // Elimina il timeout del messaggio LEADER. timer->cancelLeader(from); // Elimina il nodo dalla lista di coloro che devono inviare un messaggio INFO. leData.leader_messages.erase(from); // Memorizza il livello del vicino. leData.levels[from] = lm.level; // Il mittente imposta il nodo come genitore. if (lm.parent == myAddress) // Aggiorna la lista dei figli. leData.childs.insert(from); } else { // Il nodo riceve il primo messaggio di LEADER: imposta lo stato status = LEADER_STATUS_LEADER; // Memorizza il livello del vicino. leData.levels[from] = lm.level; // Forza a non essere candidato: FIXME leData.candidate = false; // Imposta la lista dei vicini dai quali deve ricevere messaggi di Leader. leData.leader_messages = neighbors; leData.leader_messages.erase(from); // Genitore leData.parent = from; // Numero di nodi della topologia. leData.tree_size = lm.leader.size; // Livello nell'albero leData.level = lm.level + 1; // Leader. leData.leader = lm.leader.ID; // Childs leData.childs.clear(); // Invia il messaggio di LEADER. send_LEADER(leData.leader, leData.tree_size, leData.parent, leData.level); // Inizializza i timeout verso i vicini restanti (escluso il genitore) timer->launchLeaderTimeouts(leData.leader_messages); } if (!leData.leader_messages.empty()) return; // End Procedure. endModule();}//// Questa procedura viene chiamata al termine del ciclo di FEEDBACK:// il nodo, se non e'leader propaga l'informazione sui frammenti massimali adiacenti// al proprio genitore; se e'leader decide la sorte del frammento (legarsi al frammento// vicino massimale oppure no).//voidLEADER_Agent::processLEStatus() { if (_DEBUG_) printf("%d -- PROCESS --\n", myAddress); int X = 2; // // Per il primo round, ogni nodo che sia il piu'piccolo del suo vicinato, // si lega al piu'grande vicino. Tutti gli altri rimangono leader. // if (leData.round == 0) { if (_DEBUG_) printf("%d (SIZE=%d == MAX=%d)\n", myAddress, leData.fragment.size, leData.maximal_fragment[leData.round].size); NodeAddress minimo = *min_element(neighbors.begin(), neighbors.end()); if (myAddress < minimo) { // Il nodo si lega al nodo massimo. // Se la grandezza del frammento corrente e'minore al frammento // vicino massimale, allora il frammento si lega al frammento massimale. if (utility) ((LeaderUtility*)utility)->addJoin(leData.fragment.ID, leData.maximal_fragment[leData.round].ID); // Avanza di round. leData.round++; // Memorizza un messaggio nullo. struct InfoMessage im; im.round = -1; leData.maximal_fragment_node_info_message[leData.round] = im; leData.action_for_round[leData.round] = false; // Invia il messaggio di ACTION. struct ActionMessage am; am.current_fragment = leData.fragment; receive_ACTION(myAddress, am); // Inizia un nuovo ciclo di ricezione dei messaggi INFO. init_INFO_cycle(false); return; } else { // Rimane leader if (_DEBUG_) printf("%d rimane LEADER\n", myAddress); // Avanza di round. leData.round++; // Memorizza un messaggio nullo. struct InfoMessage im; im.round = -1; leData.maximal_fragment_node_info_message[leData.round] = im; leData.action_for_round[leData.round] = false; // Invia il nuovo messaggio di INFO. leData.old_fragment_identity = leData.fragment.ID; send_INFO(leData.fragment.ID, leData.fragment.ID, leData.fragment.size, -1); // Inizia un nuovo ciclo di ricezione dei messaggi INFO. init_INFO_cycle(); return; } } if (leData.candidate) { // Il nodo e'un candidato // Aggiorna la descrizione del frammento. leData.fragment.size = leData.sub_tree_partial_count + 1; if (!leData.maximal_fragment_available[leData.round]) { if (_DEBUG_) printf("\t\t\t%d e'il LEADER\n", myAddress); beginLeaderPropagation(); return; } if (leData.fragment.size >= X * leData.maximal_fragment[leData.round].size) { if (_DEBUG_) printf("%d (SIZE=%d > MAX=%d)\n", myAddress, leData.fragment.size, leData.maximal_fragment[leData.round].size); // Se la grandezza del frammento corrente e'maggiore o uguale al frammento // vicino massimale, allora il nodo rimane candidato. if (_DEBUG_) printf("%d rimane LEADER\n", myAddress); // Avanza di round. leData.round++; // Memorizza un messaggio nullo. struct InfoMessage im; im.round = -1; leData.maximal_fragment_node_info_message[leData.round] = im; leData.action_for_round[leData.round] = false; // Invia il nuovo messaggio di INFO. leData.old_fragment_identity = leData.fragment.ID; send_INFO(leData.fragment.ID, leData.fragment.ID, leData.fragment.size, -1); // Inizia un nuovo ciclo di ricezione dei messaggi INFO. init_INFO_cycle(); return; } else if (leData.fragment < leData.maximal_fragment[leData.round]) { if (_DEBUG_) printf("%d (SIZE=%d < MAX=%d)\n", myAddress, leData.fragment.size, leData.maximal_fragment[leData.round].size); // Se la grandezza del frammento corrente e'minore al frammento // vicino massimale, allora il frammento si lega al frammento massimale. if (utility) ((LeaderUtility*)utility)->addJoin(leData.fragment.ID, leData.maximal_fragment[leData.round].ID); // Avanza di round. leData.round++; // Memorizza un messaggio nullo. struct InfoMessage im; im.round = -1; leData.maximal_fragment_node_info_message[leData.round] = im; leData.action_for_round[leData.round] = false; // Propaga un messaggio di ACTION verso il nodo di JOIN struct ActionMessage am; am.current_fragment = leData.fragment; am.round = leData.round; receive_ACTION(myAddress, am); // Inizia un nuovo ciclo di ricezione dei messaggi INFO. init_INFO_cycle(false); return; } else { if (_DEBUG_) printf("%d (MAX=%d <= SIZE=%d <= X*MAX )\n", myAddress, leData.maximal_fragment[leData.round].size, leData.fragment.size); // In tutti gli altri casi il frammento rimane candidato. if (_DEBUG_) printf("%d rimane LEADER\n", myAddress); // Avanza di round. leData.round++; // Memorizza un messaggio nullo. struct InfoMessage im; im.round = -1; leData.maximal_fragment_node_info_message[leData.round] = im; leData.action_for_round[leData.round] = false; // Invia il nuovo messaggio di INFO. leData.old_fragment_identity = leData.fragment.ID; send_INFO(leData.fragment.ID, leData.fragment.ID, leData.fragment.size, -1); // Inizia un nuovo ciclo di ricezione dei messaggi INFO. init_INFO_cycle(); return; } } else { // Il nodo non e'candidato invia al genitore le informazioni // sul frammento adiacente massimale. send_FEEDBACK (leData.tree.parent, leData.fragment.ID, leData.maximal_fragment_available[leData.round], leData.maximal_fragment[leData.round].ID, leData.maximal_fragment[leData.round].size, leData.sub_tree_partial_count + 1); timer->launchFeedbackTimeouts(leData.tree.parent, leData.round); // Avanza di round. leData.round++; // Memorizza un messaggio nullo. struct InfoMessage im; im.round = -1; leData.maximal_fragment_node_info_message[leData.round] = im; leData.action_for_round[leData.round] = false; // Inizia un nuovo ciclo di ricezione dei messaggi INFO. // FIXME: e'necessario impostare il vecchio ? leData.old_fragment_identity = leData.fragment.ID; init_INFO_cycle(); return; } }//// Aggiorna la situazione del frammento vicino massimale://voidLEADER_Agent::updateMaximalFragment(NodeAddress from, struct FeedbackMessage feedback){ // Il messaggio di feedback segnala che il nodo mittente non conosce alcun frammento massimale. if (!feedback.maximal_fragment_available) return; // Se il nodo non possiede alcuna informazione su frammenti massimali: // il frammento descritto dal messaggio FEEDBACK diventa il frammento vicino massimale. if (!leData.maximal_fragment_available[leData.round]) { leData.maximal_fragment_available[leData.round] = true; leData.maximal_fragment[leData.round] = feedback.maximal_fragment; // FIXME non so se si deve impostare leData.maximal_fragment_node[leData.round] = -1; leData.stored_path[leData.round] = from; return; } // Il nodo ha gia'un frammento massimale memorizzato: // se il frammento massimale che conosce e'minore di quello inviato // allora memorizza il frammento inviato. if (leData.maximal_fragment[leData.round] < feedback.maximal_fragment) { leData.maximal_fragment[leData.round] = feedback.maximal_fragment; // FIXME non so se si deve impostare leData.maximal_fragment_node[leData.round] = -1; leData.stored_path[leData.round] = from; return; }} //// Aggiorna la situazione del frammento vicino massimale:// Si assume che il messaggio di info provenga da un frammento differente.//voidLEADER_Agent::updateMaximalFragment(NodeAddress from, struct InfoMessage info){ // Se il nodo non possiede alcuna informazione su frammenti massimali: // il frammento descritto dal messaggio INFO diventa il frammento vicino massimale. if (!leData.maximal_fragment_available[leData.round]) { leData.maximal_fragment_available[leData.round] = true; leData.maximal_fragment[leData.round] = info.new_fragment; leData.maximal_fragment_node[leData.round] = from; leData.stored_path[leData.round] = -1; return; } // Il nodo ha gia'un frammento massimale memorizzato: // se il frammento massimale che conosce e'minore di quello inviato // allora memorizza il frammento inviato. if (leData.maximal_fragment[leData.round] < info.new_fragment) { leData.maximal_fragment[leData.round] = info.new_fragment; leData.maximal_fragment_node[leData.round] = from; leData.stored_path[leData.round] = -1; return; }}void LEADER_Agent::timeout(LeaderMessageType type, NodeAddress from, int round){ switch (type) { case LEADER_INFO: if (_DEBUG_) printf("------ %d timeout INFO (ROUND=%d) from %d ------\n", myAddress, round, from); // Nuovo CONFIRM: da modificare. send_INFO(leData.stored_messages.info[round].fragment.ID, leData.stored_messages.info[round].new_fragment.ID, leData.stored_messages.info[round].new_fragment.size, leData.stored_messages.info[round].parent, leData.stored_messages.info[round].round, from); /* send_REQUEST(from, LEADER_INFO, leData.round); */ break; case LEADER_FEEDBACK: if (_DEBUG_) printf("------ %d timeout FEEDBACK (ROUND=%d) from %d ------\n", myAddress, round, from); // Invia nuovamente il feedback bufferizzato. struct FeedbackMessage fm; for (BufferFeedbackMessages::iterator i = leData.stored_messages.feedback.begin(); i != leData.stored_messages.feedback.end(); i++) { if (i->first == round) { fm = i->second; send_FEEDBACK(from, fm.fragment.ID, fm.maximal_fragment_available, fm.maximal_fragment.ID, fm.maximal_fragment.size, fm.node_count, round); } } break; case LEADER_ACTION:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -