Skip to content
This repository has been archived by the owner on Dec 26, 2022. It is now read-only.

Commit

Permalink
feat(api): Add lock to avoid race condition
Browse files Browse the repository at this point in the history
  • Loading branch information
jkrvivian committed Aug 26, 2019
1 parent 2514a9a commit 9d0c9c4
Show file tree
Hide file tree
Showing 5 changed files with 106 additions and 0 deletions.
63 changes: 63 additions & 0 deletions accelerator/apis.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@

#include "apis.h"
#include "map/mode.h"
#include "utils/handles/lock.h"

#define APIS_LOGGER "apis"

static logger_id_t apis_logger_id;
lock_handle_t cjson_lock;

void apis_logger_init() { apis_logger_id = logger_helper_enable(APIS_LOGGER, LOGGER_DEBUG, true); }

Expand All @@ -38,6 +40,20 @@ status_t api_get_ta_info(char** json_result, ta_config_t* const info, iota_confi
return ret;
}

status_t apis_lock_init() {
if (lock_handle_init(&cjson_lock)) {
return SC_CONF_LOCK_INIT;
}
return SC_OK;
}

status_t apis_lock_destroy() {
if (lock_handle_destroy(&cjson_lock)) {
return SC_CONF_LOCK_DESTROY;
}
return SC_OK;
}

status_t api_get_tips(const iota_client_service_t* const service, char** json_result) {
status_t ret = SC_OK;
get_tips_res_t* res = get_tips_res_new();
Expand All @@ -48,11 +64,14 @@ status_t api_get_tips(const iota_client_service_t* const service, char** json_re
goto done;
}

lock_handle_lock(&cjson_lock);
if (iota_client_get_tips(service, res) != RC_OK) {
lock_handle_unlock(&cjson_lock);
ret = SC_CCLIENT_FAILED_RESPONSE;
log_error(apis_logger_id, "[%s:%d:%s]\n", __func__, __LINE__, "SC_CCLIENT_FAILED_RESPONSE");
goto done;
}
lock_handle_unlock(&cjson_lock);

ret = ta_get_tips_res_serialize(res, json_result);
if (ret != SC_OK) {
Expand Down Expand Up @@ -80,11 +99,14 @@ status_t api_get_tips_pair(const iota_config_t* const tangle, const iota_client_
}

get_transactions_to_approve_req_set_depth(req, tangle->milestone_depth);
lock_handle_lock(&cjson_lock);
if (iota_client_get_transactions_to_approve(service, req, res) != RC_OK) {
lock_handle_unlock(&cjson_lock);
ret = SC_CCLIENT_FAILED_RESPONSE;
log_error(apis_logger_id, "[%s:%d:%s]\n", __func__, __LINE__, "SC_CCLIENT_FAILED_RESPONSE");
goto done;
}
lock_handle_unlock(&cjson_lock);

if (service->serializer.vtable.get_transactions_to_approve_serialize_response(res, res_buff) != RC_OK) {
ret = SC_CCLIENT_JSON_PARSE;
Expand Down Expand Up @@ -117,10 +139,13 @@ status_t api_generate_address(const iota_config_t* const tangle, const iota_clie
goto done;
}

lock_handle_lock(&cjson_lock);
ret = ta_generate_address(tangle, service, res);
if (ret) {
lock_handle_unlock(&cjson_lock);
goto done;
}
lock_handle_unlock(&cjson_lock);

ret = ta_generate_address_res_serialize(res, json_result);

Expand All @@ -139,17 +164,23 @@ status_t api_find_transactions(const iota_client_service_t* const service, const
log_error(apis_logger_id, "[%s:%d:%s]\n", __func__, __LINE__, "SC_TA_OOM");
goto done;
}
lock_handle_lock(&cjson_lock);
if (service->serializer.vtable.find_transactions_deserialize_request(obj, req) != RC_OK) {
lock_handle_unlock(&cjson_lock);
ret = SC_CCLIENT_JSON_PARSE;
log_error(apis_logger_id, "[%s:%d:%s]\n", __func__, __LINE__, "SC_CCLIENT_JSON_PARSE");
goto done;
}
lock_handle_unlock(&cjson_lock);

lock_handle_lock(&cjson_lock);
if (iota_client_find_transactions(service, req, res) != RC_OK) {
lock_handle_unlock(&cjson_lock);
ret = SC_CCLIENT_FAILED_RESPONSE;
log_error(apis_logger_id, "[%s:%d:%s]\n", __func__, __LINE__, "SC_CCLIENT_FAILED_RESPONSE");
goto done;
}
lock_handle_unlock(&cjson_lock);

if (service->serializer.vtable.find_transactions_serialize_response(res, res_buff) != RC_OK) {
ret = SC_CCLIENT_JSON_PARSE;
Expand Down Expand Up @@ -187,11 +218,14 @@ status_t api_find_transaction_object_single(const iota_client_service_t* const s
flex_trits_from_trytes(txn_hash, NUM_TRITS_HASH, (const tryte_t*)obj, NUM_TRYTES_HASH, NUM_TRYTES_HASH);
hash243_queue_push(&req->hashes, txn_hash);

lock_handle_lock(&cjson_lock);
ret = ta_find_transaction_objects(service, req, res);
if (ret) {
lock_handle_unlock(&cjson_lock);
log_error(apis_logger_id, "[%s:%d]\n", __func__, __LINE__);
goto done;
}
lock_handle_unlock(&cjson_lock);

ret = ta_find_transaction_object_single_res_serialize(res, json_result);

Expand All @@ -212,17 +246,23 @@ status_t api_find_transaction_objects(const iota_client_service_t* const service
goto done;
}

lock_handle_lock(&cjson_lock);
ret = ta_find_transaction_objects_req_deserialize(obj, req);
if (ret != SC_OK) {
lock_handle_unlock(&cjson_lock);
log_error(apis_logger_id, "[%s:%d]\n", __func__, __LINE__);
goto done;
}
lock_handle_unlock(&cjson_lock);

lock_handle_lock(&cjson_lock);
ret = ta_find_transaction_objects(service, req, res);
if (ret) {
lock_handle_unlock(&cjson_lock);
log_error(apis_logger_id, "[%s:%d]\n", __func__, __LINE__);
goto done;
}
lock_handle_unlock(&cjson_lock);

ret = ta_find_transaction_objects_res_serialize(res, json_result);

Expand Down Expand Up @@ -251,11 +291,14 @@ status_t api_find_transactions_by_tag(const iota_client_service_t* const service
goto done;
}

lock_handle_lock(&cjson_lock);
if (iota_client_find_transactions(service, req, res) != RC_OK) {
lock_handle_unlock(&cjson_lock);
ret = SC_CCLIENT_FAILED_RESPONSE;
log_error(apis_logger_id, "[%s:%d]\n", __func__, __LINE__);
goto done;
}
lock_handle_unlock(&cjson_lock);

ret = ta_find_transactions_by_tag_res_serialize((ta_find_transactions_by_tag_res_t*)res, json_result);

Expand Down Expand Up @@ -284,11 +327,14 @@ status_t api_find_transactions_obj_by_tag(const iota_client_service_t* const ser
goto done;
}

lock_handle_lock(&cjson_lock);
ret = ta_find_transactions_obj_by_tag(service, req, res);
if (ret) {
lock_handle_unlock(&cjson_lock);
log_error(apis_logger_id, "[%s:%d]\n", __func__, __LINE__);
goto done;
}
lock_handle_unlock(&cjson_lock);

ret = ta_find_transaction_objects_res_serialize(res, json_result);

Expand Down Expand Up @@ -355,11 +401,14 @@ status_t api_mam_send_message(const iota_config_t* const tangle, const iota_clie
ta_send_mam_req_t* req = send_mam_req_new();
ta_send_mam_res_t* res = send_mam_res_new();

lock_handle_lock(&cjson_lock);
if (send_mam_req_deserialize(payload, req)) {
lock_handle_unlock(&cjson_lock);
ret = SC_MAM_FAILED_INIT;
log_error(apis_logger_id, "[%s:%d:%s]\n", __func__, __LINE__, "SC_MAM_FAILED_INIT");
goto done;
}
lock_handle_unlock(&cjson_lock);

// Creating MAM API
prng = (req->prng[0]) ? req->prng : SEED;
Expand Down Expand Up @@ -404,11 +453,14 @@ status_t api_mam_send_message(const iota_config_t* const tangle, const iota_clie
send_mam_res_set_channel_id(res, channel_id);

// Sending bundle
lock_handle_lock(&cjson_lock);
if (ta_send_bundle(tangle, service, bundle) != SC_OK) {
lock_handle_unlock(&cjson_lock);
ret = SC_MAM_FAILED_RESPONSE;
log_error(apis_logger_id, "[%s:%d:%s]\n", __func__, __LINE__, "SC_MAM_FAILED_RESPONSE");
goto done;
}
lock_handle_unlock(&cjson_lock);
send_mam_res_set_bundle_hash(res, transaction_bundle((iota_transaction_t*)utarray_front(bundle)));

ret = send_mam_res_serialize(res, json_result);
Expand Down Expand Up @@ -441,23 +493,30 @@ status_t api_send_transfer(const iota_config_t* const tangle, const iota_client_
goto done;
}

lock_handle_lock(&cjson_lock);
ret = ta_send_transfer_req_deserialize(obj, req);
if (ret) {
lock_handle_unlock(&cjson_lock);
goto done;
}

ret = ta_send_transfer(tangle, service, req, res);
if (ret) {
lock_handle_unlock(&cjson_lock);
goto done;
}
lock_handle_unlock(&cjson_lock);

// return transaction object
hash243_queue_push(&txn_obj_req->hashes, hash243_queue_peek(res->hash));

lock_handle_lock(&cjson_lock);
ret = ta_find_transaction_objects(service, txn_obj_req, res_txn_array);
if (ret) {
lock_handle_unlock(&cjson_lock);
goto done;
}
lock_handle_unlock(&cjson_lock);

ret = ta_send_transfer_res_serialize(res_txn_array, json_result);

Expand All @@ -480,15 +539,19 @@ status_t api_send_trytes(const iota_config_t* const tangle, const iota_client_se
goto done;
}

lock_handle_lock(&cjson_lock);
ret = ta_send_trytes_req_deserialize(obj, trytes);
if (ret != SC_OK) {
lock_handle_unlock(&cjson_lock);
goto done;
}

ret = ta_send_trytes(tangle, service, trytes);
if (ret != SC_OK) {
lock_handle_unlock(&cjson_lock);
goto done;
}
lock_handle_unlock(&cjson_lock);

ret = ta_send_trytes_res_serialize(trytes, json_result);

Expand Down
18 changes: 18 additions & 0 deletions accelerator/apis.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,24 @@ int apis_logger_release();
status_t api_get_ta_info(char** json_result, ta_config_t* const info, iota_config_t* const tangle,
ta_cache_t* const cache, iota_client_service_t* const service);

/**
* Initialize lock
*
* @return
* - zero on success
* - SC_CONF_LOCK_INIT on error
*/
status_t apis_lock_init();

/**
* Destroy lock
*
* @return
* - zero on success
* - SC_CONF_LOCK_DESTROY on error
*/
status_t apis_lock_destroy();

/**
* @brief Generate an unused address.
*
Expand Down
4 changes: 4 additions & 0 deletions accelerator/errors.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ typedef enum {
/**< No argument in CLI */
SC_CONF_UNKNOWN_OPTION = 0x03 | SC_MODULE_CONF | SC_SEVERITY_FATAL,
/**< undefined option in CLI */
SC_CONF_LOCK_INIT = 0x04 | SC_MODULE_CONF | SC_SEVERITY_FATAL,
/**< fail to init lock */
SC_CONF_LOCK_DESTROY = 0x05 | SC_MODULE_CONF | SC_SEVERITY_FATAL,
/**< fail to destroy lock */

// UTILS module
SC_UTILS_NULL = 0x01 | SC_MODULE_UTILS | SC_SEVERITY_FATAL,
Expand Down
11 changes: 11 additions & 0 deletions accelerator/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,12 @@ int main(int argc, char* argv[]) {
return EXIT_FAILURE;
}

// Initialize apis cJSON lock
if (apis_lock_init() != SC_OK) {
log_critical(logger_id, "[%s:%d] Lock initialization failed %s.\n", __func__, __LINE__, MAIN_LOGGER);
return EXIT_FAILURE;
}

// Enable other loggers when verbose mode is on
if (verbose_mode) {
http_logger_init();
Expand All @@ -67,6 +73,11 @@ int main(int argc, char* argv[]) {
}

cleanup:
log_warning(logger_id, "Destroying API lock\n");
if (apis_lock_destroy() != SC_OK) {
log_critical(logger_id, "[%s:%d] Destroying api lock failed %s.\n", __func__, __LINE__, MAIN_LOGGER);
return EXIT_FAILURE;
}
log_warning(logger_id, "Destroying TA configurations\n");
ta_config_destroy(&ta_core.service);

Expand Down
10 changes: 10 additions & 0 deletions accelerator/server.cc
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@ int main(int argc, char* argv[]) {
return EXIT_FAILURE;
}

// Initialize apis cJSON lock
if (apis_lock_init() != SC_OK) {
log_critical(server_logger_id, "[%s:%d] Lock initialization failed %s.\n", __func__, __LINE__, SERVER_LOGGER);
return EXIT_FAILURE;
}

// Enable other loggers when verbose mode is on
if (verbose_mode) {
apis_logger_init();
Expand Down Expand Up @@ -417,6 +423,10 @@ int main(int argc, char* argv[]) {
served::net::server server(ta_core.info.host, ta_core.info.port, mux);
server.run(ta_core.info.thread_count);

if (apis_lock_destroy() != SC_OK) {
log_critical(server_logger_id, "[%s:%d] Destroying api lock failed %s.\n", __func__, __LINE__, SERVER_LOGGER);
return EXIT_FAILURE;
}
ta_config_destroy(&ta_core.service);

if (verbose_mode) {
Expand Down

0 comments on commit 9d0c9c4

Please sign in to comment.