Ejemplo n.º 1
0
/**
 * acceptor_ack_refuse - Resolve an acceptor's claim that we do not know
 * the true proposer.
 *
 * If we send a request to someone who is not the proposer, but identifying
 * them as the proposer, we will receive a refuse.  Since the correctness
 * of the Paxos protocol guarantees that the acceptor list has a consistent
 * total ordering across the system, receiving a refuse means that there is
 * someone more fitting to be proposer than the acceptor we identified.
 *
 * Note, as with ack_redirect, that it is possible we noticed a proposer
 * failure and sent our request to the new proposer correctly before the new
 * proposer themselves recognized the failure.
 */
int
acceptor_ack_refuse(struct paxos_header *hdr, msgpack_object *o)
{
  int r;
  msgpack_object *p;
  struct paxos_acceptor *acc;
  struct paxos_continuation *k;

  // Check whether, since we sent our request, we have already found a more
  // suitable proposer, possibly due to another redirect, in which case we
  // can ignore this one.
  if (pax->proposer->pa_paxid <= hdr->ph_inum) {
    return 0;
  }

  // Pull out the acceptor struct corresponding to the purported proposer and
  // try to reconnect.  Note that we should have already set the pa_peer of
  // this acceptor to NULL to indicate the lost connection.
  acc = acceptor_find(&pax->alist, hdr->ph_inum);
  assert(acc->pa_peer == NULL);

  // Defer computation until the client performs connection.  If it succeeds,
  // resend the request.  We bind the request ID as callback data.
  k = continuation_new(continue_ack_refuse, acc->pa_paxid);

  assert(o->type == MSGPACK_OBJECT_ARRAY);
  p = o->via.array.ptr + 1;
  paxos_value_unpack(&k->pk_data.req.pr_val, p++);

  ERR_RET(r, state.connect(acc->pa_desc, acc->pa_size, &k->pk_cb));
  return 0;
}
Ejemplo n.º 2
0
/**
 * paxos_ack_retrieve - Acknowledge a retrieve.
 *
 * This basically just unpacks and wraps a resend.
 */
int paxos_ack_retrieve(struct paxos_header *hdr, msgpack_object *o)
{
  paxid_t paxid;
  msgpack_object *p;
  struct paxos_value val;
  struct paxos_request *req;
  struct paxos_acceptor *acc;

  // Make sure the payload is well-formed.
  assert(o->type == MSGPACK_OBJECT_ARRAY);
  assert(o->via.array.size == 2);
  p = o->via.array.ptr;

  // Unpack the retriever's ID and the value being retrieved.
  paxos_paxid_unpack(&paxid, p++);
  paxos_value_unpack(&val, p++);

  // Retrieve the request.
  assert(request_needs_cached(val.pv_dkind));
  req = request_find(&pax->rcache, val.pv_reqid);
  if (req != NULL) {
    // If we have the request, look up the recipient and resend.
    acc = acceptor_find(&pax->alist, paxid);
    return paxos_resend(acc, hdr, req);
  } else {
    // If we don't have the request either, just return.
    return 0;
  }
}
Ejemplo n.º 3
0
void
paxos_request_unpack(struct paxos_request *req, msgpack_object *o)
{
  msgpack_object *p;

  // Make sure the input is well-formed.
  assert(o->type == MSGPACK_OBJECT_ARRAY);
  assert(o->via.array.size == 2);

  // Unpack the value.
  p = o->via.array.ptr;
  paxos_value_unpack(&req->pr_val, p++);

  // Unpack the raw data.
  assert(p->type == MSGPACK_OBJECT_RAW);
  req->pr_size = p->via.raw.size;
  req->pr_data = g_memdup(p->via.raw.ptr, p->via.raw.size);
}
Ejemplo n.º 4
0
void
paxos_instance_unpack(struct paxos_instance *inst, msgpack_object *o)
{
  msgpack_object *p;

  // Make sure the input is well-formed.
  assert(o->type == MSGPACK_OBJECT_ARRAY);
  assert(o->via.array.size == 3);

  p = o->via.array.ptr;

  // Unpack the header, committed flag, and value.
  paxos_header_unpack(&inst->pi_hdr, p++);
  assert(p->type == MSGPACK_OBJECT_BOOLEAN);
  inst->pi_committed = (p++)->via.boolean;
  paxos_value_unpack(&inst->pi_val, p++);

  // Set everything else to 0.
  inst->pi_cached = false;
  inst->pi_learned = false;
  inst->pi_votes = 0;
  inst->pi_rejects = 0;
}