Exemple #1
0
/* Inserts the given KEY, VALUE pair into this server's store
 * Returns 0 if successful, else a negative error code. */
int tpcfollower_put(tpcfollower_t *server, char *key, char *value) {
  int ret;
  if ((ret = tpcfollower_put_check(server, key, value)) < 0)
    return ret;
  ret = kvstore_put(&server->store, key, value);
  return ret;
}
Exemple #2
0
/* Handles an incoming kvrequest REQ, and populates RES as a response.  REQ and
 * RES both must point to valid kvrequest_t and kvrespont_t structs,
 * respectively. Assumes that the request should be handled as a TPC
 * message. This should also log enough information in the server's TPC log to
 * be able to recreate the current state of the server upon recovering from
 * failure. See the spec for details on logic and error messages.
 */
void tpcfollower_handle_tpc(tpcfollower_t *server, kvrequest_t *req, kvresponse_t *res) {
  /* TODO: Implement me! */

  if (req->type == DELREQ) {
    if (server->state != TPC_WAIT) {
      server->state = TPC_WAIT;
    } else {
      res->type = ERROR;
      strcpy(res->body, ERRMSG_INVALID_REQUEST);
      return;
    }

    int del_retval = tpcfollower_del_check(server, req->key);
    if (del_retval < 0) {
      res->type = VOTE;
      if (del_retval == ERR_KEYLEN) {
        strcpy(res->body, ERRMSG_KEY_LEN);
      } else if (del_retval == ERR_NOKEY) {
        strcpy(res->body, ERRMSG_NO_KEY);
      } else {
        strcpy(res->body, ERRMSG_GENERIC_ERROR);
      }
    } else {
      tpclog_log(&server->log, DELREQ, req->key, NULL);
      res->type = VOTE;
      strcpy(res->body, MSG_COMMIT);

    }
  } else if (req->type == PUTREQ) {
    if (server->state != TPC_WAIT) {
      server->state = TPC_WAIT;
    } else {
      res->type = ERROR;
      strcpy(res->body, ERRMSG_INVALID_REQUEST);
      return;
    }

    int put_retval = tpcfollower_put_check(server, req->key, req->val);
    if (put_retval < 0) {
      res->type = VOTE;
      if (put_retval == ERR_KEYLEN) {
        strcpy(res->body, ERRMSG_KEY_LEN);
      } else if (put_retval == ERR_VALLEN) {
        strcpy(res->body, ERRMSG_VAL_LEN);
      } else {
        strcpy(res->body, ERRMSG_GENERIC_ERROR);
      }
    } else {
      tpclog_log(&server->log, PUTREQ, req->key, req->val);
      res->type = VOTE;
      strcpy(res->body, MSG_COMMIT);
    }
  } else if (req->type == COMMIT) {
    server->state = TPC_COMMIT;

    res->type = ACK;
    tpclog_iterate_begin(&server->log);
    logentry_t* entry = malloc(sizeof(logentry_t));

    while (tpclog_iterate_has_next(&server->log)) {
      entry = tpclog_iterate_next(&server->log, entry);
      char* log_key = malloc(strlen(entry->data));

      if (entry->type == DELREQ) {
        strcpy(log_key, entry->data);

        tpcfollower_del(server, log_key);
      } else if (entry->type == PUTREQ) {
        char* log_val = malloc(entry->length - strlen(entry->data));
        strcpy(log_key, entry->data);
        strcpy(log_val, entry->data + strlen(entry->data) + 1);

        tpcfollower_put(server, log_key, log_val);
      }
    } 

    tpclog_clear_log(&server->log);

  } else if (req->type == ABORT) {
    server->state = TPC_ABORT;

    res->type = ACK;
    tpclog_clear_log(&server->log);
  } else if (req->type == GETREQ) {
    int get_retval = tpcfollower_get(server, req->key, res->body);
    if (get_retval < 0) {
      res->type = ERROR;
      if (get_retval == ERR_KEYLEN) {
        strcpy(res->body, ERRMSG_KEY_LEN);
      } else if (get_retval == ERR_NOKEY) {
        strcpy(res->body, ERRMSG_NO_KEY);
      } else {
        strcpy(res->body, ERRMSG_INVALID_REQUEST);
      }
    } else {
      res->type = GETRESP;
    }
  }


}