int leader_handle_remove_neighbour(gossip_node_t* neighbour) { if (neighbour->id == leader) { // Leader was removed from neighbour table; start a new election // round election_round++; // This obviously won't work as intended as of now; // leader_elect() needs to be a thread. But this is the general // idea. leader_init(); } return 1; }
//This function is invoked when a new message is ready to be read // from the leader election oracle UDP socket static void pro_handle_oracle_msg(int sock, short event, void *arg) { //Make the compiler happy! UNUSED_ARG(sock); UNUSED_ARG(event); UNUSED_ARG(arg); assert(sock == from_oracle->sock); //Read the next message int valid = udp_read_next_message(from_oracle); if (valid < 0) { printf("Dropping invalid oracle message\n"); return; } //The message is valid, take the appropriate action // based on the type paxos_msg * msg = (paxos_msg*) &from_oracle->recv_buffer; switch(msg->type) { case leader_announce: { leader_announce_msg * la = (leader_announce_msg *)msg->data; if(LEADER_IS_ME && la->current_leader != this_proposer_id) { //Some other proposer was nominated leader instead of this one, // step down from leadership leader_shutdown(); } else if (!LEADER_IS_ME && la->current_leader == this_proposer_id) { //This proposer has just been promoted to leader leader_init(); } current_leader_id = la->current_leader; } break; default: { printf("Unknow msg type %d received from oracle\n", msg->type); } } }
//Proposer initialization, this function is invoked by // the underlying learner after it's normal initialization static int init_proposer() { //Add network events and prepare send buffer if(init_pro_network() != 0) { printf("Proposer network init failed\n"); return -1; } //Add additional timers to libevent loop if(init_pro_fd_events() != 0){ printf("Proposer timers init failed\n"); return -1; } //Normal proposer initialization, private structures if(init_pro_structs() != 0) { printf("Proposer structs init failed\n"); return -1; } //By default, proposer 0 starts as leader, // later on the failure detector may change that if(LEADER_IS_ME) { if(leader_init() != 0) { printf("Proposer Leader init failed\n"); return -1; } } //Call custom init (i.e. to register additional events) if(client_custom_init != NULL && client_custom_init() != 0) { printf("Error in client_custom_init\n"); return -1; } else { LOG(DBG, ("Custom init completed\n")); } return 0; }
/* * Place a swarm at start with a number of leaders that all have * the same initial velocity. */ Swarm *swarm_create(Point *start, Vector *initVel, Module *shape, int numLeaders, int numActorsPerLeader, float spread){ int i, j, id = 0, verbose = 1; float genX, genY, genZ; if(verbose) printf("creating swarm\n"); Swarm *s = malloc(sizeof(Swarm)); s->leaders = malloc(sizeof(Leader)*numLeaders); s->actors = malloc(sizeof(Actor)*numActorsPerLeader*numLeaders); s->numActors = numActorsPerLeader*numLeaders; s->numLeaders = numLeaders; for(i=0; i<numLeaders; i++){ genX = spread - ((double)rand() / RAND_MAX) * 2.0 * spread; genY = spread - ((double)rand() / RAND_MAX) * 2.0 * spread; genZ = spread - ((double)rand() / RAND_MAX) * 2.0 * spread; leader_init(&(s->leaders[i]), shape); leader_setLocation(&(s->leaders[i]), start->val[0] + genX, start->val[1] + genY, start->val[2] + genZ); leader_setVelocity(&(s->leaders[i]), initVel); for(j=0; j<numActorsPerLeader; j++){ genX = spread - ((double)rand() / RAND_MAX) * 2.0 * spread; genY = spread - ((double)rand() / RAND_MAX) * 2.0 * spread; genZ = spread - ((double)rand() / RAND_MAX) * 2.0 * spread; actor_init(&(s->actors[j+(i*numActorsPerLeader)]), &(s->leaders[i]), shape); actor_setLocation(&(s->actors[j+(i*numActorsPerLeader)]), start->val[0] + genX, start->val[1] + genY, start->val[2] + genZ); actor_setID(&(s->actors[j+(i*numActorsPerLeader)]), id++); } } return s; }
void leader_handle_msg(void* msg_text, size_t size, uint16_t src){ uint16_t received_leader; uint16_t round; gossip_node_t* node; char round_buffer[3]; int len = strlen(PREAMBLE) + strlen(MSG) + strlen(LE) + size; char* msg_buffer; msg_buffer = malloc(len); memset(msg_buffer, 0, len); DEBUG("D: received msg of size %d\n",size); /* we received something, that means LE started */ leader_set_initialized(1); strncpy( round_buffer, (char*)msg_text+strlen(LE) , sizeof(round_buffer) ); round = atol(round_buffer); DEBUG("D: got round %i (current round %i)\n",round,election_round); // a new election round, invalidate leader and elect the next one if(round > election_round) { // TODO: fix possible overflow DEBUG("D: got new election round %i (was %i)\n",round,election_round); election_round = round; leader_init(); free(msg_buffer); return; } // got leader from an old round, inform sending node if(round < election_round) { // TODO: fix possible overflow DEBUG("D: got round %i (current is %i) informing sender\n",round,election_round); sprintf(msg_buffer, "%s%s%s%0" ROUND_LEN_STR "i%0" UID_LEN_STR "i", PREAMBLE, MSG, LE, election_round, leader); node = gossip_find_node_by_id(src); gossip_send(node, msg_buffer, strlen(msg_buffer)); free(msg_buffer); return; } received_leader = atol((char*)msg_text+strlen(LE)+UID_LEN); DEBUG("D: received candidate: %i\n",received_leader); /* XXX: misuse MAX_UID as ACK identifier */ if(received_leader == MAX_UID){ free(msg_buffer); return; } // TODO: add custom metrics functions here instead of a<b if(received_leader < leader ){ DEBUG("D: discarding candidate and informing sender\n"); sprintf(msg_buffer, "%s%s%s%0" ROUND_LEN_STR "i%0" UID_LEN_STR "i", PREAMBLE, MSG, LE, round, leader); } // update leader if we receive a better candidate if(received_leader >= leader ){ DEBUG("D: adding a new, better leader\n"); leader_set_leader(received_leader); sprintf(msg_buffer, "%s%s%s%0" ROUND_LEN_STR "i%0" UID_LEN_STR "i", PREAMBLE, MSG, LE, round, MAX_UID); } node = gossip_find_node_by_id(src); DEBUG("D: sending msg of size %d\n",strlen(msg_buffer)); gossip_send(node, msg_buffer, strlen(msg_buffer)); free(msg_buffer); }