/* 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; }
/* 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; } } }