//Opens instances at the "end" of the proposer state array //Those instances were not opened before static void leader_open_instances_p1() { int active_count = p1_info.pending_count + p1_info.ready_count; assert(active_count >= 0); if(inf_prepare_info.status == empty) { //Ask for infinite p1 instances //Create an empty prepare batch in send buffer sendbuf_clear(to_acceptors, prepare_reqs, this_proposer_id); //Send prepare to acceptors sendbuf_add_prepare_req(to_acceptors, INF_PREPARE_REQ, FIRST_BALLOT); //Send if something is still there sendbuf_flush(to_acceptors); //Keep track of pending count inf_prepare_info.status = p1_pending; inf_prepare_info.my_ballot = FIRST_BALLOT; LOG(DBG, ("Opened %d new instances\n", 1)); return; } }
/*发送prepare_req到所有的acceptor进行第一阶段的提议*/ static void send_prepares(struct evproposer* p, prepare_req* pr) { int i; for(i = 0; i < peers_count(p->acceptors); i ++){ struct bufferevent* bev = peers_get_buffer(p->acceptors, i); sendbuf_add_prepare_req(bev, pr); } }
static void leader_check_p1_pending() { iid_t iid_iterator; p_inst_info * ii; //Create an empty prepare batch in send buffer sendbuf_clear(to_acceptors, prepare_reqs, this_proposer_id); LOG(DBG, ("Checking pending phase 1 from %lu to %lu\n", current_iid, p1_info.highest_open)); //Get current time for checking expired struct timeval time_now; gettimeofday(&time_now, NULL); for(iid_iterator = current_iid; iid_iterator <= p1_info.highest_open; iid_iterator++) { //Get instance from state array ii = GET_PRO_INSTANCE(iid_iterator); assert(ii->iid == iid_iterator); //Still pending -> it's expired if(ii->status == p1_pending && leader_is_expired(&ii->timeout, &time_now)) { LOG(DBG, ("Phase 1 of instance %ld expired!\n", ii->iid)); //Reset fields used for previous phase 1 ii->promises_bitvector = 0; ii->promises_count = 0; ii->p1_value_ballot = 0; if(ii->p1_value != NULL) { PAX_FREE(ii->p1_value); } ii->p1_value = NULL; //Ballot is incremented ii->my_ballot = NEXT_BALLOT(ii->my_ballot); //Send prepare to acceptors sendbuf_add_prepare_req(to_acceptors, ii->iid, ii->my_ballot); leader_set_expiration(ii, P1_TIMEOUT_INTERVAL); COUNT_EVENT(p1_timeout); } } //Send if something is still there sendbuf_flush(to_acceptors); }
static void leader_periodic_p2_check(int fd, short event, void *arg) { UNUSED_ARG(fd); UNUSED_ARG(event); UNUSED_ARG(arg); // create a prepare batch for expired instances sendbuf_clear(to_acceptors, prepare_reqs, this_proposer_id); struct timeval now; gettimeofday(&now, NULL); // from current to highest open, check deadline // if instances in status p2_pending iid_t i; p_inst_info * ii; for(i = current_iid; i < p2_info.next_unused_iid; i++) { ii = GET_PRO_INSTANCE(i); //Not p2_pending, skip if(ii->status != p2_pending) { continue; } //Check if it was closed in the meanwhile // (but not delivered yet) if(learner_is_closed(i)) { ii->status = p2_completed; p2_info.open_count -= 1; //The rest (i.e. answering client) // is done when the value is actually delivered LOG(VRB, ("Instance %lu closed, waiting for deliver\n", i)); continue; } //Not expired yet, skip if(!leader_is_expired(&ii->timeout, &now)) { continue; } //Expired and not closed: must restart from phase 1 ii->status = p1_pending; p1_info.pending_count += 1; ii->my_ballot = NEXT_BALLOT(ii->my_ballot); //Send prepare to acceptors sendbuf_add_prepare_req(to_acceptors, ii->iid, ii->my_ballot); leader_set_expiration(ii, P1_TIMEOUT_INTERVAL); LOG(VRB, ("Instance %lu restarts from phase 1\n", i)); COUNT_EVENT(p2_timeout); } //Flush last message if any sendbuf_flush(to_acceptors); //Open new instances leader_open_instances_p2_new(); //Set next invokation of this function leader_set_next_p2_check(); }