diff --git a/dap_chain_global_db.c b/dap_chain_global_db.c index 20d00b59c7721f76396e3e0599ae3812691db123..591e8bd500e49efd595a6e02a1c682c95e008547 100755 --- a/dap_chain_global_db.c +++ b/dap_chain_global_db.c @@ -17,16 +17,16 @@ #define LOG_TAG "dap_global_db" // for access from several streams -static pthread_mutex_t ldb_mutex_ = PTHREAD_MUTEX_INITIALIZER; +//static pthread_mutex_t ldb_mutex_ = PTHREAD_MUTEX_INITIALIZER; static inline void lock() { - pthread_mutex_lock(&ldb_mutex_); + //pthread_mutex_lock(&ldb_mutex_); } static inline void unlock() { - pthread_mutex_unlock(&ldb_mutex_); + //pthread_mutex_unlock(&ldb_mutex_); } // Callback table item @@ -43,28 +43,27 @@ typedef struct history_group_item // Tacked group callbacks static history_group_item_t * s_history_group_items = NULL; -char * extract_group_prefix (const char * a_group); - +char * extract_group_prefix(const char * a_group); /** * @brief extract_group_prefix * @param a_group * @return */ -char * extract_group_prefix (const char * a_group) +char * extract_group_prefix(const char * a_group) { - char * l_group_prefix = NULL, *l_delimeter ; + char * l_group_prefix = NULL, *l_delimeter; size_t l_group_prefix_size; - l_delimeter = index (a_group,'.'); - if ( l_delimeter == NULL ){ - l_group_prefix = strdup(a_group); - l_group_prefix_size = strlen( l_group_prefix)+1; + l_delimeter = index(a_group, '.'); + if(l_delimeter == NULL) { + l_group_prefix = dap_strdup(a_group); + l_group_prefix_size = dap_strlen(l_group_prefix) + 1; } else { - l_group_prefix_size = (size_t)l_delimeter- (size_t) a_group; - if ( l_group_prefix_size > 1 ) + l_group_prefix_size = (size_t) l_delimeter - (size_t) a_group; + if(l_group_prefix_size > 1) l_group_prefix = strndup(a_group, l_group_prefix_size); } - return l_group_prefix; + return l_group_prefix; } /** @@ -75,9 +74,9 @@ char * extract_group_prefix (const char * a_group) void dap_chain_global_db_add_history_group_prefix(const char * a_group_prefix) { history_group_item_t * l_item = DAP_NEW_Z(history_group_item_t); - snprintf(l_item->prefix,sizeof (l_item->prefix),"%s",a_group_prefix); + snprintf(l_item->prefix, sizeof(l_item->prefix), "%s", a_group_prefix); l_item->auto_track = true; - HASH_ADD_STR(s_history_group_items , prefix, l_item ); + HASH_ADD_STR(s_history_group_items, prefix, l_item); } /** @@ -85,18 +84,19 @@ void dap_chain_global_db_add_history_group_prefix(const char * a_group_prefix) * @param a_group_prefix * @param a_callback */ -void dap_chain_global_db_add_history_callback_notify(const char * a_group_prefix, dap_global_db_obj_callback_notify_t a_callback, void * a_arg) +void dap_chain_global_db_add_history_callback_notify(const char * a_group_prefix, + dap_global_db_obj_callback_notify_t a_callback, void * a_arg) { history_group_item_t * l_item = NULL; HASH_FIND_STR(s_history_group_items, a_group_prefix, l_item); - if ( l_item ){ + if(l_item) { l_item->callback_notify = a_callback; l_item->callback_arg = a_arg; - }else - log_it(L_WARNING, "Can't setup notify callback for groups with prefix %s. Possible not in history track state", a_group_prefix); + } else + log_it(L_WARNING, "Can't setup notify callback for groups with prefix %s. Possible not in history track state", + a_group_prefix); } - /** * Clean struct dap_global_db_obj_t */ @@ -159,7 +159,8 @@ void dap_chain_global_db_deinit(void) //dap_db_deinit(); unlock(); history_group_item_t * l_item = NULL, *l_item_tmp = NULL; - HASH_ITER(hh, s_history_group_items, l_item, l_item_tmp){ + HASH_ITER(hh, s_history_group_items, l_item, l_item_tmp) + { DAP_DELETE(l_item); } s_history_group_items = NULL; @@ -173,21 +174,23 @@ void dap_chain_global_db_deinit(void) */ void* dap_chain_global_db_obj_get(const char *a_key, const char *a_group) { - dap_store_obj_t *l_store_data = dap_db_read_data(a_group, a_key, NULL); + size_t l_count = 1; + // read one item + dap_store_obj_t *l_store_data = dap_chain_global_db_driver_read(a_group, a_key, &l_count); return l_store_data; -/* size_t count = 0; - if(!a_key) - return NULL; - size_t query_len = (size_t) snprintf(NULL, 0, "(&(cn=%s)(objectClass=%s))", a_key, a_group); - char *query = DAP_NEW_Z_SIZE(char, query_len + 1); //char query[32 + strlen(a_key)]; - snprintf(query, query_len + 1, "(&(cn=%s)(objectClass=%s))", a_key, a_group); // objectClass != ou - lock(); - dap_store_obj_t *store_data = dap_db_read_data(query, &count); - unlock(); - assert(count <= 1); - DAP_DELETE(query); - return store_data;*/ + /* size_t count = 0; + if(!a_key) + return NULL; + size_t query_len = (size_t) snprintf(NULL, 0, "(&(cn=%s)(objectClass=%s))", a_key, a_group); + char *query = DAP_NEW_Z_SIZE(char, query_len + 1); //char query[32 + strlen(a_key)]; + snprintf(query, query_len + 1, "(&(cn=%s)(objectClass=%s))", a_key, a_group); // objectClass != ou + lock(); + dap_store_obj_t *store_data = dap_db_read_data(query, &count); + unlock(); + assert(count <= 1); + DAP_DELETE(query); + return store_data;*/ } /** @@ -200,7 +203,10 @@ void* dap_chain_global_db_obj_get(const char *a_key, const char *a_group) uint8_t * dap_chain_global_db_gr_get(const char *a_key, size_t *a_data_len_out, const char *a_group) { uint8_t *l_ret_value = NULL; - dap_store_obj_t *l_store_data = dap_db_read_data(a_group, a_key, a_data_len_out); + // read several items, 0 - no limits + if(a_data_len_out) + *a_data_len_out = 0; + dap_store_obj_t *l_store_data = dap_chain_global_db_driver_read(a_group, a_key, a_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); @@ -209,27 +215,27 @@ uint8_t * dap_chain_global_db_gr_get(const char *a_key, size_t *a_data_len_out, } return l_ret_value; -/*ldb - * uint8_t *l_ret_value = NULL; - size_t l_count = 0; - if(!a_key) - return NULL; - size_t l_query_len =(size_t) snprintf(NULL, 0, "(&(cn=%s)(objectClass=%s))", a_key, a_group); - - char *l_query = DAP_NEW_Z_SIZE(char, l_query_len + 1); //char query[32 + strlen(a_key)]; - snprintf(l_query, l_query_len + 1, "(&(cn=%s)(objectClass=%s))", a_key, a_group); // objectClass != ou - lock(); - pdap_store_obj_t store_data = dap_db_read_data(l_query, &l_count); - unlock(); - if(l_count == 1 && store_data && !strcmp(store_data->key, a_key)) { - l_ret_value = (store_data->value) ? DAP_NEW_SIZE(uint8_t, store_data->value_len) : NULL; //ret_value = (store_data->value) ? strdup(store_data->value) : NULL; - memcpy(l_ret_value, store_data->value, store_data->value_len); - if(a_data_out) - *a_data_out = store_data->value_len; - } - dab_db_free_pdap_store_obj_t(store_data, l_count); - DAP_DELETE(l_query); - return l_ret_value;*/ + /*ldb + * uint8_t *l_ret_value = NULL; + size_t l_count = 0; + if(!a_key) + return NULL; + size_t l_query_len =(size_t) snprintf(NULL, 0, "(&(cn=%s)(objectClass=%s))", a_key, a_group); + + char *l_query = DAP_NEW_Z_SIZE(char, l_query_len + 1); //char query[32 + strlen(a_key)]; + snprintf(l_query, l_query_len + 1, "(&(cn=%s)(objectClass=%s))", a_key, a_group); // objectClass != ou + lock(); + pdap_store_obj_t store_data = dap_db_read_data(l_query, &l_count); + unlock(); + if(l_count == 1 && store_data && !strcmp(store_data->key, a_key)) { + l_ret_value = (store_data->value) ? DAP_NEW_SIZE(uint8_t, store_data->value_len) : NULL; //ret_value = (store_data->value) ? strdup(store_data->value) : NULL; + memcpy(l_ret_value, store_data->value, store_data->value_len); + if(a_data_out) + *a_data_out = store_data->value_len; + } + dap_store_obj_free(store_data, l_count); + DAP_DELETE(l_query); + return l_ret_value;*/ } uint8_t * dap_chain_global_db_get(const char *a_key, size_t *a_data_out) @@ -237,7 +243,6 @@ 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); } - /** * Set one entry to base */ @@ -245,38 +250,39 @@ bool dap_chain_global_db_gr_set(const char *a_key, const void *a_value, size_t a { pdap_store_obj_t store_data = DAP_NEW_Z_SIZE(dap_store_obj_t, sizeof(struct dap_store_obj)); store_data->type = 'a'; - store_data->key = strdup(a_key ); - store_data->value = DAP_NEW_Z_SIZE(uint8_t,a_value_len); + store_data->key = dap_strdup(a_key); + store_data->value = DAP_NEW_Z_SIZE(uint8_t, a_value_len); memcpy(store_data->value, a_value, a_value_len); - store_data->value_len = (a_value_len == (size_t) -1) ? strlen((const char* ) a_value) : a_value_len; - store_data->group = strdup(a_group); + store_data->value_len = (a_value_len == (size_t) -1) ? dap_strlen((const char*) a_value) : a_value_len; + store_data->group = dap_strdup(a_group); store_data->timestamp = time(NULL); lock(); - int l_res = dap_db_add(store_data, 1); + int l_res = dap_chain_global_db_driver_add(store_data, 1); unlock(); // Extract prefix if added successfuly, add history log and call notify callback if present - if (!l_res ){ - char * l_group_prefix = extract_group_prefix (a_group); + if(!l_res) { + char * l_group_prefix = extract_group_prefix(a_group); history_group_item_t * l_history_group_item = NULL; - if ( l_group_prefix ) + if(l_group_prefix) HASH_FIND_STR(s_history_group_items, l_group_prefix, l_history_group_item); - if ( l_history_group_item ){ - if ( l_history_group_item->auto_track ){ + if(l_history_group_item) { + if(l_history_group_item->auto_track) { lock(); dap_db_history_add('a', store_data, 1); unlock(); } - if ( l_history_group_item->callback_notify ) - l_history_group_item->callback_notify(l_history_group_item->callback_arg, 'a',l_group_prefix,a_group,a_key,a_value,a_value_len); + if(l_history_group_item->callback_notify) + l_history_group_item->callback_notify(l_history_group_item->callback_arg, 'a', l_group_prefix, a_group, + a_key, a_value, a_value_len); } - if ( l_group_prefix) - DAP_DELETE( l_group_prefix); - }else { - log_it(L_ERROR,"Save error: %d",l_res); + if(l_group_prefix) + DAP_DELETE(l_group_prefix); + } else { + log_it(L_ERROR, "Save error: %d", l_res); } DAP_DELETE(store_data); @@ -295,27 +301,28 @@ bool dap_chain_global_db_gr_del(const char *a_key, const char *a_group) if(!a_key) return NULL; pdap_store_obj_t store_data = DAP_NEW_Z_SIZE(dap_store_obj_t, sizeof(struct dap_store_obj)); - store_data->key = strdup( a_key); - store_data->group = strdup( a_group); + store_data->key = dap_strdup(a_key); + store_data->group = dap_strdup(a_group); lock(); - int l_res = dap_db_delete(store_data, 1); + int l_res = dap_chain_global_db_driver_delete(store_data, 1); unlock(); - if (!l_res){ + if(!l_res) { // Extract prefix - char * l_group_prefix = extract_group_prefix (a_group); + char * l_group_prefix = extract_group_prefix(a_group); history_group_item_t * l_history_group_item = NULL; - if ( l_group_prefix ) + if(l_group_prefix) HASH_FIND_STR(s_history_group_items, l_group_prefix, l_history_group_item); - if (l_history_group_item ){ + if(l_history_group_item) { if(l_history_group_item->auto_track) { lock(); dap_db_history_add('d', store_data, 1); unlock(); } - if ( l_history_group_item->callback_notify ) - l_history_group_item->callback_notify(l_history_group_item->callback_arg,'d',l_group_prefix,a_group, a_key, NULL, 0); + if(l_history_group_item->callback_notify) + l_history_group_item->callback_notify(l_history_group_item->callback_arg, 'd', l_group_prefix, a_group, + a_key, NULL, 0); } - if ( l_group_prefix ) + if(l_group_prefix) DAP_DELETE(l_group_prefix); } DAP_DELETE(store_data); @@ -335,45 +342,65 @@ bool dap_chain_global_db_del(const char *a_key) */ dap_global_db_obj_t** dap_chain_global_db_gr_load(const char *a_group, size_t *a_data_size_out) { - size_t l_query_len = (size_t) snprintf(NULL, 0, "(objectClass=%s)", a_group); - char *l_query = DAP_NEW_Z_SIZE(char, l_query_len + 1); - //const char *query = "(objectClass=addr_leased)"; - snprintf(l_query, l_query_len + 1, "(objectClass=%s)", a_group); size_t count = 0; // Read data lock(); - pdap_store_obj_t store_obj = dap_db_read_data(a_group, NULL, &count); + dap_store_obj_t *l_store_obj = dap_chain_global_db_driver_read(a_group, NULL, &count); unlock(); - DAP_DELETE(l_query); - // Serialization data - dap_store_obj_pkt_t *pkt = dap_store_packet_multiple(store_obj, 0, count); - dab_db_free_pdap_store_obj_t(store_obj, count); - if(pkt) - { - size_t count_new = 0; - pdap_store_obj_t store_data = dap_store_unpacket(pkt, &count_new); - assert(count_new == count); - //char **data = DAP_NEW_SIZE(char*, (count_new + 1) * sizeof(char*)); - dap_global_db_obj_t **data = DAP_NEW_Z_SIZE(dap_global_db_obj_t*, - (count_new + 1) * sizeof(dap_global_db_obj_t*)); // last item in mass must be zero - for(size_t i = 0; i < count_new; i++) { - pdap_store_obj_t store_data_cur = store_data + i; - assert(store_data_cur); - data[i] = DAP_NEW(dap_global_db_obj_t); - data[i]->key = strdup(store_data_cur->key); - data[i]->value_len = store_data_cur->value_len; - data[i]->value = DAP_NEW_Z_SIZE(uint8_t, store_data_cur->value_len + 1); - memcpy(data[i]->value, store_data_cur->value, store_data_cur->value_len); - } - DAP_DELETE(store_data); - DAP_DELETE(pkt); - if(a_data_size_out) - *a_data_size_out = count_new; - return data; + if(!l_store_obj || !count) + return NULL; + dap_global_db_obj_t **l_data = DAP_NEW_Z_SIZE(dap_global_db_obj_t*, + (count + 1) * sizeof(dap_global_db_obj_t*)); // last item in mass must be zero + for(size_t i = 0; i < count; i++) { + dap_store_obj_t *l_store_obj_cur = l_store_obj + i; + assert(l_store_obj_cur); + l_data[i] = DAP_NEW(dap_global_db_obj_t); + l_data[i]->key = dap_strdup(l_store_obj_cur->key); + l_data[i]->value_len = l_store_obj_cur->value_len; + l_data[i]->value = DAP_NEW_Z_SIZE(uint8_t, l_store_obj_cur->value_len + 1); + memcpy(l_data[i]->value, l_store_obj_cur->value, l_store_obj_cur->value_len); } + dap_store_obj_free(l_store_obj, count); if(a_data_size_out) - *a_data_size_out = 0; - return NULL; + *a_data_size_out = count; + return l_data; + /*size_t l_query_len = (size_t) snprintf(NULL, 0, "(objectClass=%s)", a_group); + char *l_query = DAP_NEW_Z_SIZE(char, l_query_len + 1); + //const char *query = "(objectClass=addr_leased)"; + snprintf(l_query, l_query_len + 1, "(objectClass=%s)", a_group); + size_t count = 0; + // Read data + lock(); + pdap_store_obj_t store_obj = dap_chain_global_db_driver_read(a_group, NULL, &count); + unlock(); + DAP_DELETE(l_query); + // Serialization data + dap_store_obj_pkt_t *pkt = dap_store_packet_multiple(store_obj, 0, count); + dap_store_obj_free(store_obj, count); + if(pkt) + { + size_t count_new = 0; + pdap_store_obj_t store_data = dap_store_unpacket_multiple(pkt, &count_new); + assert(count_new == count); + //char **data = DAP_NEW_SIZE(char*, (count_new + 1) * sizeof(char*)); + dap_global_db_obj_t **data = DAP_NEW_Z_SIZE(dap_global_db_obj_t*, + (count_new + 1) * sizeof(dap_global_db_obj_t*)); // last item in mass must be zero + for(size_t i = 0; i < count_new; i++) { + pdap_store_obj_t store_data_cur = store_data + i; + assert(store_data_cur); + data[i] = DAP_NEW(dap_global_db_obj_t); + data[i]->key = strdup(store_data_cur->key); + data[i]->value_len = store_data_cur->value_len; + data[i]->value = DAP_NEW_Z_SIZE(uint8_t, store_data_cur->value_len + 1); + memcpy(data[i]->value, store_data_cur->value, store_data_cur->value_len); + } + DAP_DELETE(store_data); + DAP_DELETE(pkt); + if(a_data_size_out) + *a_data_size_out = count_new; + return data; + }*/ + } dap_global_db_obj_t** dap_chain_global_db_load(size_t *a_data_size_out) @@ -387,7 +414,7 @@ dap_global_db_obj_t** dap_chain_global_db_load(size_t *a_data_size_out) */ bool dap_chain_global_db_obj_save(void* a_store_data, size_t a_objs_count) { - dap_store_obj_t* l_store_data = (dap_store_obj_t*) a_store_data; +/* dap_store_obj_t* l_store_data = (dap_store_obj_t*) a_store_data; if(l_store_data && a_objs_count > 0) { // real records size_t l_objs_count = a_objs_count; @@ -399,7 +426,7 @@ bool dap_chain_global_db_obj_save(void* a_store_data, size_t a_objs_count) size_t l_count = 0; char *l_query = dap_strdup_printf("(&(cn=%s)(objectClass=%s))", l_obj->key, l_obj->group); lock(); - dap_store_obj_t *l_read_store_data = dap_db_read_data(l_query,NULL, &l_count); + dap_store_obj_t *l_read_store_data = dap_chain_global_db_driver_read(l_query, NULL, &l_count); unlock(); // whether to add a record if(l_obj->type == 'a' && l_read_store_data) { @@ -419,57 +446,50 @@ bool dap_chain_global_db_obj_save(void* a_store_data, size_t a_objs_count) // reduce the number of real records l_objs_count--; } - dab_db_free_pdap_store_obj_t(l_read_store_data, l_count); + dap_store_obj_free(l_read_store_data, l_count); DAP_DELETE(l_query); - } + }*/ - // save/delete data - if(l_objs_count > 0) { + // save/delete data + if(!a_objs_count) + return true; - lock(); - int l_res = -1; - //add a record - if(l_store_data->type == 'a') - l_res = dap_db_add(l_store_data, a_objs_count); - //delete a record - if(l_store_data->type == 'd') - l_res = dap_db_delete(l_store_data, a_objs_count); - unlock(); - // Extract prefix if added successfuly, add history log and call notify callback if present - if (!l_res){ - for (size_t i =0; i< l_objs_count; i++ ){ - history_group_item_t * l_history_group_item = NULL; - dap_store_obj_t* l_obj = l_store_data + i; - char * l_group_prefix = extract_group_prefix (l_obj->group ); - if ( l_group_prefix ) - HASH_FIND_STR(s_history_group_items, l_group_prefix, l_history_group_item); - - if ( l_history_group_item ){ - if ( l_history_group_item->auto_track ){ - lock(); - dap_db_history_add(l_store_data->type, l_store_data, 1); - unlock(); - } - if ( l_history_group_item->callback_notify ){ - if (l_obj){ - l_history_group_item->callback_notify( l_history_group_item->callback_arg, l_store_data->type, - l_group_prefix, l_obj->group , l_obj->key, - l_obj->value, l_obj->value_len ); - }else { - break; - } - } + lock(); + int l_res = dap_chain_global_db_driver_appy(a_store_data, a_objs_count); + unlock(); + + // 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++) { + history_group_item_t * l_history_group_item = NULL; + dap_store_obj_t* l_obj = a_store_data + i; + char * l_group_prefix = extract_group_prefix(l_obj->group); + if(l_group_prefix) + HASH_FIND_STR(s_history_group_items, l_group_prefix, l_history_group_item); + + if(l_history_group_item) { + if(l_history_group_item->auto_track) { + lock(); + dap_db_history_add(l_obj->type, l_obj, 1); + unlock(); + } + if(l_history_group_item->callback_notify) { + if(l_obj) { + l_history_group_item->callback_notify(l_history_group_item->callback_arg, + l_obj->type, + l_group_prefix, l_obj->group, l_obj->key, + l_obj->value, l_obj->value_len); + } else { + break; } - DAP_DELETE( l_group_prefix); } - } - if(!l_res) - return true; + DAP_DELETE(l_group_prefix); } - else - return true; + } + if(!l_res) + return true; return false; } @@ -477,51 +497,56 @@ bool dap_chain_global_db_gr_save(dap_global_db_obj_t* a_objs, size_t a_objs_coun { dap_store_obj_t *l_store_data = DAP_NEW_Z_SIZE(dap_store_obj_t, a_objs_count * sizeof(struct dap_store_obj)); time_t l_timestamp = time(NULL); + char *l_group = dap_strdup(a_group); for(size_t q = 0; q < a_objs_count; ++q) { dap_store_obj_t *store_data_cur = l_store_data + q; dap_global_db_obj_t *a_obj_cur = a_objs + q; store_data_cur->key = a_obj_cur->key; - store_data_cur->group = strdup(a_group); + store_data_cur->group = l_group; store_data_cur->value = a_obj_cur->value; store_data_cur->value_len = a_obj_cur->value_len; store_data_cur->timestamp = l_timestamp; } if(l_store_data) { lock(); - int l_res = dap_db_add(l_store_data, a_objs_count); + int l_res = dap_chain_global_db_driver_add(l_store_data, a_objs_count); unlock(); - if (!l_res){ - for (size_t i =0; i< a_objs_count; i++ ){ + if(!l_res) { + for(size_t i = 0; i < a_objs_count; i++) { history_group_item_t * l_history_group_item = NULL; dap_store_obj_t *l_obj = l_store_data + i; - char * l_group_prefix = extract_group_prefix (l_obj->group ); - if ( l_group_prefix ) + char * l_group_prefix = extract_group_prefix(l_obj->group); + if(l_group_prefix) HASH_FIND_STR(s_history_group_items, l_group_prefix, l_history_group_item); - if ( l_history_group_item ){ - if ( l_history_group_item->auto_track ){ + if(l_history_group_item) { + if(l_history_group_item->auto_track) { lock(); dap_db_history_add('a', l_store_data, 1); unlock(); } - if ( l_history_group_item->callback_notify ){ - if (l_obj){ - l_history_group_item->callback_notify(l_history_group_item->callback_arg,'a',l_group_prefix, l_obj->group , l_obj->key, - l_obj->value, l_obj->value_len ); - }else { - break; - } + if(l_history_group_item->callback_notify) { + if(l_obj) { + l_history_group_item->callback_notify(l_history_group_item->callback_arg, 'a', + l_group_prefix, l_obj->group, l_obj->key, + l_obj->value, l_obj->value_len); + } else { + break; + } } } - DAP_DELETE( l_group_prefix); + DAP_DELETE(l_group_prefix); } } - DAP_DELETE(l_store_data); //dab_db_free_pdap_store_obj_t(store_data, a_objs_count); - if(!l_res) + DAP_DELETE(l_store_data); //dap_store_obj_free(store_data, a_objs_count); + if(!l_res){ + DAP_DELETE(l_group); return true; + } } + DAP_DELETE(l_group); return false; } @@ -537,21 +562,21 @@ bool dap_chain_global_db_save(dap_global_db_obj_t* a_objs, size_t a_objs_count) */ char* dap_chain_global_db_hash(const uint8_t *data, size_t data_size) { - return dap_db_driver_db_hash(data,data_size); + return dap_chain_global_db_driver_hash(data, data_size); } /** -* Parse data from dap_db_log_pack() -* -* return dap_store_obj_t* -*/ + * Parse data from dap_db_log_pack() + * + * return dap_store_obj_t* + */ void* dap_db_log_unpack(const void *a_data, size_t a_data_size, size_t *a_store_obj_count) { const dap_store_obj_pkt_t *l_pkt = (const dap_store_obj_pkt_t*) a_data; - if(!l_pkt || l_pkt->data_size != ( (size_t ) a_data_size - sizeof(dap_store_obj_pkt_t))) + if(!l_pkt || l_pkt->data_size != ((size_t) a_data_size - sizeof(dap_store_obj_pkt_t))) return NULL; size_t l_store_obj_count = 0; - dap_store_obj_t *l_obj = dap_store_unpacket(l_pkt, &l_store_obj_count); + dap_store_obj_t *l_obj = dap_store_unpacket_multiple(l_pkt, &l_store_obj_count); if(a_store_obj_count) *a_store_obj_count = l_store_obj_count; @@ -588,7 +613,7 @@ char* dap_db_log_get_diff(size_t *a_data_size_out) l_keys_vals[i] = l_obj_cur->key; l_keys_vals[i + l_data_size_out] = (char*) l_obj_cur->value; } - if (a_data_size_out) + if(a_data_size_out) *a_data_size_out = l_data_size_out; // last element - NULL (marker) l_keys_vals[l_data_size_out * 2] = NULL; diff --git a/dap_chain_global_db_driver.c b/dap_chain_global_db_driver.c index 2cd50549fd13c860a2db31f1099c330acbdc1298..9e67016b43b565101c7d94e2facff7933c06e4aa 100644 --- a/dap_chain_global_db_driver.c +++ b/dap_chain_global_db_driver.c @@ -160,12 +160,126 @@ void dap_store_obj_free(dap_store_obj_t *a_store_obj, size_t a_store_count) DAP_DELETE(a_store_obj); } +static size_t dap_db_get_size_pdap_store_obj_t(pdap_store_obj_t store_obj) +{ + size_t size = sizeof(uint32_t) + 2 * sizeof(uint16_t) + sizeof(size_t) + sizeof(time_t) + dap_strlen(store_obj->group) + + dap_strlen(store_obj->key) + store_obj->value_len; + return size; +} + +/** + * serialization + * @param a_store_obj_count count of structures store_obj + * @param a_timestamp create data time + * @param a_size_out[out] size of output structure + * @return NULL in case of an error + */ +dap_store_obj_pkt_t *dap_store_packet_multiple(pdap_store_obj_t a_store_obj, time_t a_timestamp, size_t a_store_obj_count) +{ + if(!a_store_obj || a_store_obj_count < 1) + return NULL; + size_t l_data_size_out = sizeof(uint32_t); // size of output data + // calculate output structure size + for(size_t l_q = 0; l_q < a_store_obj_count; ++l_q) + l_data_size_out += dap_db_get_size_pdap_store_obj_t(&a_store_obj[l_q]); + + dap_store_obj_pkt_t *l_pkt = DAP_NEW_Z_SIZE(dap_store_obj_pkt_t, sizeof(dap_store_obj_pkt_t) + l_data_size_out); + l_pkt->data_size = l_data_size_out; + l_pkt->timestamp = a_timestamp; + uint64_t l_offset = 0; + uint32_t l_count = (uint32_t) a_store_obj_count; + memcpy(l_pkt->data + l_offset, &l_count, sizeof(uint32_t)); + l_offset += sizeof(uint32_t); + for( size_t l_q = 0; l_q < a_store_obj_count; ++l_q) { + dap_store_obj_t obj = a_store_obj[l_q]; + //uint16_t section_size = (uint16_t) dap_strlen(obj.section); + uint16_t group_size = (uint16_t) dap_strlen(obj.group); + uint16_t key_size = (uint16_t) dap_strlen(obj.key); + memcpy(l_pkt->data + l_offset, &obj.type, sizeof(int)); + l_offset += sizeof(int); + //memcpy(l_pkt->data + l_offset, §ion_size, sizeof(uint16_t)); + //l_offset += sizeof(uint16_t); + //memcpy(l_pkt->data + l_offset, obj.section, section_size); + //l_offset += section_size; + memcpy(l_pkt->data + l_offset, &group_size, sizeof(uint16_t)); + l_offset += sizeof(uint16_t); + memcpy(l_pkt->data + l_offset, obj.group, group_size); + l_offset += group_size; + memcpy(l_pkt->data + l_offset, &obj.timestamp, sizeof(time_t)); + l_offset += sizeof(time_t); + memcpy(l_pkt->data + l_offset, &key_size, sizeof(uint16_t)); + l_offset += sizeof(uint16_t); + memcpy(l_pkt->data + l_offset, obj.key, key_size); + l_offset += key_size; + memcpy(l_pkt->data + l_offset, &obj.value_len, sizeof(size_t)); + l_offset += sizeof(size_t); + memcpy(l_pkt->data + l_offset, obj.value, obj.value_len); + l_offset += obj.value_len; + } + assert(l_data_size_out == l_offset); + return l_pkt; +} +/** + * deserialization + * @param store_obj_count[out] count of the output structures store_obj + * @return NULL in case of an error* + */ + +dap_store_obj_t *dap_store_unpacket_multiple(const dap_store_obj_pkt_t *pkt, size_t *store_obj_count) +{ + if(!pkt || pkt->data_size < 1) + return NULL; + uint64_t offset = 0; + uint32_t count; + memcpy(&count, pkt->data, sizeof(uint32_t)); + offset += sizeof(uint32_t); + dap_store_obj_t *store_obj = DAP_NEW_Z_SIZE(dap_store_obj_t, count * sizeof(struct dap_store_obj)); + for(size_t q = 0; q < count; ++q) { + dap_store_obj_t *obj = store_obj + q; + uint16_t str_size; + memcpy(&obj->type, pkt->data + offset, sizeof(int)); + offset += sizeof(int); + + //memcpy(&str_size, pkt->data + offset, sizeof(uint16_t)); + //offset += sizeof(uint16_t); + //obj->section = DAP_NEW_Z_SIZE(char, str_size + 1); + //memcpy(obj->section, pkt->data + offset, str_size); + //offset += str_size; + + memcpy(&str_size, pkt->data + offset, sizeof(uint16_t)); + offset += sizeof(uint16_t); + obj->group = DAP_NEW_Z_SIZE(char, str_size + 1); + memcpy(obj->group, pkt->data + offset, str_size); + offset += str_size; + + memcpy(&obj->timestamp, pkt->data + offset, sizeof(time_t)); + offset += sizeof(time_t); + + memcpy(&str_size, pkt->data + offset, sizeof(uint16_t)); + offset += sizeof(uint16_t); + obj->key = DAP_NEW_Z_SIZE(char, str_size + 1); + memcpy(obj->key, pkt->data + offset, str_size); + offset += str_size; + + memcpy(&obj->value_len, pkt->data + offset, sizeof(size_t)); + offset += sizeof(size_t); + + obj->value = DAP_NEW_Z_SIZE(uint8_t, obj->value_len + 1); + memcpy(obj->value, pkt->data + offset, obj->value_len); + offset += obj->value_len; + } + assert(pkt->data_size == offset); + if(store_obj_count) + *store_obj_count = count; + return store_obj; +} + /** * Calc hash for data * * return hash or NULL */ -char* dap_db_driver_db_hash(const uint8_t *data, size_t data_size) +char* dap_chain_global_db_driver_hash(const uint8_t *data, size_t data_size) { if(!data || data_size <= 0) return NULL; @@ -311,7 +425,7 @@ static void* func_write_buf(void * arg) pthread_exit(0); } -int dap_db_add(pdap_store_obj_t a_store_obj, size_t a_store_count) +int dap_chain_global_db_driver_appy(pdap_store_obj_t a_store_obj, size_t a_store_count) { //dap_store_obj_t *l_store_obj = dap_store_obj_copy(a_store_obj, a_store_count); if(!a_store_obj || !a_store_count) @@ -344,19 +458,33 @@ int dap_db_add(pdap_store_obj_t a_store_obj, size_t a_store_count) return 0; } -int dap_db_delete(pdap_store_obj_t a_store_obj, size_t a_store_count) +int dap_chain_global_db_driver_add(pdap_store_obj_t a_store_obj, size_t a_store_count) +{ + a_store_obj->type = 'd'; + return dap_chain_global_db_driver_appy(a_store_obj, a_store_count); +} + +int dap_chain_global_db_driver_delete(pdap_store_obj_t a_store_obj, size_t a_store_count) { a_store_obj->type = 'd'; - return dap_db_add(a_store_obj, a_store_count); + return dap_chain_global_db_driver_appy(a_store_obj, a_store_count); } -dap_store_obj_t* dap_db_read_data(const char *a_group, const char *a_key, size_t *count_out) +/** + * Read several items + * + * a_group - group name + * a_key - key name, may by NULL, it means reading the whole group + * a_count_out[in], how many items to read, 0 - no limits + * a_count_out[out], how many items was read + */ +dap_store_obj_t* dap_chain_global_db_driver_read(const char *a_group, const char *a_key, size_t *a_count_out) { dap_store_obj_t *l_ret = NULL; // wait apply write buffer wait_write_buf(); - // read record + // read records using the selected database engine if(s_drv_callback.read_store_obj) - l_ret = s_drv_callback.read_store_obj(a_group, a_key, count_out); + l_ret = s_drv_callback.read_store_obj(a_group, a_key, a_count_out); return l_ret; } diff --git a/dap_chain_global_db_driver.h b/dap_chain_global_db_driver.h index 9d819aac2198e3a05af11c3d24c4cbc1d80963a7..efd2631763ae086f76531870362e8b32af1cb684 100644 --- a/dap_chain_global_db_driver.h +++ b/dap_chain_global_db_driver.h @@ -65,20 +65,17 @@ void dap_db_driver_deinit(void); dap_store_obj_t* dap_store_obj_copy(dap_store_obj_t *a_store_obj, size_t a_store_count); void dap_store_obj_free(dap_store_obj_t *a_store_obj, size_t a_store_count); -char* dap_db_driver_db_hash(const uint8_t *data, size_t data_size); +char* dap_chain_global_db_driver_hash(const uint8_t *data, size_t data_size); -int dap_db_add(pdap_store_obj_t a_store_obj, size_t a_store_count); -int dap_db_delete(pdap_store_obj_t a_store_obj, size_t a_store_count); -dap_store_obj_t* dap_db_read_data(const char *a_group, const char *a_key, size_t *count_out); +int dap_chain_global_db_driver_appy(pdap_store_obj_t a_store_obj, size_t a_store_count); +int dap_chain_global_db_driver_add(pdap_store_obj_t a_store_obj, size_t a_store_count); +int dap_chain_global_db_driver_delete(pdap_store_obj_t a_store_obj, size_t a_store_count); +dap_store_obj_t* dap_chain_global_db_driver_read(const char *a_group, const char *a_key, size_t *count_out); -pdap_store_obj_t dap_db_read_file_data(const char *a_path, const char *a_group); // state of emergency only, if LDB database is inaccessible -dap_store_obj_pkt_t *dap_store_packet_single(pdap_store_obj_t a_store_obj); dap_store_obj_pkt_t *dap_store_packet_multiple(pdap_store_obj_t a_store_obj, time_t a_timestamp, size_t a_store_obj_count); -dap_store_obj_t *dap_store_unpacket(const dap_store_obj_pkt_t *a_pkt, +dap_store_obj_t *dap_store_unpacket_multiple(const dap_store_obj_pkt_t *a_pkt, size_t *a_store_obj_count); -void dab_db_free_pdap_store_obj_t(pdap_store_obj_t a_store_data, - size_t a_count); #endif //_GLOBAL_DB_DRIVER_H_ diff --git a/dap_chain_global_db_driver_sqlite.c b/dap_chain_global_db_driver_sqlite.c index ef8984ba5981c5b33498f785a8e7803af63c0a7d..e3ec3ef143f9c7ca3b0fae1f0f3e3b1a5696f61e 100644 --- a/dap_chain_global_db_driver_sqlite.c +++ b/dap_chain_global_db_driver_sqlite.c @@ -91,9 +91,9 @@ int dap_db_driver_sqlite_init(const char *a_filename_db, dap_db_driver_callbacks printf("can't set new journal mode\n"); if(!dap_db_driver_sqlite_set_pragma(s_db, "page_size", "1024")) // DELETE | TRUNCATE | PERSIST | MEMORY | WAL | OFF - printf("can't set page_size\n"); - // *PRAGMA page_size = bytes; // page size DB; it is reasonable to make it equal to the size of the disk cluster 4096 - // *PRAGMA cache_size = -kibibytes; // by default it is equal to 2000 pages of database + printf("can't set page_size\n"); + // *PRAGMA page_size = bytes; // page size DB; it is reasonable to make it equal to the size of the disk cluster 4096 + // *PRAGMA cache_size = -kibibytes; // by default it is equal to 2000 pages of database // a_drv_callback->apply_store_obj = dap_db_driver_sqlite_apply_store_obj; a_drv_callback->read_store_obj = dap_db_driver_sqlite_read_store_obj; @@ -268,16 +268,10 @@ static int dap_db_driver_sqlite_create_group_table(const char *a_table_name) * SELECT * FROM data WHERE hex(sd) LIKE '%370%' * hex(x'0806') -> '08f6' или quote(sd) -> X'08f6' * substr(x'031407301210361320690000',3,2) -> x'0730' - * преобразование типов: + * * CAST(substr(sd,5,2) as TEXT) * additional function of line to number _uint8 * byte_to_bin(x'ff') -> 255 - * логичеÑкие операции: - // [out] res - идентификатор запроÑа, памÑÑ‚ÑŒ нужно будет удалÑÑ‚ÑŒ через dap_db_driver_sqlite_query_free() - // "SELECT name FROM sqlite_master WHERE type='table' ORDER BY name" - // [out] error_message - Ñюда будет запиÑано текÑтовое Ñообщение об ошибке (памÑÑ‚ÑŒ требует ÑƒÐ´Ð°Ð»ÐµÐ½Ð¸Ñ Ñ‡ÐµÑ€ÐµÐ· sqlite_free()) - // return: возвращает код ошибки SQL (еÑли не равно SQLITE_OK(0) то ошибка) - * return 0 if Ok, else error code >0 */ static int dap_db_driver_sqlite_query(sqlite3 *db, char *query, sqlite3_stmt **l_res, char **l_error_message) { @@ -493,17 +487,40 @@ int dap_db_driver_sqlite_apply_store_obj(dap_store_obj_t *a_store_obj) } /** - * Read data - * a_key may be NULL + * Read several items + * + * a_group - group name + * a_key - key name, may by NULL, it means reading the whole group + * a_count_out[in], how many items to read, 0 - no limits + * a_count_out[out], how many items was read */ -dap_store_obj_t* dap_db_driver_sqlite_read_store_obj(const char *a_group, const char *a_key) +dap_store_obj_t* dap_db_driver_sqlite_read_store_obj(const char *a_group, const char *a_key, size_t *a_count_out) { dap_store_obj_t *l_obj = NULL; char *l_error_message = NULL; sqlite3_stmt *l_res; - if(!a_group || !a_key) + if(!a_group) return NULL; - char *l_str_query = sqlite3_mprintf("SELECT ts,value FROM '%s' WHERE key='%s' LIMIT 1", a_group, a_key); + // no limit + int l_count_out = 0; + if(a_count_out) + l_count_out = *a_count_out; + char *l_str_query; + if(a_key) { + if(l_count_out) + l_str_query = sqlite3_mprintf("SELECT ts,key,value FROM '%s' WHERE key='%s' LIMIT %d ORDER BY id ASC", + a_group, a_key, l_count_out); + else + l_str_query = sqlite3_mprintf("SELECT ts,key,value FROM '%s' WHERE key='%s' ORDER BY id ASC", a_group, + a_key); + } + else { + if(l_count_out) + l_str_query = sqlite3_mprintf("SELECT ts,key,value FROM '%s' LIMIT %d ORDER BY id ASC", + a_group, a_key, l_count_out); + else + l_str_query = sqlite3_mprintf("SELECT ts,key,value FROM '%s' ORDER BY id ASC", a_group, a_key); + } int l_ret = dap_db_driver_sqlite_query(s_db, l_str_query, &l_res, &l_error_message); sqlite3_free(l_str_query); if(l_ret != SQLITE_OK) { @@ -511,7 +528,11 @@ dap_store_obj_t* dap_db_driver_sqlite_read_store_obj(const char *a_group, const dap_db_driver_sqlite_free(l_error_message); return NULL; } + + //int b = qlite3_column_count(s_db); SQLITE_ROW_VALUE *l_row = NULL; + l_count_out = 0; + int l_count_sized = 0; do { l_ret = dap_db_driver_sqlite_fetch_array(l_res, &l_row); if(l_ret != SQLITE_ROW && l_ret != SQLITE_DONE) @@ -519,31 +540,45 @@ dap_store_obj_t* dap_db_driver_sqlite_read_store_obj(const char *a_group, const log_it(L_ERROR, "read l_ret=%d, %s\n", sqlite3_errcode(s_db), sqlite3_errmsg(s_db)); } if(l_ret == SQLITE_ROW && l_row) { - l_obj = DAP_NEW_Z(dap_store_obj_t); - l_obj->group = dap_strdup(a_group); - l_obj->key = dap_strdup(a_key); + if(l_count_out >= l_count_sized) { + l_count_sized += 10; + l_obj = DAP_REALLOC(l_obj, sizeof(dap_store_obj_t) * l_count_sized); + memset(l_obj + l_count_out, 0, sizeof(dap_store_obj_t) * (l_count_sized - l_count_out)); + } + dap_store_obj_t *l_obj_cur = l_obj + l_count_out; + + l_obj_cur->group = dap_strdup(a_group); + l_obj_cur->key = dap_strdup(a_key); for(int l_iCol = 0; l_iCol < l_row->count; l_iCol++) { SQLITE_VALUE *cur_val = l_row->val + l_iCol; switch (l_iCol) { case 0: if(cur_val->type == SQLITE_INTEGER) - l_obj->timestamp = cur_val->val.val_int64; - break; // id + l_obj_cur->timestamp = cur_val->val.val_int64; + break; // ts case 1: + if(cur_val->type == SQLITE_TEXT) + l_obj_cur->key = dap_strdup(cur_val->val.val_str); + break; // key + case 2: if(cur_val->type == SQLITE_BLOB) { - l_obj->value_len = (size_t) cur_val->len; - l_obj->value = DAP_NEW_SIZE(uint8_t, l_obj->value_len); - memcpy(l_obj->value, cur_val->val.val_blob, l_obj->value_len); + l_obj_cur->value_len = (size_t) cur_val->len; + l_obj_cur->value = DAP_NEW_SIZE(uint8_t, l_obj_cur->value_len); + memcpy(l_obj_cur->value, cur_val->val.val_blob, l_obj_cur->value_len); } + break;// value } } + l_count_out++; } dap_db_driver_sqlite_row_free(l_row); } while(l_row); dap_db_driver_sqlite_query_free(l_res); + if(a_count_out) + *a_count_out = l_count_out; return l_obj; } diff --git a/dap_chain_global_db_driver_sqlite.h b/dap_chain_global_db_driver_sqlite.h index f75b770103443a4ebddb6c9fcbd325074976e6f1..bb33f18a8d7abe5facb2e3e6ae056dd714aaa9db 100644 --- a/dap_chain_global_db_driver_sqlite.h +++ b/dap_chain_global_db_driver_sqlite.h @@ -44,4 +44,4 @@ int dap_db_driver_sqlite_end_transaction(void); // Apply data (write or delete) int dap_db_driver_sqlite_apply_store_obj(dap_store_obj_t *a_store_obj); // Read data -dap_store_obj_t* dap_db_driver_sqlite_read_store_obj(const char *a_group, const char *a_key); +dap_store_obj_t* dap_db_driver_sqlite_read_store_obj(const char *a_group, const char *a_key, size_t *a_count_out); diff --git a/dap_chain_global_db_hist.c b/dap_chain_global_db_hist.c index f95ce13c8b0288c34d3fb6599604f0ce60abf160..345858e202beac3a4d1a174a6a086d5fa5c02011 100755 --- a/dap_chain_global_db_hist.c +++ b/dap_chain_global_db_hist.c @@ -82,7 +82,7 @@ uint8_t* dap_db_log_pack(dap_global_db_obj_t *a_obj, size_t *a_data_size_out) l_obj->key = dap_strdup(l_keys[i]); } if (l_obj == NULL){ - dab_db_free_pdap_store_obj_t(l_store_obj, l_count); + dap_store_obj_free(l_store_obj, l_count); dap_strfreev(l_keys); return NULL; } @@ -96,7 +96,7 @@ uint8_t* dap_db_log_pack(dap_global_db_obj_t *a_obj, size_t *a_data_size_out) // serialize data dap_store_obj_pkt_t *l_data_out = dap_store_packet_multiple(l_store_obj, l_timestamp, l_count); - dab_db_free_pdap_store_obj_t(l_store_obj, l_count); + dap_store_obj_free(l_store_obj, l_count); dap_strfreev(l_keys); if(l_data_out && a_data_size_out) { @@ -148,8 +148,7 @@ bool dap_db_history_add(char a_type, pdap_store_obj_t a_store_obj, size_t a_dap_ l_store_data.value_len = l_str_len+1; l_store_data.group = GROUP_LOCAL_HISTORY; l_store_data.timestamp = time(NULL); - int l_res = dap_db_add(&l_store_data, 1); - //printf("!!!\n!!!HISTORY store save l_res=%d ts=%lld text=%s\n!!!\n",l_res,l_store_data.timestamp,l_str); + int l_res = dap_chain_global_db_driver_add(&l_store_data, 1); if(l_rec.keys_count > 1) DAP_DELETE(l_rec.keys); DAP_DELETE(l_str); diff --git a/dap_chain_global_db_hist.h b/dap_chain_global_db_hist.h index b21d6341919d89f021b6384cebf05151db39e041..62e98c5844bf6cc84f79563db42850d416a41761 100755 --- a/dap_chain_global_db_hist.h +++ b/dap_chain_global_db_hist.h @@ -1,7 +1,7 @@ #pragma once #include <stdbool.h> -#include "dap_chain_global_db_pvt.h" +#include "dap_chain_global_db_driver.h" #define GLOBAL_DB_HIST_REC_SEPARATOR "\r;" #define GLOBAL_DB_HIST_KEY_SEPARATOR "\a;" diff --git a/dap_chain_global_db_pvt.c b/dap_chain_global_db_pvt.c deleted file mode 100755 index 52a0028bc0980d618dae92bd682b4b5337832ada..0000000000000000000000000000000000000000 --- a/dap_chain_global_db_pvt.c +++ /dev/null @@ -1,575 +0,0 @@ -#include <string.h> -#include <stdio.h> -#include <assert.h> -#include <time.h> - -#include "dap_chain_global_db.h" -#include "dap_chain_global_db_pvt.h" -#include "dap_strfuncs.h" -#include "dap_list.h" - -#define LOG_TAG "dap_global_db" -#define TDB_PREFIX_LEN 7 - -static struct ldb_context *s_ldb = NULL; -static TALLOC_CTX *s_mem_ctx = NULL; - -//static int dap_store_len = 0; // initialized only when reading from local db -static char *dap_db_path = NULL; - -#define CALL2(a, b, ...) (a), (b) -#define dap_db_add_record(...) dap_db_merge(CALL2(__VA_ARGS__, 0)) - -static int dap_db_add_msg(struct ldb_message *a_msg) -{ - if(ldb_msg_sanity_check(s_ldb, a_msg) != LDB_SUCCESS) { - log_it(L_ERROR, "LDB message is inconsistent: %s", ldb_errstring(s_ldb)); - return -1; - } - ldb_transaction_start(s_ldb); - int status = ldb_add(s_ldb, a_msg); - // Delete the entry if it already exist and add again - if(status == LDB_ERR_ENTRY_ALREADY_EXISTS) { - ldb_delete(s_ldb, a_msg->dn); - status = ldb_add(s_ldb, a_msg); - } - if(status != LDB_SUCCESS) { - if(status == LDB_ERR_ENTRY_ALREADY_EXISTS) { - log_it(L_INFO, "Entry %s already present, skipped", ldb_dn_get_linearized(a_msg->dn)); - } - else { - log_it(L_ERROR, "LDB adding error: %s", ldb_errstring(s_ldb)); - } - ldb_transaction_cancel(s_ldb); - return -2; - } - else { - ldb_transaction_commit(s_ldb); - //log_it(L_INFO, "Entry %s added", ldb_dn_get_linearized(a_msg->dn)); - return 0; - } -} - -/** - * @brief dap_db_group_create - * @param a_group - */ -void dap_db_group_create(const char * a_group) -{ - struct ldb_message *msg; - - // level 2: group record - msg = ldb_msg_new(s_ldb); - msg->dn = ldb_dn_new(s_mem_ctx, s_ldb, "ou=addrs_leased,dc=kelvin_nodes"); - ldb_msg_add_string(msg, "ou", a_group ); - ldb_msg_add_string(msg, "objectClass", "group"); - ldb_msg_add_string(msg, "section", "kelvin_nodes"); - ldb_msg_add_string(msg, "description", "Whitelist of Kelvin blockchain nodes"); - dap_db_add_msg(msg); - talloc_free(msg->dn); - talloc_free(msg); - -} - -/** - * @brief dap_db_init - * @param path - * @return - */ -int dap_db_init(const char *path) -{ - s_mem_ctx = talloc_new(NULL); - if(ldb_global_init() != 0) { - log_it(L_ERROR, "Couldn't initialize LDB's global information"); - return -1; - }; - if((s_ldb = ldb_init(s_mem_ctx, NULL)) != LDB_SUCCESS) { - log_it(L_INFO, "ldb context initialized"); - char *l_tdb_path = DAP_NEW_Z_SIZE(char,strlen(path) + TDB_PREFIX_LEN ); - memset(l_tdb_path, '\0', strlen(path) + TDB_PREFIX_LEN); - strcat(l_tdb_path, "tdb://"); // using tdb for simplicity, no need for separate LDAP server - strcat(l_tdb_path, path); - struct ldb_result *data_message; - if(ldb_connect(s_ldb, l_tdb_path, 0, NULL) != LDB_SUCCESS) { - log_it(L_ERROR, "Couldn't connect to database"); - DAP_DELETE(l_tdb_path); - return 1; - } - dap_db_path = strdup(l_tdb_path); - const char *query = "(dn=*)"; - if(ldb_search(s_ldb, s_mem_ctx, &data_message, NULL, LDB_SCOPE_DEFAULT, NULL, "%s", query) != LDB_SUCCESS) { - log_it(L_ERROR, "Database querying failed"); - DAP_DELETE(l_tdb_path); - return 2; - } - struct ldb_message *msg; - if(data_message->count == 0) { - // level 1: section record - msg = ldb_msg_new(s_ldb); - msg->dn = ldb_dn_new(s_mem_ctx, s_ldb, "dc=kelvin_nodes"); - ldb_msg_add_string(msg, "dc", "kelvin_nodes"); - ldb_msg_add_string(msg, "objectClass", "top"); - ldb_msg_add_string(msg, "objectClass", "section"); - dap_db_add_msg(msg); - - // level 2: groups - dap_db_group_create( GROUP_LOCAL_HISTORY); - dap_db_group_create( GROUP_LOCAL_GENERAL ); - dap_db_group_create( GROUP_LOCAL_NODE_LAST_TS); - - } - talloc_free(data_message); - DAP_DELETE(l_tdb_path); - return 0; - } - else { - log_it(L_ERROR, "Couldn't initialize LDB context"); - return -2; - } -} - -int dap_db_del_msg(struct ldb_dn *ldn) -{ - ldb_transaction_start(s_ldb); - int status = ldb_delete(s_ldb, ldn); - if(status != LDB_SUCCESS) { - log_it(L_ERROR, "LDB deleting error: %s", ldb_errstring(s_ldb)); - ldb_transaction_cancel(s_ldb); - return -2; - } - else { - ldb_transaction_commit(s_ldb); - //log_it(L_INFO, "Entry %s deleted", ldb_dn_get_linearized(ldn)); - return 0; - } -} - -static int compare_message_items(const void * l_a, const void * l_b) -{ - const struct ldb_message *l_item_a = (const struct ldb_message*) l_a; - const struct ldb_message *l_item_b = (const struct ldb_message*) l_b; - const struct ldb_val *l_val_a = ldb_msg_find_ldb_val(l_item_a, "time"); - const struct ldb_val *l_val_b = ldb_msg_find_ldb_val(l_item_b, "time"); - time_t timestamp_a = 0; - time_t timestamp_b = 0; - if(l_val_a) - memcpy(×tamp_a, l_val_a->data, min(sizeof(time_t), l_val_a->length)); - if(l_val_b) - memcpy(×tamp_b, l_val_b->data, min(sizeof(time_t), l_val_b->length)); - if(timestamp_a == timestamp_b) - return 0; - if(timestamp_a < timestamp_b) - return -1; - return 1; -} - -/** - * Get data from base - * - * query RFC2254 (The String Representation of LDAP Search Filters) - * sample: - * (uid=testuser) Matches to all users that have exactly the value testuser for the attribute uid. - * (uid=test*) Matches to all users that have values for the attribute uid that start with test. - * (!(uid=test*)) Matches to all users that have values for the attribute uid that do not start with test. - * (&(department=1234)(city=Paris)) Matches to all users that have exactly the value 1234 for the attribute department and exactly the value Paris for the attribute city . - * - */ -pdap_store_obj_t dap_db_read_data_ldb(const char *a_query, size_t *a_count) -{ - struct ldb_result *data_message; - /* - CN commonName (2.5.4.3) - L localityName (2.5.4.7) - ST stateOrProvinceName (2.5.4.8) - O organizationName (2.5.4.10) - OU organizationalUnitName (2.5.4.11) - C countryName (2.5.4.6) - STREET streetAddress (2.5.4.9) - DC domainComponent (0.9.2342.19200300.100.1.25) - UID userId (0.9.2342.19200300.100.1.1) - */ - if(ldb_connect(s_ldb, dap_db_path, LDB_FLG_RDONLY, NULL) != LDB_SUCCESS) { - log_it(L_ERROR, "Couldn't connect to database"); - return NULL; - } - //sample: query = "(objectClass=addr_leased)"; - if(ldb_search(s_ldb, NULL, &data_message, NULL, LDB_SCOPE_DEFAULT, NULL, a_query) != LDB_SUCCESS) { - log_it(L_ERROR, "Database querying failed"); - return NULL; - } - //log_it(L_INFO, "Obtained binary data, %d entries", data_message->count); - - // not found data - if(!data_message->count ) { - talloc_free(data_message); - return NULL; - } - - pdap_store_obj_t store_data = DAP_NEW_Z_SIZE(dap_store_obj_t, data_message->count * sizeof(struct dap_store_obj)); - if(!store_data) { - log_it(L_ERROR, "Couldn't allocate memory, store objects unobtained"); - talloc_free(data_message); - return NULL; - } - - dap_list_t *l_list_items = NULL; - // fill list - for(size_t i = 0; i < data_message->count; i++) { - l_list_items = dap_list_prepend(l_list_items, data_message->msgs[i]); - } - // sort list by time - l_list_items = dap_list_sort(l_list_items, (dap_callback_compare_t) compare_message_items); - - dap_list_t *l_list = l_list_items; - size_t q = 0; - while(l_list) { - const struct ldb_message *l_msgs = l_list->data; - store_data[q].section = strdup(ldb_msg_find_attr_as_string(l_msgs, "section", "")); //strdup("kelvin_nodes"); - store_data[q].group = strdup(ldb_msg_find_attr_as_string(l_msgs, "objectClass", "")); //strdup(group); - store_data[q].type = 1; - store_data[q].key = strdup(ldb_msg_find_attr_as_string(l_msgs, "cn", "")); - // get timestamp - const struct ldb_val *l_val = ldb_msg_find_ldb_val(l_msgs, "time"); - if(l_val) { - memcpy(&store_data[q].timestamp, l_val->data, min(sizeof(time_t), l_val->length)); - } - // get value - l_val = ldb_msg_find_ldb_val(l_msgs, "val"); - if(l_val) { - store_data[q].value_len = l_val->length; - store_data[q].value = DAP_NEW_SIZE(uint8_t, l_val->length); - memcpy(store_data[q].value, l_val->data, l_val->length); - } - q++; - l_list = dap_list_next(l_list); - //log_it(L_INFO, "Record %s read successfully", ldb_dn_get_linearized(data_message->msgs[q]->dn)); - } - size_t dap_store_len = data_message->count; - /*for(size_t q = 0; q < dap_store_len; ++q) { - store_data[q].section = strdup(ldb_msg_find_attr_as_string(data_message->msgs[q], "section", "")); //strdup("kelvin_nodes"); - store_data[q].group = strdup(ldb_msg_find_attr_as_string(data_message->msgs[q], "objectClass", "")); //strdup(group); - store_data[q].type = 1; - store_data[q].key = strdup(ldb_msg_find_attr_as_string(data_message->msgs[q], "cn", "")); - // get timestamp - const struct ldb_val *l_val = ldb_msg_find_ldb_val(data_message->msgs[q], "time"); - if(l_val) { - memcpy(&store_data[q].timestamp, l_val->data, min(sizeof(time_t), l_val->length)); - } - // get value - l_val = ldb_msg_find_ldb_val(data_message->msgs[q], "val"); - if(l_val) { - store_data[q].value_len = l_val->length; - store_data[q].value = DAP_NEW_SIZE(uint8_t, l_val->length); - memcpy(store_data[q].value, l_val->data, l_val->length); - } - //log_it(L_INFO, "Record %s read successfully", ldb_dn_get_linearized(data_message->msgs[q]->dn)); - }*/ - talloc_free(data_message); - dap_list_free(l_list_items); - if(a_count) - *a_count = dap_store_len; - return store_data; -} - -/** - * clean memory - */ -void dab_db_free_pdap_store_obj_t(pdap_store_obj_t store_data, size_t count) -{ - if(!store_data) - return; - for(size_t i = 0; i < count; i++) { - pdap_store_obj_t store_one = store_data + i; - DAP_DELETE(store_one->section); - DAP_DELETE(store_one->group); - DAP_DELETE(store_one->key); - DAP_DELETE(store_one->value); - } - DAP_DELETE(store_data); -} - -/* Get the entire content without using query expression - * This function is highly dissuaded from being used - * */ -pdap_store_obj_t dap_db_read_file_data(const char *path, const char *group) -{ - struct ldb_ldif *ldif_msg; - FILE *fs = fopen(path, "r"); - if(!fs) { - log_it(L_ERROR, "Can't open file %s", path); - return NULL; - } - pdap_store_obj_t store_data = (pdap_store_obj_t) malloc(256 * sizeof(dap_store_obj_t)); - if(store_data != NULL) { - log_it(L_INFO, "We're about to put entries in store objects"); - } - else { - log_it(L_ERROR, "Couldn't allocate memory, store objects unobtained"); - fclose(fs); - return NULL; - } - - size_t q = 0; - for(ldif_msg = ldb_ldif_read_file(s_ldb, fs); ldif_msg; ldif_msg = ldb_ldif_read_file(s_ldb, fs), q++) { - if(q % 256 == 0) { - store_data = (pdap_store_obj_t) realloc(store_data, (q + 256) * sizeof(dap_store_obj_t)); - } - /* if (ldif_msg->changetype == LDB_CHANGETYPE_ADD) { - / ... / - } */ // in case we gonna use extra LDIF functionality - const char *key = ldb_msg_find_attr_as_string(ldif_msg->msg, "cn", NULL); - if(key != NULL) { - store_data[q].section = strdup("kelvin-testnet"); - store_data[q].group = strdup(group); - store_data[q].type = 1; - store_data[q].key = strdup(key); - store_data[q].value =(uint8_t*) strdup( ldb_msg_find_attr_as_string(ldif_msg->msg, "time", NULL)); - store_data[q].value_len = strlen ( (char*) store_data[q].value) +1; - log_it(L_INFO, "Record %s stored successfully", ldb_dn_get_linearized(ldif_msg->msg->dn)); - } - ldb_ldif_read_free(s_ldb, ldif_msg); - } - fclose(fs); - return store_data; -} - -/* - * Add multiple entries received from remote node to local database. - * Since we don't know the size, it must be supplied too - * - * dap_store_size the count records - * return 0 if Ok, <0 if errors - */ -int dap_db_add_ldb(pdap_store_obj_t a_store_obj, size_t a_store_count) -{ - int l_ret = 0; - if(a_store_obj == NULL) { - log_it(L_ERROR, "Invalid Dap store objects passed"); - return -1; - } - if(ldb_connect(s_ldb, dap_db_path, 0, NULL) != LDB_SUCCESS) { - log_it(L_ERROR, "Couldn't connect to database"); - return -2; - } - //log_it(L_INFO, "We're about to put %d records into database", a_store_count); - struct ldb_message *l_msg; - if(a_store_count == 0) { - a_store_count = 1; - } - for(size_t q = 0; q < a_store_count; q++) { - // level 3: leased address, single whitelist entity - - // if it is marked, don't save - if(a_store_obj[q].timestamp == (time_t) -1) - continue; - - l_msg = ldb_msg_new(s_ldb); - char dn[256]; - memset(dn, '\0', 256); - strcat(dn, "cn="); - strcat(dn, a_store_obj[q].key); - //strcat(dn, ",ou=addrs_leased,dc=kelvin_nodes"); - strcat(dn, ",ou="); - strcat(dn, a_store_obj[q].group); - strcat(dn, ",dc=kelvin_nodes"); - l_msg->dn = ldb_dn_new(s_mem_ctx, s_ldb, dn); - int l_res = ldb_msg_add_string(l_msg, "cn", a_store_obj[q].key); - ldb_msg_add_string(l_msg, "objectClass", a_store_obj[q].group); - ldb_msg_add_string(l_msg, "section", "kelvin_nodes"); - ldb_msg_add_string(l_msg, "description", "Approved Kelvin node"); - - struct ldb_val l_val; - struct ldb_message_element *return_el; - l_val.data = (uint8_t*) &a_store_obj[q].timestamp; - l_val.length = sizeof(time_t); - l_res = ldb_msg_add_value(l_msg, "time", &l_val, &return_el); - - l_val.data = a_store_obj[q].value; - l_val.length = a_store_obj[q].value_len; - l_res = ldb_msg_add_value(l_msg, "val", &l_val, &return_el); - - l_ret += dap_db_add_msg(l_msg); // accumulation error codes - talloc_free(l_msg->dn); - talloc_free(l_msg); - } - return l_ret; -} - -/* - * Delete multiple entries from local database. - * - * dap_store_size the count records - * return 0 if Ok, <0 if errors - */ -int dap_db_delete_ldb(pdap_store_obj_t store_obj, size_t a_store_count) -{ - int ret = 0; - if(store_obj == NULL) { - log_it(L_ERROR, "Invalid Dap store objects passed"); - return -1; - } - if(ldb_connect(s_ldb, dap_db_path, 0, NULL) != LDB_SUCCESS) { - log_it(L_ERROR, "Couldn't connect to database"); - return -2; - } - //log_it(L_INFO, "We're delete %d records from database", a_store_count); - if(a_store_count == 0) { - a_store_count = 1; - } - for(size_t q = 0; q < a_store_count; q++) { - char dn[128]; - memset(dn, '\0', 128); - strcat(dn, "cn="); - strcat(dn, store_obj[q].key); - //strcat(dn, ",ou=addrs_leased,dc=kelvin_nodes"); - strcat(dn, ",ou="); - strcat(dn, store_obj[q].group); - strcat(dn, ",dc=kelvin_nodes"); - struct ldb_dn *ldn = ldb_dn_new(s_mem_ctx, s_ldb, dn); - ret += dap_db_del_msg(ldn); // accumulation error codes - talloc_free(ldn); - } - return ret; - -} - -/* serialization */ -/*dap_store_obj_pkt_t *dap_store_packet_single(pdap_store_obj_t store_obj) - { - dap_store_obj_pkt_t *pkt = DAP_NEW_Z_SIZE(dap_store_obj_pkt_t, - sizeof(int) + 4 + strlen(store_obj->group) + strlen(store_obj->key) + strlen(store_obj->section) - + strlen(store_obj->value)); - pkt->grp_size = strlen(store_obj->group) + 1; - pkt->name_size = strlen(store_obj->key) + 1; - pkt->sec_size = strlen(store_obj->section) + 1; - pkt->type = store_obj->type; - memcpy(pkt->data, &store_obj->section, pkt->sec_size); - memcpy(pkt->data + pkt->sec_size, &store_obj->group, pkt->grp_size); - memcpy(pkt->data + pkt->sec_size + pkt->grp_size, &store_obj->key, pkt->name_size); - memcpy(pkt->data + pkt->sec_size + pkt->grp_size + pkt->name_size, &store_obj->value, strlen(store_obj->value) + 1); - return pkt; - }*/ - -static size_t dap_db_get_size_pdap_store_obj_t(pdap_store_obj_t store_obj) -{ - size_t size = sizeof(uint32_t) + 3 * sizeof(uint16_t) + sizeof(size_t) + sizeof(time_t) + dap_strlen(store_obj->group) + - dap_strlen(store_obj->key) + dap_strlen(store_obj->section) + store_obj->value_len; - return size; -} - -/** - * serialization - * @param a_store_obj_count count of structures store_obj - * @param a_timestamp create data time - * @param a_size_out[out] size of output structure - * @return NULL in case of an error - */ -dap_store_obj_pkt_t *dap_store_packet_multiple(pdap_store_obj_t a_store_obj, time_t a_timestamp, size_t a_store_obj_count) -{ - if(!a_store_obj || a_store_obj_count < 1) - return NULL; - size_t l_data_size_out = sizeof(uint32_t); // size of output data - // calculate output structure size - for(size_t l_q = 0; l_q < a_store_obj_count; ++l_q) - l_data_size_out += dap_db_get_size_pdap_store_obj_t(&a_store_obj[l_q]); - - dap_store_obj_pkt_t *l_pkt = DAP_NEW_Z_SIZE(dap_store_obj_pkt_t, sizeof(dap_store_obj_pkt_t) + l_data_size_out); - l_pkt->data_size = l_data_size_out; - l_pkt->timestamp = a_timestamp; - uint64_t l_offset = 0; - uint32_t l_count = (uint32_t) a_store_obj_count; - memcpy(l_pkt->data + l_offset, &l_count, sizeof(uint32_t)); - l_offset += sizeof(uint32_t); - for( size_t l_q = 0; l_q < a_store_obj_count; ++l_q) { - dap_store_obj_t obj = a_store_obj[l_q]; - uint16_t section_size = (uint16_t) dap_strlen(obj.section); - uint16_t group_size = (uint16_t) dap_strlen(obj.group); - uint16_t key_size = (uint16_t) dap_strlen(obj.key); - memcpy(l_pkt->data + l_offset, &obj.type, sizeof(int)); - l_offset += sizeof(int); - memcpy(l_pkt->data + l_offset, §ion_size, sizeof(uint16_t)); - l_offset += sizeof(uint16_t); - memcpy(l_pkt->data + l_offset, obj.section, section_size); - l_offset += section_size; - memcpy(l_pkt->data + l_offset, &group_size, sizeof(uint16_t)); - l_offset += sizeof(uint16_t); - memcpy(l_pkt->data + l_offset, obj.group, group_size); - l_offset += group_size; - memcpy(l_pkt->data + l_offset, &obj.timestamp, sizeof(time_t)); - l_offset += sizeof(time_t); - memcpy(l_pkt->data + l_offset, &key_size, sizeof(uint16_t)); - l_offset += sizeof(uint16_t); - memcpy(l_pkt->data + l_offset, obj.key, key_size); - l_offset += key_size; - memcpy(l_pkt->data + l_offset, &obj.value_len, sizeof(size_t)); - l_offset += sizeof(size_t); - memcpy(l_pkt->data + l_offset, obj.value, obj.value_len); - l_offset += obj.value_len; - } - assert(l_data_size_out == l_offset); - return l_pkt; -} -/** - * deserialization - * @param store_obj_count[out] count of the output structures store_obj - * @return NULL in case of an error* - */ - -dap_store_obj_t *dap_store_unpacket(const dap_store_obj_pkt_t *pkt, size_t *store_obj_count) -{ - if(!pkt || pkt->data_size < 1) - return NULL; - uint64_t offset = 0; - uint32_t count; - memcpy(&count, pkt->data, sizeof(uint32_t)); - offset += sizeof(uint32_t); - dap_store_obj_t *store_obj = DAP_NEW_Z_SIZE(dap_store_obj_t, count * sizeof(struct dap_store_obj)); - for(size_t q = 0; q < count; ++q) { - dap_store_obj_t *obj = store_obj + q; - uint16_t str_size; - memcpy(&obj->type, pkt->data + offset, sizeof(int)); - offset += sizeof(int); - - memcpy(&str_size, pkt->data + offset, sizeof(uint16_t)); - offset += sizeof(uint16_t); - obj->section = DAP_NEW_Z_SIZE(char, str_size + 1); - memcpy(obj->section, pkt->data + offset, str_size); - offset += str_size; - - memcpy(&str_size, pkt->data + offset, sizeof(uint16_t)); - offset += sizeof(uint16_t); - obj->group = DAP_NEW_Z_SIZE(char, str_size + 1); - memcpy(obj->group, pkt->data + offset, str_size); - offset += str_size; - - memcpy(&obj->timestamp, pkt->data + offset, sizeof(time_t)); - offset += sizeof(time_t); - - memcpy(&str_size, pkt->data + offset, sizeof(uint16_t)); - offset += sizeof(uint16_t); - obj->key = DAP_NEW_Z_SIZE(char, str_size + 1); - memcpy(obj->key, pkt->data + offset, str_size); - offset += str_size; - - memcpy(&obj->value_len, pkt->data + offset, sizeof(size_t)); - offset += sizeof(size_t); - - obj->value = DAP_NEW_Z_SIZE(uint8_t, obj->value_len + 1); - memcpy(obj->value, pkt->data + offset, obj->value_len); - offset += obj->value_len; - } - assert(pkt->data_size == offset); - if(store_obj_count) - *store_obj_count = count; - return store_obj; -} - -void dap_db_deinit() -{ - talloc_free(s_ldb); - talloc_free(s_mem_ctx); - free(dap_db_path); - s_ldb = NULL; - s_mem_ctx = NULL; - dap_db_path = NULL; -} diff --git a/dap_chain_global_db_pvt.h b/dap_chain_global_db_pvt.h deleted file mode 100755 index dacd0eabcf117c0066e74a5f4106f78c4d80ab1f..0000000000000000000000000000000000000000 --- a/dap_chain_global_db_pvt.h +++ /dev/null @@ -1,43 +0,0 @@ -#ifndef _GLOBAL_DB_DRIVER_H_ -#define _GLOBAL_DB_DRIVER_H_ - -#include <stdint.h> -#include "dap_common.h" -#include "ldb.h" - -typedef struct dap_store_obj { - time_t timestamp; - uint8_t type; - char *section; - char *group; - char *key; - uint8_t *value; - size_t value_len; -}DAP_ALIGN_PACKED dap_store_obj_t, *pdap_store_obj_t; - -typedef struct dap_store_obj_pkt { - /*uint8_t type; - uint8_t sec_size; - uint8_t grp_size; - uint8_t name_size;*/ - time_t timestamp; - size_t data_size; - uint8_t data[]; -}__attribute__((packed)) dap_store_obj_pkt_t; - -int dap_db_init(const char*); -void dap_db_group_create(const char *); -void dap_db_deinit(void); - -int dap_db_add(pdap_store_obj_t a_store_obj, size_t a_store_count); -int dap_db_delete(pdap_store_obj_t a_store_obj, size_t a_store_count); - -pdap_store_obj_t dap_db_read_data_ldb(const char *a_query, size_t *a_count); -pdap_store_obj_t dap_db_read_file_data(const char *a_path, const char *a_group); // state of emergency only, if LDB database is inaccessible -dap_store_obj_pkt_t *dap_store_packet_single(pdap_store_obj_t a_store_obj); -dap_store_obj_pkt_t *dap_store_packet_multiple(pdap_store_obj_t a_store_obj, time_t a_timestamp, size_t a_store_obj_count); -dap_store_obj_t *dap_store_unpacket(const dap_store_obj_pkt_t *a_pkt, size_t *a_store_obj_count); - -void dab_db_free_pdap_store_obj_t(pdap_store_obj_t a_store_data, size_t a_count); - -#endif // #ifndef _GLOBAL_DB_DRIVER_H_