From 62898b699debb2c68479fd5fa21a2a9ec68266f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Al=D0=B5x=D0=B0nder=20Lysik=D0=BEv?= <alexander.lysikov@demlabs.net> Date: Fri, 6 Mar 2020 23:42:20 +0500 Subject: [PATCH] fixed node sync --- dap_chain_global_db.c | 142 +++++++++++++++++++++++++++++- dap_chain_global_db.h | 6 ++ dap_chain_global_db_driver.c | 36 ++++++-- dap_chain_global_db_driver.h | 5 +- dap_chain_global_db_driver_cdb.c | 36 ++++++-- dap_chain_global_db_driver_cdb.h | 1 + dap_chain_global_db_hist.c | 3 + dap_chain_global_db_hist.h | 10 +-- dap_chain_global_db_remote.c | 4 +- libdap-cuttdb/src/cdb_core.c | 55 ++++++++++++ libdap-cuttdb/src/cdb_hashtable.c | 6 +- libdap-cuttdb/src/cuttdb.h | 2 + 12 files changed, 282 insertions(+), 24 deletions(-) diff --git a/dap_chain_global_db.c b/dap_chain_global_db.c index 21ae1dd..083eaa3 100755 --- a/dap_chain_global_db.c +++ b/dap_chain_global_db.c @@ -3,7 +3,7 @@ * Alexander Lysikov <alexander.lysikov@demlabs.net> * DeM Labs Inc. https://demlabs.net * Kelvin Project https://github.com/kelvinblockchain - * Copyright (c) 2019 +* Copyright (c) 2019-2020 * All rights reserved. This file is part of DAP (Deus Applications Prototypes) the open source project @@ -139,6 +139,8 @@ void dap_chain_global_db_add_history_callback_notify(const char * a_group_prefix */ void dap_chain_global_db_obj_clean(dap_global_db_obj_t *obj) { + if(!obj) + return; DAP_DELETE(obj->key); DAP_DELETE(obj->value); obj->key = NULL; @@ -244,6 +246,31 @@ void* dap_chain_global_db_obj_get(const char *a_key, const char *a_group) return store_data;*/ } +/** + * @brief dap_chain_global_db_obj_gr_get + * @param a_key + * @param a_data_out + * @param a_group + * @return + */ +dap_store_obj_t* dap_chain_global_db_obj_gr_get(const char *a_key, size_t *a_data_len_out, const char *a_group) +{ + uint8_t *l_ret_value = NULL; + // read several items, 0 - no limits + size_t l_data_len_out = 0; + if(a_data_len_out) + l_data_len_out = *a_data_len_out; + dap_store_obj_t *l_store_data = dap_chain_global_db_driver_read(a_group, a_key, &l_data_len_out); + if(l_store_data) { + l_ret_value = (l_store_data->value) ? DAP_NEW_SIZE(uint8_t, l_store_data->value_len) : NULL; //ret_value = (store_data->value) ? strdup(store_data->value) : NULL; + memcpy(l_ret_value, l_store_data->value, l_store_data->value_len); + if(a_data_len_out) + *a_data_len_out = l_store_data->value_len; + //dap_store_obj_free(l_store_data, l_data_len_out); + } + return l_store_data; +} + /** * @brief dap_chain_global_db_gr_get * @param a_key @@ -296,6 +323,82 @@ uint8_t * dap_chain_global_db_get(const char *a_key, size_t *a_data_out) return dap_chain_global_db_gr_get(a_key, a_data_out, GROUP_LOCAL_GENERAL); } + +/** + * Add info about the deleted entry to the base + */ +static bool global_db_gr_del_add(char *a_key,const char *a_group, time_t a_timestamp) +{ + dap_store_obj_t store_data;// = DAP_NEW_Z_SIZE(dap_store_obj_t, sizeof(struct dap_store_obj)); + memset(&store_data, 0, sizeof(dap_store_obj_t)); + store_data.type = 'a'; + store_data.key = a_key;//dap_strdup(a_key); + // no data + store_data.value = NULL; + store_data.value_len = 0; + // group = parent group + '.del' + store_data.group = dap_strdup_printf("%s.del", a_group); + store_data.timestamp = a_timestamp;//time(NULL); + lock(); + int l_res = dap_chain_global_db_driver_add(&store_data, 1); + unlock(); + DAP_DELETE(store_data.group); + if(l_res>=0) + return true; + return false; +} + +/** + * Delete info about the deleted entry from the base + */ +static bool global_db_gr_del_del(char *a_key,const char *a_group) +{ + if(!a_key) + return NULL; + dap_store_obj_t store_data;// = DAP_NEW_Z_SIZE(dap_store_obj_t, sizeof(struct dap_store_obj)); + memset(&store_data, 0, sizeof(dap_store_obj_t)); + store_data.key = a_key; + // store_data->c_key = a_key; + store_data.group = dap_strdup_printf("%s.del", a_group); + //store_data->c_group = a_group; + lock(); + int l_res = 0; + if(dap_chain_global_db_driver_is(store_data.group, store_data.key)) + l_res = dap_chain_global_db_driver_delete(&store_data, 1); + unlock(); + DAP_DELETE(store_data.group); + if(l_res>=0) + return true; + return false; +} + +/** + * Get timestamp of the deleted entry + */ +time_t global_db_gr_del_get_timestamp(const char *a_group, char *a_key) +{ + time_t l_timestamp = 0; + if(!a_key) + return l_timestamp; + dap_store_obj_t store_data; + memset(&store_data, 0, sizeof(dap_store_obj_t)); + store_data.key = a_key; + // store_data->c_key = a_key; + store_data.group = dap_strdup_printf("%s.del", a_group); + //store_data->c_group = a_group; + lock(); + if(dap_chain_global_db_driver_is(store_data.group, store_data.key)) { + size_t l_count_out = 0; + dap_store_obj_t *l_obj = dap_chain_global_db_driver_read(store_data.group, store_data.key, &l_count_out); + assert(l_count_out <= 1); + l_timestamp = l_obj->timestamp; + dap_store_obj_free(l_obj, l_count_out); + } + unlock(); + DAP_DELETE(store_data.group); + return l_timestamp; +} + /** * */ @@ -328,6 +431,9 @@ bool dap_chain_global_db_gr_set(char *a_key, void *a_value, size_t a_value_len, // Extract prefix if added successfuly, add history log and call notify callback if present if(!l_res) { + // Delete info about the deleted entry from the base if one present + global_db_gr_del_del(a_key, a_group); + char * l_group_prefix = extract_group_prefix(a_group); history_group_item_t * l_history_group_item = NULL; if(l_group_prefix) @@ -357,6 +463,7 @@ bool dap_chain_global_db_set( char *a_key, void *a_value, size_t a_value_len) { return dap_chain_global_db_gr_set(a_key, a_value, a_value_len, GROUP_LOCAL_GENERAL); } + /** * Delete entry from base */ @@ -368,11 +475,14 @@ bool dap_chain_global_db_gr_del(char *a_key,const char *a_group) store_data->key = a_key; // store_data->c_key = a_key; store_data->group = dap_strdup(a_group); - store_data->c_group = a_group; + //store_data->c_group = a_group; lock(); int l_res = dap_chain_global_db_driver_delete(store_data, 1); unlock(); + // do not add to history if l_res=1 (already deleted) if(!l_res) { + // added to Del group + global_db_gr_del_add(a_key, a_group, time(NULL)); // Extract prefix char * l_group_prefix = extract_group_prefix(a_group); history_group_item_t * l_history_group_item = NULL; @@ -392,8 +502,21 @@ bool dap_chain_global_db_gr_del(char *a_key,const char *a_group) DAP_DELETE(l_group_prefix); } //DAP_DELETE(store_data); - if(!l_res) + if(l_res>=0){ + // added to Del group + global_db_gr_del_add(a_key, a_group, time(NULL)); + /*/ read del info + char *l_group = dap_strdup_printf("%s.del", a_group); + size_t l_data_size_out = 0; + dap_store_obj_t *l_objs = dap_chain_global_db_obj_gr_get(a_key, &l_data_size_out,l_group); + // update timestamp + if(l_objs){ + if(l_objs->timestamp<time(NULL)) + dap_store_obj_free(l_objs, l_data_size_out); + } + DAP_DELETE(l_group);*/ return true; + } return false; } bool dap_chain_global_db_del(char *a_key) @@ -496,6 +619,16 @@ bool dap_chain_global_db_obj_save(void* a_store_data, size_t a_objs_count) // Extract prefix if added successfuly, add history log and call notify callback if present if(!l_res) { for(size_t i = 0; i < a_objs_count; i++) { + + dap_store_obj_t *a_store_obj = a_store_data + i; + if(a_store_obj->type == 'a') + // delete info about the deleted entry from the base if one present + global_db_gr_del_del(a_store_obj->key, a_store_obj->group); + else if(a_store_obj->type == 'd') + // add to Del group + global_db_gr_del_add(a_store_obj->key, a_store_obj->group, a_store_obj->timestamp); + + history_group_item_t * l_history_group_item = NULL; dap_store_obj_t* l_obj = (dap_store_obj_t*)a_store_data + i; char * l_group_prefix = extract_group_prefix(l_obj->group); @@ -523,8 +656,9 @@ bool dap_chain_global_db_obj_save(void* a_store_data, size_t a_objs_count) } } - if(!l_res) + if(l_res >= 0) { return true; + } return false; } diff --git a/dap_chain_global_db.h b/dap_chain_global_db.h index 3d594e4..8fc7742 100755 --- a/dap_chain_global_db.h +++ b/dap_chain_global_db.h @@ -61,6 +61,7 @@ void dap_chain_global_db_add_history_callback_notify(const char * a_group_prefix * Get entry from base */ void* dap_chain_global_db_obj_get(const char *a_key, const char *a_group); +dap_store_obj_t* dap_chain_global_db_obj_gr_get(const char *a_key, size_t *a_data_len_out, const char *a_group); uint8_t * dap_chain_global_db_gr_get(const char *a_key, size_t *a_data_out, const char *a_group); uint8_t * dap_chain_global_db_get(const char *a_key, size_t *a_data_out); @@ -76,6 +77,11 @@ bool dap_chain_global_db_set( char *a_key, void *a_value, size_t a_value_len); bool dap_chain_global_db_gr_del(char *a_key, const char *a_group); bool dap_chain_global_db_del(char *a_key); +/** + * Get timestamp of the deleted entry + */ +time_t global_db_gr_del_get_timestamp(const char *a_group, char *a_key); + /** * Read the entire database into an array of size bytes * diff --git a/dap_chain_global_db_driver.c b/dap_chain_global_db_driver.c index b14f1e6..c1e9c7f 100755 --- a/dap_chain_global_db_driver.c +++ b/dap_chain_global_db_driver.c @@ -407,12 +407,21 @@ static int save_write_buf(void) dap_store_obj_t *l_obj = s_list_begin->data; assert(l_obj); if(s_drv_callback.apply_store_obj) { - if(!s_drv_callback.apply_store_obj(l_obj)) { + int l_ret_tmp = s_drv_callback.apply_store_obj(l_obj); + if(l_ret_tmp == 1) { + log_it(L_INFO, "item is missing (may be already deleted) %s/%s\n", l_obj->group, l_obj->key); + l_ret = 1; + } + if(l_ret_tmp < 0) { + log_it(L_ERROR, "Can't write item %s/%s\n", l_obj->group, l_obj->key); + l_ret -= 1; + } + /*if(!s_drv_callback.apply_store_obj(l_obj)) { //log_it(L_INFO, "Write item Ok %s/%s\n", l_obj->group, l_obj->key); } else { log_it(L_ERROR, "Can't write item %s/%s\n", l_obj->group, l_obj->key); - } + }*/ } s_list_begin = dap_list_next(s_list_begin); @@ -496,10 +505,12 @@ int dap_chain_global_db_driver_appy(pdap_store_obj_t a_store_obj, size_t a_store for(size_t i = 0; i < a_store_count; i++) { dap_store_obj_t *l_store_obj_cur = a_store_obj + i; assert(l_store_obj_cur); - if(!s_drv_callback.apply_store_obj(l_store_obj_cur)) { - //log_it(L_INFO, "Write item Ok %s/%s\n", l_obj->group, l_obj->key); + int l_ret_tmp = s_drv_callback.apply_store_obj(l_store_obj_cur); + if(l_ret_tmp == 1) { + log_it(L_INFO, "item is missing (may be already deleted) %s/%s\n", l_store_obj_cur->group, l_store_obj_cur->key); + l_ret = 1; } - else { + if(l_ret_tmp < 0) { log_it(L_ERROR, "Can't write item %s/%s\n", l_store_obj_cur->group, l_store_obj_cur->key); l_ret -= 1; } @@ -601,3 +612,18 @@ dap_store_obj_t* dap_chain_global_db_driver_read(const char *a_group, const char l_ret = s_drv_callback.read_store_obj(a_group, a_key, a_count_out); return l_ret; } + +/** + * Check an element in the database + * + * a_group - group name + * a_key - key name + */ +bool dap_chain_global_db_driver_is(const char *a_group, const char *a_key) +{ + bool l_ret = NULL; + // read records using the selected database engine + if(s_drv_callback.is_obj) + l_ret = s_drv_callback.is_obj(a_group, a_key); + return l_ret; +} diff --git a/dap_chain_global_db_driver.h b/dap_chain_global_db_driver.h index f078d51..22452f4 100755 --- a/dap_chain_global_db_driver.h +++ b/dap_chain_global_db_driver.h @@ -34,7 +34,7 @@ typedef struct dap_store_obj { uint8_t type; char *group; char *key; - const char *c_group; + //const char *c_group; const char *c_key; uint8_t *value; size_t value_len; @@ -51,6 +51,7 @@ typedef dap_store_obj_t* (*dap_db_driver_read_callback_t)(const char *,const cha typedef dap_store_obj_t* (*dap_db_driver_read_cond_callback_t)(const char *,uint64_t , size_t *); typedef dap_store_obj_t* (*dap_db_driver_read_last_callback_t)(const char *); typedef size_t (*dap_db_driver_read_count_callback_t)(const char *,uint64_t); +typedef bool (*dap_db_driver_is_obj_callback_t)(const char *, const char *); typedef int (*dap_db_driver_callback_t)(void); typedef struct dap_db_driver_callbacks { @@ -59,6 +60,7 @@ typedef struct dap_db_driver_callbacks { dap_db_driver_read_last_callback_t read_last_store_obj; dap_db_driver_read_cond_callback_t read_cond_store_obj; dap_db_driver_read_count_callback_t read_count_store; + dap_db_driver_is_obj_callback_t is_obj; dap_db_driver_callback_t transaction_start; dap_db_driver_callback_t transaction_end; dap_db_driver_callback_t deinit; @@ -81,6 +83,7 @@ int dap_chain_global_db_driver_delete(pdap_store_obj_t a_store_obj, size_t a_sto dap_store_obj_t* dap_chain_global_db_driver_read_last(const char *a_group); dap_store_obj_t* dap_chain_global_db_driver_cond_read(const char *a_group, uint64_t id, size_t *a_count_out); dap_store_obj_t* dap_chain_global_db_driver_read(const char *a_group, const char *a_key, size_t *count_out); +bool dap_chain_global_db_driver_is(const char *a_group, const char *a_key); size_t dap_chain_global_db_driver_count(const char *a_group, uint64_t id); dap_store_obj_pkt_t *dap_store_packet_multiple(pdap_store_obj_t a_store_obj, diff --git a/dap_chain_global_db_driver_cdb.c b/dap_chain_global_db_driver_cdb.c index 09961f5..2d29c9b 100644 --- a/dap_chain_global_db_driver_cdb.c +++ b/dap_chain_global_db_driver_cdb.c @@ -228,6 +228,7 @@ int dap_db_driver_cdb_init(const char *a_cdb_path, dap_db_driver_callbacks_t *a_ a_drv_callback->read_store_obj = dap_db_driver_cdb_read_store_obj; a_drv_callback->read_cond_store_obj = dap_db_driver_cdb_read_cond_store_obj; a_drv_callback->read_count_store = dap_db_driver_cdb_read_count_store; + a_drv_callback->is_obj = dap_db_driver_cdb_is_obj; a_drv_callback->deinit = dap_db_driver_cdb_deinit; a_drv_callback->flush = dap_db_driver_cdb_flush; @@ -321,6 +322,26 @@ dap_store_obj_t *dap_db_driver_cdb_read_last_store_obj(const char* a_group) { return l_arg.o; } +bool dap_db_driver_cdb_is_obj(const char *a_group, const char *a_key) +{ + bool l_ret = false; + if(!a_group) { + return false; + } + pcdb_instance l_cdb_i = dap_cdb_get_db_by_group(a_group); + if(!l_cdb_i) { + return false; + } + CDB *l_cdb = l_cdb_i->cdb; + if(a_key) { + + int l_vsize; + if(!cdb_is(l_cdb, a_key, (int) dap_strlen(a_key))) + l_ret = true; + } + return l_ret; +} + dap_store_obj_t *dap_db_driver_cdb_read_store_obj(const char *a_group, const char *a_key, size_t *a_count_out) { if (!a_group) { return NULL; @@ -426,12 +447,14 @@ size_t dap_db_driver_cdb_read_count_store(const char *a_group, uint64_t a_id) } pcdb_instance l_cdb_i = dap_cdb_get_db_by_group(a_group); if(!l_cdb_i) { - return NULL; + return 0; } CDB *l_cdb = l_cdb_i->cdb; CDBSTAT l_cdb_stat; cdb_stat(l_cdb, &l_cdb_stat); - return (size_t) l_cdb_stat.rnum; + if(a_id > l_cdb_stat.rnum) + return 0; + return (size_t) l_cdb_stat.rnum - a_id + 1; } int dap_db_driver_cdb_apply_store_obj(pdap_store_obj_t a_store_obj) { @@ -448,7 +471,7 @@ int dap_db_driver_cdb_apply_store_obj(pdap_store_obj_t a_store_obj) { return -1; } if(a_store_obj->type == 'a') { - if(!a_store_obj->key || !a_store_obj->value || !a_store_obj->value_len){ + if(!a_store_obj->key) {// || !a_store_obj->value || !a_store_obj->value_len){ return -2; } cdb_record l_rec; @@ -459,7 +482,9 @@ int dap_db_driver_cdb_apply_store_obj(pdap_store_obj_t a_store_obj) { offset += sizeof(uint64_t); dap_cdb_uint_to_hex(l_val + offset, a_store_obj->value_len, sizeof(unsigned long)); offset += sizeof(unsigned long); - memcpy(l_val + offset, a_store_obj->value, a_store_obj->value_len); + if(a_store_obj->value && a_store_obj->value_len){ + memcpy(l_val + offset, a_store_obj->value, a_store_obj->value_len); + } offset += a_store_obj->value_len; unsigned long l_time = (unsigned long)a_store_obj->timestamp; dap_cdb_uint_to_hex(l_val + offset, l_time, sizeof(time_t)); @@ -473,7 +498,8 @@ int dap_db_driver_cdb_apply_store_obj(pdap_store_obj_t a_store_obj) { DAP_DELETE(l_rec.val); } else if(a_store_obj->type == 'd') { if(a_store_obj->key) { - cdb_del(l_cdb_i->cdb, a_store_obj->key, (int)strlen(a_store_obj->key)); + if(cdb_del(l_cdb_i->cdb, a_store_obj->key, (int) strlen(a_store_obj->key)) == -3) + ret = 1; } else { cdb_destroy(l_cdb_i->cdb); if (!dap_cdb_init_group(a_store_obj->group, CDB_TRUNC | CDB_PAGEWARMUP)) { diff --git a/dap_chain_global_db_driver_cdb.h b/dap_chain_global_db_driver_cdb.h index 44997bc..8415dc3 100644 --- a/dap_chain_global_db_driver_cdb.h +++ b/dap_chain_global_db_driver_cdb.h @@ -47,3 +47,4 @@ dap_store_obj_t *dap_db_driver_cdb_read_last_store_obj(const char*); dap_store_obj_t *dap_db_driver_cdb_read_store_obj(const char*, const char*, size_t*); size_t dap_db_driver_cdb_read_count_store(const char *a_group, uint64_t a_id); dap_store_obj_t* dap_db_driver_cdb_read_cond_store_obj(const char*, uint64_t, size_t*); +bool dap_db_driver_cdb_is_obj(const char *a_group, const char *a_key); diff --git a/dap_chain_global_db_hist.c b/dap_chain_global_db_hist.c index a480201..4eabd9e 100755 --- a/dap_chain_global_db_hist.c +++ b/dap_chain_global_db_hist.c @@ -107,6 +107,7 @@ uint8_t* dap_db_log_pack(dap_global_db_obj_t *a_obj, size_t *a_data_size_out) l_obj->id = a_obj->id; l_obj->group = dap_strdup(l_rec.group); l_obj->key = dap_strdup(l_keys[i]); + l_obj->timestamp = global_db_gr_del_get_timestamp(l_obj->group, l_obj->key); } if(l_obj == NULL) { dap_store_obj_free(l_store_obj, l_count); @@ -1292,6 +1293,8 @@ dap_db_log_list_t* dap_db_log_list_start(uint64_t first_id) dap_db_log_list_t *l_dap_db_log_list = DAP_NEW_Z(dap_db_log_list_t); size_t l_data_size_out = dap_chain_global_db_driver_count(GROUP_LOCAL_HISTORY, first_id); + if(!l_data_size_out) + return NULL; // debug // if(l_data_size_out>11) // l_data_size_out = 11; diff --git a/dap_chain_global_db_hist.h b/dap_chain_global_db_hist.h index 851cfad..2508b9a 100755 --- a/dap_chain_global_db_hist.h +++ b/dap_chain_global_db_hist.h @@ -25,12 +25,12 @@ bool dap_db_history_truncate(void); // for dap_db_log_list_xxx() typedef struct dap_db_log_list { dap_list_t *list_write; // writed list - dap_list_t *list_read; // readed list (inside list_write) + dap_list_t *list_read; // readed list (inside list_write) bool is_process; - size_t item_start; - size_t item_last; - size_t items_rest; - size_t items_number; + size_t item_start; // first item to read from db + size_t item_last; // last item to read from db + size_t items_rest; // rest items to read from list_read + size_t items_number; // remaining items in list_write after reading from db pthread_t thread; pthread_mutex_t list_mutex; } dap_db_log_list_t; diff --git a/dap_chain_global_db_remote.c b/dap_chain_global_db_remote.c index cdc78dd..d8beff4 100755 --- a/dap_chain_global_db_remote.c +++ b/dap_chain_global_db_remote.c @@ -106,7 +106,7 @@ uint64_t dap_db_get_cur_node_addr(char *a_net_name) bool dap_db_log_set_last_id_remote(uint64_t a_node_addr, uint64_t a_id) { dap_global_db_obj_t l_objs; - l_objs.key = dap_strdup_printf("%lld", a_node_addr); + l_objs.key = dap_strdup_printf("%ju", a_node_addr); l_objs.value = (uint8_t*) &a_id; l_objs.value_len = sizeof(uint64_t); bool l_ret = dap_chain_global_db_gr_save(&l_objs, 1, GROUP_LOCAL_NODE_LAST_ID); @@ -120,7 +120,7 @@ bool dap_db_log_set_last_id_remote(uint64_t a_node_addr, uint64_t a_id) */ uint64_t dap_db_log_get_last_id_remote(uint64_t a_node_addr) { - char *l_node_addr_str = dap_strdup_printf("%lld", a_node_addr); + char *l_node_addr_str = dap_strdup_printf("%ju", a_node_addr); size_t l_timestamp_len = 0; uint8_t *l_timestamp = dap_chain_global_db_gr_get((const char*) l_node_addr_str, &l_timestamp_len, GROUP_LOCAL_NODE_LAST_ID); diff --git a/libdap-cuttdb/src/cdb_core.c b/libdap-cuttdb/src/cdb_core.c index ddd5245..db2320d 100644 --- a/libdap-cuttdb/src/cdb_core.c +++ b/libdap-cuttdb/src/cdb_core.c @@ -1086,6 +1086,61 @@ int cdb_set2(CDB *db, const char *key, int ksize, const char *val, int vsize, in } +int cdb_is(CDB *db, const char *key, int ksize) +{ + FOFF soffs[SFOFFNUM]; + FOFF *offs; + int dupnum, ret = -3; + uint64_t hash; + uint32_t now = time(NULL); + uint32_t lockid; + + if (db->rcache) { + char *cval; + cdb_lock_lock(db->rclock); + cval = cdb_ht_get(db->rcache, key, ksize, 0, true); + if (cval) { + db->rchit++; + cdb_lock_unlock(db->rclock); + return 0; + } else { + db->rcmiss++; + if (db->vio == NULL) { + cdb_lock_unlock(db->rclock); + return -3; + } + } + cdb_lock_unlock(db->rclock); + } + + offs = soffs; + hash = CDBHASH64(key, ksize); + lockid = (hash >> 24) % db->hsize % MLOCKNUM; + cdb_lock_lock(db->mlock[lockid]); + dupnum = cdb_getoff(db, hash, &offs, CDB_LOCKED); + if (dupnum <= 0) { + cdb_lock_unlock(db->mlock[lockid]); + return -1; + } + else + ret = 0; + cdb_lock_unlock(db->mlock[lockid]); + + if (RCOVERFLOW(db)) + _cdb_recout(db); + + if (offs != soffs) + free(offs); + + if (ret < 0) + cdb_seterrno(db, CDB_NOTFOUND, __FILE__, __LINE__); + else { + db->rcmiss++; + cdb_seterrno(db, CDB_SUCCESS, __FILE__, __LINE__); + } + return ret; +} + int cdb_get(CDB *db, const char *key, int ksize, void **val, int *vsize) { diff --git a/libdap-cuttdb/src/cdb_hashtable.c b/libdap-cuttdb/src/cdb_hashtable.c index f8746a6..1f33f0c 100644 --- a/libdap-cuttdb/src/cdb_hashtable.c +++ b/libdap-cuttdb/src/cdb_hashtable.c @@ -225,10 +225,12 @@ void *cdb_ht_get(CDBHASHTABLE *ht, const void *key, int ksize, int *vsize, bool res = cdb_ht_get3(ht, key, ksize, mtf); if (res) { - *vsize = res->vsize; + if(vsize) + *vsize = res->vsize; return cdb_ht_itemval(ht, res); } else { - *vsize = 0; + if(vsize) + *vsize = 0; return NULL; } } diff --git a/libdap-cuttdb/src/cuttdb.h b/libdap-cuttdb/src/cuttdb.h index e3eeac9..1814028 100644 --- a/libdap-cuttdb/src/cuttdb.h +++ b/libdap-cuttdb/src/cuttdb.h @@ -155,6 +155,8 @@ int cdb_set(CDB *db, const char *key, int ksize, const char *val, int vsize); int cdb_set2(CDB *db, const char *key, int ksize, const char *val, int vsize, int opt, int expire); +int cdb_is(CDB *db, const char *key, int ksize); + /* get an record by 'key', the value will be allocated and passed out by 'val', its size is 'vsize'. return 0 if success, or -1 at failure. */ int cdb_get(CDB *db, const char *key, int ksize, void **val, int *vsize); -- GitLab