diff --git a/3rdparty/cuttdb/src/cdb_bgtask.c b/3rdparty/cuttdb/src/cdb_bgtask.c index 1d16c81a95ec1a5b83b64283150fe97e86f83d64..d12bd26e6c3b35e61e97aab1f2be49b10ea9cd80 100644 --- a/3rdparty/cuttdb/src/cdb_bgtask.c +++ b/3rdparty/cuttdb/src/cdb_bgtask.c @@ -16,14 +16,7 @@ #include "cdb_bgtask.h" #include <stdlib.h> #include <errno.h> -#if defined(DAP_OS_DARWIN) #include <signal.h> -#elif defined(_WIN32) -#include <sys/signal.h> -#else -#include <signal.h> -#endif - /* where thread begins */ static void *_cdb_bgtask_func(void *arg); diff --git a/dap-sdk/core/include/dap_common.h b/dap-sdk/core/include/dap_common.h index 7baa879248bd5fb824dfcaaf99ee5521e7dc1698..46b5578d90139ce055ded6108faaea8cfcd70461 100755 --- a/dap-sdk/core/include/dap_common.h +++ b/dap-sdk/core/include/dap_common.h @@ -122,8 +122,8 @@ typedef uint8_t byte_t; #define DAP_NEW_Z_SIZE(a, b) DAP_CAST_REINT(a, rpcalloc(1,b)) #define DAP_REALLOC(a, b) rprealloc(a,b) #define DAP_DELETE(a) rpfree(a) - #define DAP_DUP(a) ( __typeof(a) ret = memcpy(ret,a,sizeof(*a)) ) - #define DAP_DUP_SIZE(a,b) ( __typeof(a) ret = memcpy(ret,a,b) ) + #define DAP_DUP(a, b) memcpy(a, b, sizeof(*b)) + #define DAP_DUP_SIZE(a, b, s) memcpy(a, b, s) #else #define DAP_MALLOC(a) malloc(a) #define DAP_FREE(a) free(a) @@ -139,8 +139,8 @@ typedef uint8_t byte_t; #define DAP_NEW_Z_SIZE(a, b) DAP_CAST_REINT(a, calloc(1,b)) #define DAP_REALLOC(a, b) realloc(a,b) #define DAP_DELETE(a) free(a) - #define DAP_DUP(a) ( __typeof(a) ret = memcpy(ret,a,sizeof(*a)) ) - #define DAP_DUP_SIZE(a,b) ( __typeof(a) memcpy(ret,a,b) ) + #define DAP_DUP(a, b) memcpy(a, b, sizeof(*b)) + #define DAP_DUP_SIZE(a, b, s) memcpy(a, b, s) #endif #define DAP_DEL_Z(a) if(a) { DAP_DELETE(a); a=NULL;} diff --git a/dap-sdk/core/src/dap_common.c b/dap-sdk/core/src/dap_common.c index 0a7aa08e40deba922de8896e0a0a13b1f330d6a5..d36d88e4575a670ce1774896f706fbe4436932a1 100755 --- a/dap-sdk/core/src/dap_common.c +++ b/dap-sdk/core/src/dap_common.c @@ -190,7 +190,7 @@ const char * dap_get_appname() } /** - * @brief dap_set_appname + * @brief dap_set_appname set application name in global s_appname variable * @param a_appname * @return */ @@ -222,6 +222,16 @@ void dap_set_log_tag_width(size_t a_width) { * @param[in] a_log_file * @return */ + +/** + * @brief dap_common_init call this function before using dap sdk modules + * + * @param a_console_title set console title. Can be result of dap_get_appname() + * @param a_log_file_path path to log file. Saved in s_log_file_path variable + * @param a_log_dirpath path to log directory. Saved in s_log_dir_path variable + * @return int (0 if succcess, -1 if error) + */ + int dap_common_init( const char *a_console_title, const char *a_log_file_path, const char *a_log_dirpath) { // init randomer diff --git a/dap-sdk/core/src/dap_file_utils.c b/dap-sdk/core/src/dap_file_utils.c index 5844fcf3d712beaa08b1c617d4c8da43dfdebce3..30b3f7dc98effc0e4a69c5e6a0de728dcf81386f 100755 --- a/dap-sdk/core/src/dap_file_utils.c +++ b/dap-sdk/core/src/dap_file_utils.c @@ -114,12 +114,14 @@ bool dap_dir_test(const char * a_dir_path) return false; } + /** - * Create a new directory with intermediate sub-directories - * - * @dir_path new directory pathname - * @return 0, if the directory was created or already exist, else -1 + * @brief dap_mkdir_with_parents Create a new directory with intermediate sub-directories + * + * @param a_dir_path new directory pathname + * @return int 0, if the directory was created or already exist, else -1 */ + int dap_mkdir_with_parents(const char *a_dir_path) { // validation of a pointer diff --git a/dap-sdk/core/src/dap_strfuncs.c b/dap-sdk/core/src/dap_strfuncs.c index 118c040d0c300e38f7914faf20ca40bd923d5f15..f8944b88b34ef8fb956dfcb35036a7c188b07211 100755 --- a/dap-sdk/core/src/dap_strfuncs.c +++ b/dap-sdk/core/src/dap_strfuncs.c @@ -185,6 +185,14 @@ char *dap_itoa128(char *a_str, int128_t a_value, int a_base) * * Returns: length of the string */ + +/** + * @brief dap_strlen get length of the string + * + * @param a_str pointer to string + * @return size_t + */ + size_t dap_strlen(const char *a_str) { size_t l_length = 0; @@ -196,12 +204,13 @@ size_t dap_strlen(const char *a_str) } /** - * dap_strcmp: - * @a_str1: (nullable): the string - * @a_str2: (nullable): the string - * - * Compare a_str1 and a_str2 + * @brief dap_strcmp a_str1 and a_str2 + * + * @param a_str1 (nullable): the string + * @param a_str2 (nullable): the string + * @return int */ + int dap_strcmp(const char *a_str1, const char *a_str2) { if(a_str1 && a_str2) { @@ -211,12 +220,14 @@ int dap_strcmp(const char *a_str1, const char *a_str2) } /** - * dap_strcmp: - * @a_str1: (nullable): the string - * @a_str2: (nullable): the string - * - * Compare a_n characters of a_str1 and a_str2 + * @brief dap_strcmp + * + * @param a_str1 (nullable): the string + * @param a_str2 (nullable): the string + * @param a_n Compare a_n characters of a_str1 and a_str2 + * @return int */ + int dap_strncmp(const char *a_str1, const char *a_str2, size_t a_n) { if(a_str1 && a_str2) { @@ -225,16 +236,17 @@ int dap_strncmp(const char *a_str1, const char *a_str2, size_t a_n) return -1; } + /** - * dap_strdup: - * @a_str: (nullable): the string to duplicate - * + * @brief dap_strdup: * Duplicates a string. If @a_str is %NULL it returns %NULL. * The returned string should be freed * when no longer needed. * - * Returns: a newly-allocated copy of @a_str + * @param a_str (nullable): the string to duplicate + * @return char* duplicated string */ + char* dap_strdup(const char *a_str) { char *l_new_str; @@ -255,18 +267,21 @@ char* dap_strdup(const char *a_str) } /** - * dap_strdup_vprintf: - * @a_format: a standard printf() format string, but notice - * [string precision pitfalls][string-precision] - * @a_args: the list of parameters to insert into the format string - * + * @brief dap_strdup_vprintf + * * Similar to the standard C vsprintf() function but safer, since it * calculates the maximum space required and allocates memory to hold * the result. The returned string should be freed with DAP_DELETE() * when no longer needed. * * Returns: a newly-allocated string holding the result + * + * @param a_format a standard printf() format string, but notice + * [string precision pitfalls][string-precision] + * @param a_args the list of parameters to insert into the format string + * @return char* */ + char* dap_strdup_vprintf(const char *a_format, va_list a_args) { char *l_string = NULL; @@ -277,16 +292,18 @@ char* dap_strdup_vprintf(const char *a_format, va_list a_args) } /** - * dap_strdup_printf: - * @a_format: a standard printf() format string - * - * Similar to the standard C sprintf() function but safer, since it + * @brief dap_strdup_printf: + * + * * Similar to the standard C sprintf() function but safer, since it * calculates the maximum space required and allocates memory to hold * the result. The returned string should be freed with DAP_DELETE() * when no longer needed. - * - * Returns: a newly-allocated string holding the result + * + * @param a_format a standard printf() format string + * @param ... + * @return char* a newly-allocated string holding the result */ + char* dap_strdup_printf(const char *a_format, ...) { char *l_buffer; @@ -630,6 +647,13 @@ char** dap_strsplit(const char *a_string, const char *a_delimiter, int a_max_tok return l_str_array; } +/** + * @brief dap_str_countv + * + * @param a_str_array + * @return size_t + */ + size_t dap_str_countv(char **a_str_array) { size_t l_i = 0; @@ -642,16 +666,19 @@ size_t dap_str_countv(char **a_str_array) } /** - * dap_strdupv: - * @a_str_array: (nullable): a %NULL-terminated array of strings - * + * @brief dap_strdupv: + * + * @param a_str_array (nullable): a %NULL-terminated array of strings * Copies %NULL-terminated array of strings. The copy is a deep copy; * the new array should be freed by first freeing each string, then * the array itself. g_strfreev() does this for you. If called * on a %NULL value, g_strdupv() simply returns %NULL. * * Returns: (nullable): a new %NULL-terminated array of strings. + * + * @return char** */ + char** dap_strdupv(const char **a_str_array) { if(a_str_array) @@ -680,14 +707,16 @@ char** dap_strdupv(const char **a_str_array) } /** - * dap_strfreev: - * @a_str_array: (nullable): a %NULL-terminated array of strings to free - * + * @brief dap_strfreev: + * * Frees a %NULL-terminated array of strings, as well as each * string it contains. * * If @a_str_array is %NULL, this function simply returns. + * + * @param a_str_array (nullable): a %NULL-terminated array of strings to free */ + void dap_strfreev(char **a_str_array) { if(a_str_array) @@ -701,9 +730,8 @@ void dap_strfreev(char **a_str_array) } /** - * dap_strchug: - * @a_string: a string to remove the leading whitespace from - * + * @brief dap_strchug: + * * Removes leading whitespace from a string, by moving the rest * of the characters forward. * @@ -713,7 +741,11 @@ void dap_strfreev(char **a_str_array) * * The pointer to @a_string is returned to allow the nesting of functions. * Returns: @a_string + * + * @param a_string a string to remove the leading whitespace from + * @return char* */ + char* dap_strchug(char *a_string) { unsigned char *l_start; @@ -760,15 +792,18 @@ char* dap_strchomp(char *a_string) } /** - * dap_strup: - * @a_str: a string - * @a_len: length of @a_str in bytes, or -1 if @a_str is nul-terminated - * + * @brief dap_strup + * * Converts all lower case ASCII letters to upper case ASCII letters. * * Returns: a newly allocated string, with all the lower case * characters in @a_str converted to upper case + * + * @param a_str a string + * @param a_len length of @a_str in bytes, or -1 if @a_str is nul-terminated + * @return char* */ + char* dap_strup(const char *a_str, ssize_t a_len) { char *l_result, *l_s; @@ -786,15 +821,17 @@ char* dap_strup(const char *a_str, ssize_t a_len) } /** - * dap_strdown: - * @a_str: a string - * @a_len: length of @a_str in bytes, or -1 if @a_str is nul-terminated - * - * Converts all upper case ASCII letters to lower case ASCII letters. + * @brief dap_strdown + * Converts all upper case ASCII letters to lower case ASCII letters. * * Returns: a newly-allocated string, with all the upper case * characters in @a_str converted to lower case + * + * @param a_str a string + * @param a_len length of @a_str in bytes, or -1 if @a_str is nul-terminated + * @return char* */ + char* dap_strdown(const char *a_str, ssize_t a_len) { char *l_result, *l_s; @@ -811,10 +848,9 @@ char* dap_strdown(const char *a_str, ssize_t a_len) return l_result; } + /** - * dap_strreverse: - * @a_string: the string to reverse - * + * @brief dap_strreverse * Reverses all of the bytes in a string. For example, * `dap_strreverse("abcdef")` will result in "fedcba". * @@ -822,7 +858,11 @@ char* dap_strdown(const char *a_str, ssize_t a_len) * containing multibyte characters. * * Returns: the same pointer passed in as @a_string + * + * @param a_string the string to reverse + * @return char* */ + char* dap_strreverse(char *a_string) { dap_return_val_if_fail(a_string != NULL, NULL); @@ -857,6 +897,14 @@ char *strptime( char *buff, const char *fmt, struct tm *tm ) { return buff + len; } +/** + * @brief _strndup + * + * @param str + * @param len + * @return char* + */ + char *_strndup(const char *str, unsigned long len) { char *buf = (char*)memchr(str, '\0', len); if (buf) diff --git a/dap-sdk/crypto/src/dap_cert.c b/dap-sdk/crypto/src/dap_cert.c index 920e16678ad35a37c074412ef3e620b6850ffceb..131b7415c5a152a088c75a78f4715d181bbb83d9 100755 --- a/dap-sdk/crypto/src/dap_cert.c +++ b/dap-sdk/crypto/src/dap_cert.c @@ -73,7 +73,7 @@ static dap_cert_item_t * s_certs = NULL; static dap_cert_folder_t * s_cert_folders = NULL; /** - * @brief dap_cert_init + * @brief dap_cert_init empty stub for certificate init * @return */ int dap_cert_init() diff --git a/dap-sdk/crypto/src/dap_enc.c b/dap-sdk/crypto/src/dap_enc.c index bb388202b73abac4f794c96408768490c7ad4102..507d62b52553d8e6e0eaab3ff8147b3bf351037d 100755 --- a/dap-sdk/crypto/src/dap_enc.c +++ b/dap-sdk/crypto/src/dap_enc.c @@ -35,9 +35,11 @@ #define LOG_TAG "dap_enc" /** - * @brief enc_init - * @return + * @brief dap_enc_init if you want to use crypto functions from dap-sdk call that function + * + * @return int */ + int dap_enc_init() { srand(time(NULL)); diff --git a/dap-sdk/crypto/src/dap_enc_base58.c b/dap-sdk/crypto/src/dap_enc_base58.c index 84282f26f97c1b9da2101a7b8274f93091f89f06..ad6c897a31beddb1ee04489d91bdbc19c10e389f 100755 --- a/dap-sdk/crypto/src/dap_enc_base58.c +++ b/dap-sdk/crypto/src/dap_enc_base58.c @@ -46,10 +46,10 @@ const int8_t c_b58digits_map[] = { }; /** - * @brief dap_enc_base58_decode - * @param a_in - * @param a_out - * @return + * @brief dap_enc_base58_decode decode string using base58 alghoritm + * @param a_in - encoded string + * @param a_out - output buffer + * @return size_t output buffer size */ size_t dap_enc_base58_decode(const char * a_in, void * a_out) { @@ -152,8 +152,14 @@ size_t dap_enc_base58_decode(const char * a_in, void * a_out) } - -//bool b58enc(char *a_out, size_t *l_out_size, const void *a_in, size_t a_in_size) +/** + * @brief dap_enc_base58_encode encode string in Base58 alghorithm + * + * @param a_in - input buffer + * @param a_in_size - buffer size + * @param a_out - string with results + * @return size_t - returned string size (in bytes) + */ size_t dap_enc_base58_encode(const void * a_in, size_t a_in_size, char * a_out) { const uint8_t *l_in_u8 = a_in; diff --git a/dap-sdk/crypto/src/dap_enc_key.c b/dap-sdk/crypto/src/dap_enc_key.c index 580127163d885d223b3d0857a501dde984c170f7..8d4c458ae07f8f42cae459bfb52610cc448de940 100755 --- a/dap-sdk/crypto/src/dap_enc_key.c +++ b/dap-sdk/crypto/src/dap_enc_key.c @@ -351,7 +351,7 @@ struct dap_enc_key_callbacks{ const size_t c_callbacks_size = sizeof(s_callbacks) / sizeof(s_callbacks[0]); /** - * @brief dap_enc_key_init + * @brief dap_enc_key_init empty stub * @return */ int dap_enc_key_init() diff --git a/modules/chain/dap_chain_cell.c b/modules/chain/dap_chain_cell.c index 238e97a4a69df20aafab2d60b05c1d165f0dfa1c..8e44c836749ef016857260637011c9092096f604 100644 --- a/modules/chain/dap_chain_cell.c +++ b/modules/chain/dap_chain_cell.c @@ -115,14 +115,13 @@ void dap_chain_cell_delete(dap_chain_cell_t *a_cell) int dap_chain_cell_load(dap_chain_t * a_chain, const char * a_cell_file_path) { dap_chain_cell_t * l_cell = dap_chain_cell_create(); - l_cell->file_storage_path = dap_strdup( a_cell_file_path ); - - char *l_file_path = dap_strdup_printf("%s/%s", DAP_CHAIN_PVT (a_chain)->file_storage_dir, - l_cell->file_storage_path); - - l_cell->file_storage = fopen(l_file_path,"rb"); - DAP_DELETE(l_file_path); + { + char l_file_path[MAX_PATH] = {'\0'}; + dap_snprintf(l_file_path, MAX_PATH, "%s/%s", DAP_CHAIN_PVT(a_chain)->file_storage_dir, + l_cell->file_storage_path); + l_cell->file_storage = fopen(l_file_path,"rb"); + } if ( l_cell->file_storage ){ dap_chain_cell_file_header_t l_hdr = {0}; if ( fread( &l_hdr,1,sizeof(l_hdr),l_cell->file_storage ) == sizeof (l_hdr) ) { @@ -186,12 +185,12 @@ int dap_chain_cell_file_append( dap_chain_cell_t * a_cell, const void* a_atom, s size_t l_total_wrote_bytes = 0; // file need to be opened or created if(a_cell->file_storage == NULL) { - char *l_file_path = dap_strdup_printf("%s/%s", DAP_CHAIN_PVT ( a_cell->chain)->file_storage_dir, - a_cell->file_storage_path); + char l_file_path[MAX_PATH] = {'\0'}; + dap_snprintf(l_file_path, MAX_PATH, "%s/%s", DAP_CHAIN_PVT(a_cell->chain)->file_storage_dir, + a_cell->file_storage_path); a_cell->file_storage = fopen(l_file_path, "ab"); if(a_cell->file_storage == NULL) a_cell->file_storage = fopen(l_file_path, "wb"); - DAP_DELETE(l_file_path); } if(!a_cell->file_storage) { log_it(L_ERROR, "File \"%s\" not opened for write cell 0x%016X", @@ -255,10 +254,10 @@ int dap_chain_cell_file_update( dap_chain_cell_t * a_cell) return -1; } if(a_cell->file_storage == NULL ){ // File need to be created - char *l_file_path = dap_strdup_printf("%s/%s", DAP_CHAIN_PVT ( a_cell->chain)->file_storage_dir, - a_cell->file_storage_path); + char l_file_path[MAX_PATH] = {'\0'}; + dap_snprintf(l_file_path, MAX_PATH, "%s/%s", DAP_CHAIN_PVT(a_cell->chain)->file_storage_dir, + a_cell->file_storage_path); a_cell->file_storage = fopen(l_file_path, "wb"); - DAP_DELETE(l_file_path); if(a_cell->file_storage) { dap_chain_cell_file_header_t l_hdr = { .signature = DAP_CHAIN_CELL_FILE_SIGNATURE, diff --git a/modules/channel/chain/dap_stream_ch_chain.c b/modules/channel/chain/dap_stream_ch_chain.c index 7e6fd0b55d3e1de16eb2430203d544a720c1daa4..86a353e7ec4526bdfec864dab5b2ab82b325b934 100644 --- a/modules/channel/chain/dap_stream_ch_chain.c +++ b/modules/channel/chain/dap_stream_ch_chain.c @@ -77,8 +77,6 @@ struct sync_request dap_stream_ch_chain_pkt_hdr_t request_hdr; dap_chain_pkt_item_t pkt; - dap_stream_ch_chain_update_element_t *local_gdbs; - uint64_t local_gdbs_count; dap_stream_ch_chain_hash_item_t *remote_atoms; // Remote atoms dap_stream_ch_chain_hash_item_t *remote_gdbs; // Remote gdbs @@ -331,8 +329,7 @@ static void s_sync_out_gdb_first_worker_callback(dap_worker_t *a_worker, void *a dap_chain_net_t *l_net = dap_chain_net_by_id(l_ch_chain->request_hdr.net_id); // Add it to outgoing list - l_ch_chain->request_global_db_trs = l_sync_request->gdb.db_log; - l_ch_chain->request_db_iter = NULL; + l_ch_chain->request_db_log = l_sync_request->gdb.db_log; l_ch_chain->state = CHAIN_STATE_SYNC_GLOBAL_DB; dap_chain_node_addr_t l_node_addr = { 0 }; l_node_addr.uint64 = dap_chain_net_get_cur_addr_int(l_net); @@ -347,7 +344,6 @@ static void s_sync_out_gdb_first_worker_callback(dap_worker_t *a_worker, void *a if( a_worker){ // We send NULL to prevent delete s_sync_request_delete(l_sync_request); - l_ch_chain->is_on_request = false; } } @@ -369,19 +365,16 @@ static void s_sync_out_gdb_last_worker_callback(dap_worker_t *a_worker, void *a_ dap_stream_ch_chain_t *l_ch_chain = DAP_STREAM_CH_CHAIN( l_ch ); s_sync_out_gdb_first_worker_callback(NULL,a_arg); // NULL to say callback not to delete request - dap_stream_ch_chain_sync_request_t l_request = {0}; if (s_debug_more ) log_it(L_INFO,"Out: DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB"); dap_stream_ch_chain_pkt_write_unsafe(l_ch_chain->ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB, l_ch_chain->request_hdr.net_id.uint64, l_ch_chain->request_hdr.chain_id.uint64, - l_ch_chain->request_hdr.cell_id.uint64, &l_request, sizeof(l_request)); + l_ch_chain->request_hdr.cell_id.uint64, NULL, 0); l_ch_chain->state = CHAIN_STATE_IDLE; if(l_ch_chain->callback_notify_packet_out) l_ch_chain->callback_notify_packet_out(l_ch_chain, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB, NULL, 0, l_ch_chain->callback_notify_arg); - l_ch_chain->is_on_request = false; s_sync_request_delete(l_sync_request); - } /** @@ -392,27 +385,23 @@ static void s_sync_out_gdb_last_worker_callback(dap_worker_t *a_worker, void *a_ */ static bool s_sync_out_gdb_proc_callback(dap_proc_thread_t *a_thread, void *a_arg) { - struct sync_request *l_sync_request = (struct sync_request *) a_arg; - - // Get log diff - uint64_t l_local_last_id = dap_db_log_get_last_id(); - if (s_debug_more) - log_it(L_DEBUG, "Sync out gdb proc, requested transactions %"DAP_UINT64_FORMAT_u":%"DAP_UINT64_FORMAT_u" from address "NODE_ADDR_FP_STR, - l_sync_request->request.id_start, l_local_last_id, NODE_ADDR_FP_ARGS_S(l_sync_request->request.node_addr)); - uint64_t l_start_item = l_sync_request->request.id_start; - // If the current global_db has been truncated, but the remote node has not known this - if(l_sync_request->request.id_start > l_local_last_id) { - l_start_item = 0; - } + struct sync_request *l_sync_request = (struct sync_request *)a_arg; dap_chain_net_t *l_net = dap_chain_net_by_id(l_sync_request->request_hdr.net_id); - dap_list_t *l_add_groups = dap_chain_net_get_add_gdb_group(l_net, l_sync_request->request.node_addr); - dap_db_log_list_t *l_db_log = dap_db_log_list_start(l_start_item + 1, l_add_groups); + int l_flags = 0; + if (dap_chain_net_get_add_gdb_group(l_net, l_sync_request->request.node_addr)) + l_flags |= F_DB_LOG_ADD_EXTRA_GROUPS; + if (!l_sync_request->request.id_start) + l_flags |= F_DB_LOG_SYNC_FROM_ZERO; + dap_db_log_list_t *l_db_log = dap_db_log_list_start(l_sync_request->request.node_addr, l_flags); if(l_db_log) { + if (s_debug_more) + log_it(L_DEBUG, "Sync out gdb proc, requested %"DAP_UINT64_FORMAT_u" transactions from address "NODE_ADDR_FP_STR, + l_db_log->items_number, NODE_ADDR_FP_ARGS_S(l_sync_request->request.node_addr)); l_sync_request->gdb.db_log = l_db_log; - dap_proc_thread_worker_exec_callback(a_thread, l_sync_request->worker->id, s_sync_out_gdb_first_worker_callback,l_sync_request ); + dap_proc_thread_worker_exec_callback(a_thread, l_sync_request->worker->id, s_sync_out_gdb_first_worker_callback, l_sync_request ); } else { - dap_proc_thread_worker_exec_callback(a_thread, l_sync_request->worker->id, s_sync_out_gdb_last_worker_callback,l_sync_request ); + dap_proc_thread_worker_exec_callback(a_thread, l_sync_request->worker->id, s_sync_out_gdb_last_worker_callback, l_sync_request ); } return true; } @@ -427,7 +416,6 @@ static void s_sync_update_gdb_start_worker_callback(dap_worker_t *a_worker, void s_sync_request_delete(l_sync_request); return; } - dap_stream_ch_chain_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB_START, l_sync_request->request_hdr.net_id.uint64, l_sync_request->request_hdr.chain_id.uint64, l_sync_request->request_hdr.cell_id.uint64, NULL, 0); @@ -438,21 +426,24 @@ static void s_sync_update_gdb_start_worker_callback(dap_worker_t *a_worker, void DAP_DELETE(l_sync_request); } -static void s_sync_update_gdb_proc_callback(dap_worker_t *a_worker, void *a_arg) +static bool s_sync_update_gdb_proc_callback(dap_proc_thread_t *a_thread, void *a_arg) { - struct sync_request *l_sync_request = (struct sync_request *) a_arg; - - dap_stream_ch_t *l_ch = dap_stream_ch_find_by_uuid_unsafe(DAP_STREAM_WORKER(a_worker), l_sync_request->ch_uuid); - if( l_ch == NULL ){ - log_it(L_INFO,"Client disconnected before we sent the reply"); - s_sync_request_delete(l_sync_request); - return ; - } - // TODO make a local_gdbs hash table + struct sync_request *l_sync_request = (struct sync_request *)a_arg; + log_it(L_DEBUG, "Prepare request to gdb sync from %s", l_sync_request->request.id_start ? "last sync" : "zero"); + dap_chain_net_t *l_net = dap_chain_net_by_id(l_sync_request->request_hdr.net_id); + dap_stream_ch_t *l_ch = dap_stream_ch_find_by_uuid_unsafe(DAP_STREAM_WORKER(l_sync_request->worker), l_sync_request->ch_uuid); dap_stream_ch_chain_t *l_ch_chain = DAP_STREAM_CH_CHAIN(l_ch); - l_ch_chain->local_gdbs = l_sync_request->local_gdbs; - l_ch_chain->local_gdbs_count = l_sync_request->local_gdbs_count; - dap_worker_exec_callback_on( l_sync_request->worker, s_sync_update_gdb_start_worker_callback, l_sync_request); + int l_flags = 0; + if (dap_chain_net_get_add_gdb_group(l_net, l_sync_request->request.node_addr)) + l_flags |= F_DB_LOG_ADD_EXTRA_GROUPS; + if (!l_sync_request->request.id_start) + l_flags |= F_DB_LOG_SYNC_FROM_ZERO; + dap_db_log_list_t *l_db_log = dap_db_log_list_start(l_sync_request->request.node_addr, l_flags); + l_ch_chain->request_db_log = l_db_log; + l_ch_chain->state = CHAIN_STATE_UPDATE_GLOBAL_DB; + l_sync_request->request.node_addr.uint64 = dap_chain_net_get_cur_addr_int(l_net); + dap_proc_thread_worker_exec_callback(a_thread, l_sync_request->worker->id, s_sync_update_gdb_start_worker_callback, l_sync_request); + return true; } /** @@ -583,7 +574,7 @@ static void s_gdb_in_pkt_error_worker_callback(dap_worker_t *a_worker, void *a_a dap_stream_ch_t *l_ch = dap_stream_ch_find_by_uuid_unsafe(DAP_STREAM_WORKER(a_worker), l_sync_request->ch_uuid); if( l_ch == NULL ){ log_it(L_INFO,"Client disconnected before we sent the reply"); - s_sync_request_delete(l_sync_request); + DAP_DELETE(l_sync_request); return; } @@ -609,7 +600,7 @@ static bool s_gdb_in_pkt_proc_callback(dap_proc_thread_t *a_thread, void *a_arg) if (l_pkt_item->pkt_data_size) { size_t l_data_obj_count = 0; // deserialize data & Parse data from dap_db_log_pack() - dap_store_obj_t *l_store_obj = dap_db_log_unpack(l_pkt_item->pkt_data, l_pkt_item->pkt_data_size, &l_data_obj_count); + dap_store_obj_t *l_store_obj = dap_store_unpacket_multiple((dap_store_obj_pkt_t *)l_pkt_item->pkt_data, &l_data_obj_count); if (s_debug_more){ if (l_data_obj_count) log_it(L_INFO, "In: GLOBAL_DB parse: pkt_data_size=%zd, l_data_obj_count = %d",l_pkt_item->pkt_data_size, l_data_obj_count ); @@ -619,46 +610,25 @@ static bool s_gdb_in_pkt_proc_callback(dap_proc_thread_t *a_thread, void *a_arg) log_it(L_WARNING, "In: GLOBAL_DB parse: packet in list with NULL data(pkt_data_size:%zd)", l_pkt_item->pkt_data_size); } - for(size_t i = 0; i < l_data_obj_count; i++) { - // timestamp for exist obj - time_t l_timestamp_cur = 0; + for (size_t i = 0; i < l_data_obj_count; i++) { // obj to add - dap_store_obj_t* l_obj = l_store_obj + i; - // read item from base; - size_t l_count_read = 0; - dap_store_obj_t *l_read_obj = dap_chain_global_db_driver_read(l_obj->group, - l_obj->key, &l_count_read); - // get timestamp for the exist entry - if(l_read_obj) - l_timestamp_cur = l_read_obj->timestamp; - // get timestamp for the deleted entry - else - { - l_timestamp_cur = global_db_gr_del_get_timestamp(l_obj->group, l_obj->key); - } - + dap_store_obj_t *l_obj = l_store_obj + i; //check whether to apply the received data into the database - bool l_apply = true; - if(l_obj->timestamp < l_timestamp_cur) - l_apply = false; - else if(l_obj->type == 'd') { - // already deleted - if(!l_read_obj) - l_apply = false; + bool l_apply = false; + // timestamp for exist obj + time_t l_timestamp_cur = 0; + if (dap_chain_global_db_driver_is(l_obj->group, l_obj->key)) { + dap_store_obj_t *l_read_obj = dap_chain_global_db_driver_read(l_obj->group, l_obj->key, NULL); + if (l_read_obj) { + l_timestamp_cur = l_read_obj->timestamp; + dap_store_obj_free(l_read_obj, 1); + } } - else if(l_obj->type == 'a') { - bool l_is_the_same_present = false; - if(l_read_obj && - l_read_obj->value_len == l_obj->value_len && - !memcmp(l_read_obj->value, l_obj->value, l_obj->value_len)) - l_is_the_same_present = true; - // this data already present in global_db and not obsolete (out of date) - if(l_read_obj && (l_is_the_same_present || l_read_obj->timestamp >= l_store_obj->timestamp)) - l_apply = false; + // check the applied object newer that we have stored or erased + if (l_obj->timestamp > global_db_gr_del_get_timestamp(l_obj->group, l_obj->key) && + l_obj->timestamp > l_timestamp_cur) { + l_apply = true; } - if(l_read_obj) - dap_store_obj_free(l_read_obj, l_count_read); - if (s_debug_more){ char l_ts_str[50]; dap_time_to_str_rfc822(l_ts_str, sizeof(l_ts_str), l_store_obj[i].timestamp); @@ -667,12 +637,7 @@ static bool s_gdb_in_pkt_proc_callback(dap_proc_thread_t *a_thread, void *a_arg) (char ) l_store_obj[i].type, l_store_obj[i].type, l_store_obj[i].group, l_store_obj[i].key, l_ts_str, l_store_obj[i].value_len); } - - if(!l_apply) { - // If request was from defined node_addr we update its state - if(l_sync_request->request.node_addr.uint64) { - dap_db_set_last_id_remote(l_sync_request->request.node_addr.uint64, l_obj->id); - } + if (!l_apply) { continue; } @@ -680,7 +645,7 @@ static bool s_gdb_in_pkt_proc_callback(dap_proc_thread_t *a_thread, void *a_arg) dap_chain_t *l_chain = dap_chain_find_by_id(l_sync_request->request_hdr.net_id, l_sync_request->request_hdr.chain_id); if(l_chain) { if(l_chain->callback_add_datums_with_group){ - void * restrict l_store_obj_value = l_store_obj->value; + void * restrict l_store_obj_value = l_store_obj[i].value; l_chain->callback_add_datums_with_group(l_chain, (dap_chain_datum_t** restrict) l_store_obj_value, 1, l_store_obj[i].group); @@ -688,17 +653,13 @@ static bool s_gdb_in_pkt_proc_callback(dap_proc_thread_t *a_thread, void *a_arg) } // save data to global_db if(!dap_chain_global_db_obj_save(l_obj, 1)) { - if(l_store_obj) - dap_store_obj_free(l_store_obj, l_data_obj_count); - dap_proc_thread_worker_exec_callback(a_thread, l_sync_request->worker->id, s_gdb_in_pkt_error_worker_callback, l_sync_request); - return true; + struct sync_request *l_sync_req_err = DAP_NEW_Z(struct sync_request); + memcpy(l_sync_req_err, l_sync_request, sizeof(struct sync_request)); + dap_proc_thread_worker_exec_callback(a_thread, l_sync_request->worker->id, + s_gdb_in_pkt_error_worker_callback, l_sync_req_err); } else { - // If request was from defined node_addr we update its state - if(l_sync_request->request.node_addr.uint64) { - dap_db_set_last_id_remote(l_sync_request->request.node_addr.uint64, l_obj->id); - } if (s_debug_more) - log_it(L_DEBUG, "Added new GLOBAL_DB history pack"); + log_it(L_DEBUG, "Added new GLOBAL_DB synchronization record"); } } if(l_store_obj) @@ -721,7 +682,6 @@ static bool s_gdb_in_pkt_proc_callback(dap_proc_thread_t *a_thread, void *a_arg) struct sync_request *dap_stream_ch_chain_create_sync_request(dap_stream_ch_chain_pkt_t *a_chain_pkt, dap_stream_ch_t* a_ch) { dap_stream_ch_chain_t * l_ch_chain = DAP_STREAM_CH_CHAIN(a_ch); - memcpy(&l_ch_chain->request, a_chain_pkt->data, sizeof(l_ch_chain->request)); memcpy(&l_ch_chain->request_hdr, &a_chain_pkt->hdr, sizeof(l_ch_chain->request_hdr)); struct sync_request *l_sync_request = DAP_NEW_Z(struct sync_request); l_sync_request->ch_uuid = a_ch->uuid; @@ -749,11 +709,13 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) { dap_stream_ch_chain_t * l_ch_chain = DAP_STREAM_CH_CHAIN(a_ch); if (!l_ch_chain) { + log_it(L_ERROR, "No chain in channel, returning"); return; } dap_stream_ch_pkt_t * l_ch_pkt = (dap_stream_ch_pkt_t *) a_arg; dap_stream_ch_chain_pkt_t * l_chain_pkt = (dap_stream_ch_chain_pkt_t *) l_ch_pkt->data; if (!l_chain_pkt) { + log_it(L_ERROR, "No chain packet in channel packet, returning"); return; } if (l_ch_pkt->hdr.size< sizeof (l_chain_pkt->hdr) ){ @@ -807,21 +769,30 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) if(s_debug_more) log_it(L_INFO, "In: UPDATE_GLOBAL_DB_REQ pkt: net 0x%016x chain 0x%016x cell 0x%016x", l_chain_pkt->hdr.net_id.uint64 , l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64); - l_ch_chain->state = CHAIN_STATE_UPDATE_GLOBAL_DB; + if (l_chain_pkt_data_size == sizeof(dap_stream_ch_chain_sync_request_t)) + memcpy(&l_ch_chain->request, l_chain_pkt->data, sizeof(dap_stream_ch_chain_sync_request_t)); + dap_chain_node_client_t *l_client = (dap_chain_node_client_t *)l_ch_chain->callback_notify_arg; + if (l_client && l_client->resync_gdb) + l_ch_chain->request.id_start = 0; + else + l_ch_chain->request.id_start = 1; // incremental sync by default struct sync_request *l_sync_request = dap_stream_ch_chain_create_sync_request(l_chain_pkt, a_ch); l_ch_chain->stats_request_gdb_processed = 0; - dap_worker_exec_callback_on( a_ch->stream_worker->worker, s_sync_update_gdb_proc_callback, l_sync_request); - }break; + dap_proc_queue_add_callback_inter(a_ch->stream_worker->worker->proc_queue_input, s_sync_update_gdb_proc_callback, l_sync_request); + } break; + // Response with metadata organized in TSD case DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB_TSD:{ + if (s_debug_more) + log_it(L_DEBUG, "Global DB TSD packet detected"); + } break; - }break; // If requested - begin to recieve record's hashes case DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB_START:{ if (s_debug_more) log_it(L_INFO, "In: UPDATE_GLOBAL_DB_START pkt net 0x%016x chain 0x%016x cell 0x%016x", l_chain_pkt->hdr.net_id.uint64 , l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64); - if(l_ch_chain->state != CHAIN_STATE_IDLE){ + if (l_ch_chain->state != CHAIN_STATE_IDLE){ log_it(L_WARNING, "Can't process UPDATE_GLOBAL_DB_START request because its already busy with syncronization"); s_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64, l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64, @@ -830,12 +801,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) } memcpy(&l_ch_chain->request_hdr, &l_chain_pkt->hdr, sizeof(dap_stream_ch_chain_pkt_t)); l_ch_chain->state = CHAIN_STATE_UPDATE_GLOBAL_DB_REMOTE; - dap_stream_ch_chain_hash_item_t *l_hash_item = NULL, *l_tmp = NULL; - HASH_ITER(hh, l_ch_chain->remote_gdbs, l_hash_item, l_tmp) { - HASH_DEL(l_ch_chain->remote_gdbs, l_hash_item); - DAP_DELETE(l_hash_item); - } - }break; + } break; // Response with gdb element hashes and sizes case DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB:{ if(s_debug_more) @@ -858,14 +824,14 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) memcpy(&l_hash_item->hash, &l_element->hash, sizeof (l_element->hash)); l_hash_item->size = l_element->size; HASH_ADD(hh, l_ch_chain->remote_gdbs, hash, sizeof (l_hash_item->hash), l_hash_item); - if (s_debug_more){ + /*if (s_debug_more){ char l_hash_str[72]={ [0]='\0'}; dap_chain_hash_fast_to_str(&l_hash_item->hash,l_hash_str,sizeof (l_hash_str)); - log_it(L_INFO,"In: Updated remote hash gdb list with %s ", l_hash_str); - } + log_it(L_DEBUG,"In: Updated remote hash gdb list with %s ", l_hash_str); + }*/ } } - }break; + } break; // End of response with starting of DB sync case DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_GLOBAL_DB: case DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB_END: { @@ -893,8 +859,9 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) else log_it(L_INFO, "In: SYNC_GLOBAL_DB pkt"); } + if (l_chain_pkt_data_size == sizeof(dap_stream_ch_chain_sync_request_t)) + memcpy(&l_ch_chain->request, l_chain_pkt->data, sizeof(dap_stream_ch_chain_sync_request_t)); struct sync_request *l_sync_request = dap_stream_ch_chain_create_sync_request(l_chain_pkt, a_ch); - l_ch_chain->state = CHAIN_STATE_SYNC_GLOBAL_DB; dap_proc_queue_add_callback_inter(a_ch->stream_worker->worker->proc_queue_input, s_sync_out_gdb_proc_callback, l_sync_request); }else{ log_it(L_WARNING, "DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_GLOBAL_DB: Wrong chain packet size %zd when expected %zd", l_chain_pkt_data_size, sizeof(l_ch_chain->request)); @@ -943,7 +910,6 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64); if (!l_ch_chain->callback_notify_packet_in) { // we haven't node client waitng, so reply to other side dap_stream_ch_chain_sync_request_t l_sync_gdb = {}; - l_sync_gdb.id_start = dap_db_get_last_id_remote(l_sync_gdb.node_addr.uint64); dap_chain_net_t *l_net = dap_chain_net_by_id(l_chain_pkt->hdr.net_id); l_sync_gdb.node_addr.uint64 = dap_chain_net_get_cur_addr_int(l_net); dap_stream_ch_chain_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB_REQ, l_chain_pkt->hdr.net_id.uint64, @@ -953,7 +919,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) case DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_GLOBAL_DB_RVRS: { dap_stream_ch_chain_sync_request_t l_sync_gdb = {}; - l_sync_gdb.id_start = dap_db_get_last_id_remote(l_sync_gdb.node_addr.uint64); + l_sync_gdb.id_start = 1; dap_chain_net_t *l_net = dap_chain_net_by_id(l_chain_pkt->hdr.net_id); l_sync_gdb.node_addr.uint64 = dap_chain_net_get_cur_addr_int(l_net); log_it(L_INFO, "In: SYNC_GLOBAL_DB_RVRS pkt: net 0x%016x chain 0x%016x cell 0x%016x, request gdb sync from %u", l_chain_pkt->hdr.net_id.uint64 , @@ -969,7 +935,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) } break; case DAP_STREAM_CH_CHAIN_PKT_TYPE_FIRST_GLOBAL_DB_GROUP: { if (s_debug_more) - log_it(L_INFO, "In: SYNCED_GLOBAL_DB_GROUP pkt net 0x%016x chain 0x%016x cell 0x%016x", l_chain_pkt->hdr.net_id.uint64 , + log_it(L_INFO, "In: FIRST_GLOBAL_DB_GROUP pkt net 0x%016x chain 0x%016x cell 0x%016x", l_chain_pkt->hdr.net_id.uint64 , l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64); } break; @@ -999,11 +965,12 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) l_chain_pkt->hdr.net_id.uint64,l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64, NULL, 0); } - }break; + } break; // Response with metadata organized in TSD case DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_CHAINS_TSD :{ - - }break; + if (s_debug_more) + log_it(L_DEBUG, "Chain TSD packet detected"); + } break; // If requested - begin to send atom hashes case DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_CHAINS_START:{ @@ -1029,19 +996,14 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) } l_ch_chain->state = CHAIN_STATE_UPDATE_CHAINS_REMOTE; memcpy(&l_ch_chain->request_hdr, &l_chain_pkt->hdr, sizeof(dap_stream_ch_chain_pkt_hdr_t)); - dap_stream_ch_chain_hash_item_t *l_hash_item = NULL, *l_tmp = NULL; - HASH_ITER(hh, l_ch_chain->remote_atoms, l_hash_item, l_tmp) { - HASH_DEL(l_ch_chain->remote_atoms, l_hash_item); - DAP_DELETE(l_hash_item); - } if(s_debug_more) log_it(L_INFO,"In: UPDATE_CHAINS_START pkt"); } break; // Response with atom hashes and sizes case DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_CHAINS :{ - uint l_count_added=0; - uint l_count_total=0; + unsigned int l_count_added=0; + unsigned int l_count_total=0; dap_chain_t * l_chain = dap_chain_find_by_id(l_chain_pkt->hdr.net_id, l_chain_pkt->hdr.chain_id); if (! l_chain){ @@ -1119,13 +1081,16 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) } struct sync_request *l_sync_request = dap_stream_ch_chain_create_sync_request(l_chain_pkt, a_ch); l_ch_chain->state = CHAIN_STATE_SYNC_CHAINS; - char *l_hash_from_str = dap_chain_hash_fast_to_str_new(&l_ch_chain->request.hash_from); - char *l_hash_to_str = dap_chain_hash_fast_to_str_new(&l_ch_chain->request.hash_to); - log_it(L_INFO, "In: SYNC_CHAINS pkt: net 0x%016x chain 0x%016x cell 0x%016x between %s and %s", l_ch_chain->request_hdr.net_id.uint64 , - l_ch_chain->request_hdr.chain_id.uint64, l_ch_chain->request_hdr.cell_id.uint64, - l_hash_from_str? l_hash_from_str: "(null)", l_hash_to_str?l_hash_to_str:"(null)"); - DAP_DELETE(l_hash_from_str); - DAP_DELETE(l_hash_to_str); + l_ch_chain->stats_request_atoms_processed = 0; + if (l_ch_pkt->hdr.type == DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_CHAINS) { + char *l_hash_from_str = dap_chain_hash_fast_to_str_new(&l_ch_chain->request.hash_from); + char *l_hash_to_str = dap_chain_hash_fast_to_str_new(&l_ch_chain->request.hash_to); + log_it(L_INFO, "In: SYNC_CHAINS pkt: net 0x%016x chain 0x%016x cell 0x%016x between %s and %s", l_ch_chain->request_hdr.net_id.uint64 , + l_ch_chain->request_hdr.chain_id.uint64, l_ch_chain->request_hdr.cell_id.uint64, + l_hash_from_str? l_hash_from_str: "(null)", l_hash_to_str?l_hash_to_str:"(null)"); + DAP_DELETE(l_hash_from_str); + DAP_DELETE(l_hash_to_str); + } dap_proc_queue_add_callback_inter(a_ch->stream_worker->worker->proc_queue_input, s_sync_out_chains_proc_callback, l_sync_request); } else { log_it(L_WARNING, "DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_CHAINS: Wrong chain packet size %zd when expected %zd", @@ -1144,7 +1109,6 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) NODE_ADDR_FP_ARGS_S(l_ch_chain->request.node_addr), l_chain_pkt_data_size, l_ch_chain->request_hdr.net_id.uint64 , l_ch_chain->request_hdr.chain_id.uint64, l_ch_chain->request_hdr.cell_id.uint64); - l_ch_chain->stats_request_atoms_processed = 0; }else{ log_it(L_WARNING,"Incorrect data size %zd in packet DAP_STREAM_CH_CHAIN_PKT_TYPE_FIRST_CHAIN", l_chain_pkt_data_size); s_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64, @@ -1205,6 +1169,9 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) "ERROR_NET_INVALID_ID"); break; } + if (s_debug_more) { + log_it(L_INFO, "Out: UPDATE_CHAINS_REQ pkt"); + } dap_stream_ch_chain_sync_request_t l_request= {}; dap_stream_ch_chain_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_CHAINS_REQ, l_chain_pkt->hdr.net_id.uint64, l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64, &l_request, sizeof(l_request)); @@ -1241,14 +1208,13 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) l_error_str[l_chain_pkt_data_size-1]='\0'; // To be sure that nobody sends us garbage // without trailing zero log_it(L_WARNING,"In from remote addr %s chain id 0x%016x got error on his side: '%s'", - l_ch_chain->ch->stream->esocket->remote_addr_str? - l_ch_chain->ch->stream->esocket->remote_addr_str: "<no addr>", - l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt_data_size>1? l_error_str:"<empty>"); + l_ch_chain->ch->stream->esocket->remote_addr_str ? l_ch_chain->ch->stream->esocket->remote_addr_str: "<no addr>", + l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt_data_size > 1 ? l_error_str:"<empty>"); } break; case DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_ALL: { log_it(L_INFO, "In from "NODE_ADDR_FP_STR": SYNCED_ALL net 0x%016x chain 0x%016x cell 0x%016x",NODE_ADDR_FP_ARGS_S(l_ch_chain->node_client->remote_node_addr), l_chain_pkt->hdr.net_id.uint64 , - l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64); + l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64); } break; default: { @@ -1285,29 +1251,17 @@ void dap_stream_ch_chain_go_idle ( dap_stream_ch_chain_t * a_ch_chain) } DAP_DEL_Z(a_ch_chain->request_atom_iter); } -} - -static void s_process_gdb_iter(dap_stream_ch_t *a_ch) -{ - dap_stream_ch_chain_t *l_ch_chain = DAP_STREAM_CH_CHAIN(a_ch); - dap_db_log_list_t *l_db_list = l_ch_chain->request_global_db_trs; - dap_store_obj_pkt_t *l_pkt = (dap_store_obj_pkt_t *)l_ch_chain->request_db_iter->data; - uint32_t l_pkt_size = sizeof(dap_store_obj_pkt_t) + l_pkt->data_size; - // TODO find current record hash and compare it with hash table - if( s_debug_more) - log_it(L_INFO, "Send one global_db record packet len=%d (rest=%d/%d items)", l_pkt_size, - dap_db_log_list_get_count_rest(l_db_list), dap_db_log_list_get_count(l_db_list)); - dap_stream_ch_chain_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_GLOBAL_DB, - l_ch_chain->request_hdr.net_id.uint64, l_ch_chain->request_hdr.chain_id.uint64, - l_ch_chain->request_hdr.cell_id.uint64, l_pkt, l_pkt_size); - dap_list_t *l_iter = dap_list_next(l_ch_chain->request_db_iter); - if (l_iter) { - l_ch_chain->request_db_iter = l_iter; - } else { - l_ch_chain->stats_request_gdb_processed++; - l_ch_chain->request_db_iter = dap_list_first(l_ch_chain->request_db_iter); - dap_list_free_full(l_ch_chain->request_db_iter, free); - l_ch_chain->request_db_iter = NULL; + // free log list + dap_db_log_list_delete(a_ch_chain->request_db_log); + a_ch_chain->request_db_log = NULL; + dap_stream_ch_chain_hash_item_t *l_hash_item = NULL, *l_tmp = NULL; + HASH_ITER(hh, a_ch_chain->remote_gdbs, l_hash_item, l_tmp) { + HASH_DEL(a_ch_chain->remote_gdbs, l_hash_item); + DAP_DELETE(l_hash_item); + } + HASH_ITER(hh, a_ch_chain->remote_atoms, l_hash_item, l_tmp) { + HASH_DEL(a_ch_chain->remote_atoms, l_hash_item); + DAP_DELETE(l_hash_item); } } @@ -1325,69 +1279,104 @@ void s_stream_ch_packet_out(dap_stream_ch_t* a_ch, void* a_arg) dap_stream_ch_chain_t *l_ch_chain = DAP_STREAM_CH_CHAIN(a_ch); switch (l_ch_chain->state) { - // Update list of global DB records to remote case CHAIN_STATE_UPDATE_GLOBAL_DB: { - if (l_ch_chain->stats_request_gdb_processed == l_ch_chain->local_gdbs_count) { - dap_stream_ch_chain_sync_request_t l_sync_gdb = {}; - l_sync_gdb.id_start = dap_db_get_last_id_remote(l_ch_chain->request.node_addr.uint64); - dap_chain_net_t *l_net = dap_chain_net_by_id(l_ch_chain->request_hdr.net_id); - l_sync_gdb.node_addr.uint64 = dap_chain_net_get_cur_addr_int(l_net); - dap_stream_ch_chain_pkt_write_unsafe(l_ch_chain->ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB_END, - l_ch_chain->request_hdr.net_id.uint64, l_ch_chain->request_hdr.chain_id.uint64, - l_ch_chain->request_hdr.cell_id.uint64, &l_sync_gdb, sizeof(dap_stream_ch_chain_sync_request_t)); - if (s_debug_more ) - log_it(L_INFO, "Out: DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB_END"); - dap_stream_ch_chain_go_idle(l_ch_chain); - } else { - uint_fast16_t l_count = l_ch_chain->local_gdbs_count - l_ch_chain->stats_request_gdb_processed; - if (l_count > s_update_pack_size) - l_count = s_update_pack_size; + dap_stream_ch_chain_update_element_t l_data[s_update_pack_size]; + uint_fast16_t i; + for (i = 0; i < s_update_pack_size; i++) { + dap_db_log_list_obj_t *l_obj = dap_db_log_list_get(l_ch_chain->request_db_log); + if (!l_obj) + break; + memcpy(&l_data[i].hash, &l_obj->hash, sizeof(dap_chain_hash_fast_t)); + l_data[i].size = l_obj->pkt->data_size; + } + if (i) { dap_stream_ch_chain_pkt_write_unsafe(l_ch_chain->ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB, l_ch_chain->request_hdr.net_id.uint64, l_ch_chain->request_hdr.chain_id.uint64, l_ch_chain->request_hdr.cell_id.uint64, - &l_ch_chain->local_gdbs[l_ch_chain->stats_request_gdb_processed], - l_count * sizeof(dap_stream_ch_chain_update_element_t)); - l_ch_chain->stats_request_gdb_processed += l_count; + l_data, i * sizeof(dap_stream_ch_chain_update_element_t)); + l_ch_chain->stats_request_gdb_processed += i; if (s_debug_more) log_it(L_INFO, "Out: DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB"); + } else { + l_ch_chain->request.node_addr.uint64 = dap_chain_net_get_cur_addr_int(dap_chain_net_by_id( + l_ch_chain->request_hdr.net_id)); + dap_stream_ch_chain_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB_END, + l_ch_chain->request_hdr.net_id.uint64, + l_ch_chain->request_hdr.chain_id.uint64, + l_ch_chain->request_hdr.cell_id.uint64, + &l_ch_chain->request, sizeof(dap_stream_ch_chain_sync_request_t)); + if (s_debug_more ) + log_it(L_INFO, "Out: DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB_END"); + dap_stream_ch_chain_go_idle(l_ch_chain); } } break; // Synchronize GDB case CHAIN_STATE_SYNC_GLOBAL_DB: { - if (l_ch_chain->request_db_iter) { - s_process_gdb_iter(a_ch); - } else { - dap_global_db_obj_t *l_obj; - do { // Get log diff - size_t l_item_size_out = 0; - l_obj = dap_db_log_list_get(l_ch_chain->request_global_db_trs); - l_ch_chain->request_db_iter = dap_db_log_pack(l_obj, &l_item_size_out); - if (l_ch_chain->request_db_iter && l_item_size_out) { - break; - } - // Item not found, maybe it has deleted? Then go to the next item - } while (l_obj); - if (l_ch_chain->request_db_iter) { - s_process_gdb_iter(a_ch); + // Get global DB record + dap_store_obj_pkt_t *l_pkt = NULL; + dap_db_log_list_obj_t *l_obj = NULL; + size_t l_pkt_size = 0; + for (uint_fast16_t l_skip_count = 0; l_skip_count < s_skip_in_reactor_count; ) { + l_obj = dap_db_log_list_get(l_ch_chain->request_db_log); + if (!l_obj) + break; + dap_stream_ch_chain_hash_item_t *l_hash_item = NULL; + HASH_FIND(hh, l_ch_chain->remote_gdbs, &l_obj->hash, sizeof(dap_hash_fast_t), l_hash_item); + if (l_hash_item) { // If found - skip it + /*if (s_debug_more) { + char l_request_atom_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE]; + dap_chain_hash_fast_to_str(&l_obj->hash, l_request_atom_hash_str, DAP_CHAIN_HASH_FAST_STR_SIZE); + log_it(L_DEBUG, "Out CHAIN: skip GDB hash %s because its already present in remote GDB hash table", + l_request_atom_hash_str); + }*/ + l_skip_count++; } else { - // free log list - dap_db_log_list_delete(l_ch_chain->request_global_db_trs); - l_ch_chain->request_global_db_trs = NULL; - log_it( L_INFO,"Syncronized database: last id %"DAP_UINT64_FORMAT_U", items syncronyzed %"DAP_UINT64_FORMAT_U" ", dap_db_log_get_last_id(), - l_ch_chain->stats_request_gdb_processed ); - // last message - dap_stream_ch_chain_sync_request_t l_request = {}; - dap_stream_ch_chain_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB, - l_ch_chain->request_hdr.net_id.uint64, l_ch_chain->request_hdr.chain_id.uint64, - l_ch_chain->request_hdr.cell_id.uint64, &l_request, sizeof(l_request)); - dap_stream_ch_chain_go_idle(l_ch_chain); - if (l_ch_chain->callback_notify_packet_out) - l_ch_chain->callback_notify_packet_out(l_ch_chain, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB, - NULL, 0, l_ch_chain->callback_notify_arg); + if (l_ch_chain->request.node_addr.uint64) { + dap_db_set_last_id_remote(l_ch_chain->request.node_addr.uint64, + dap_store_packet_get_id(l_obj->pkt), + dap_store_packet_get_group(l_obj->pkt)); + } + l_hash_item = DAP_NEW(dap_stream_ch_chain_hash_item_t); + memcpy(&l_hash_item->hash, &l_obj->hash, sizeof(dap_chain_hash_fast_t)); + l_hash_item->size = l_obj->pkt->data_size; + HASH_ADD(hh, l_ch_chain->remote_gdbs, hash, sizeof(dap_chain_hash_fast_t), l_hash_item); + l_pkt = dap_store_packet_multiple(l_pkt, l_obj->pkt); + l_ch_chain->stats_request_gdb_processed++; + l_pkt_size = sizeof(dap_store_obj_pkt_t) + l_pkt->data_size; + if (l_pkt_size >= DAP_CHAIN_PKT_EXPECT_SIZE) + break; } } + if (l_pkt_size) { + // If request was from defined node_addr we update its state + if( s_debug_more) + log_it(L_INFO, "Send one global_db packet len=%d (rest=%d/%d items)", l_pkt_size, + dap_db_log_list_get_count_rest(l_ch_chain->request_db_log), + dap_db_log_list_get_count(l_ch_chain->request_db_log)); + dap_stream_ch_chain_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_GLOBAL_DB, + l_ch_chain->request_hdr.net_id.uint64, l_ch_chain->request_hdr.chain_id.uint64, + l_ch_chain->request_hdr.cell_id.uint64, l_pkt, l_pkt_size); + DAP_DELETE(l_pkt); + } else if (l_obj) { + // Sending dumb packet with nothing to inform remote thats we're just skiping GDBs, nothing freezed + dap_stream_ch_chain_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB_TSD, + l_ch_chain->request_hdr.net_id.uint64, l_ch_chain->request_hdr.chain_id.uint64, + l_ch_chain->request_hdr.cell_id.uint64, NULL, 0); + } else { + log_it( L_INFO,"Syncronized database: items syncronyzed %"DAP_UINT64_FORMAT_u" from %"DAP_UINT64_FORMAT_u"", + l_ch_chain->stats_request_gdb_processed, dap_db_log_list_get_count(l_ch_chain->request_db_log)); + // last message + dap_stream_ch_chain_sync_request_t l_request = {}; + dap_stream_ch_chain_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB, + l_ch_chain->request_hdr.net_id.uint64, l_ch_chain->request_hdr.chain_id.uint64, + l_ch_chain->request_hdr.cell_id.uint64, &l_request, sizeof(l_request)); + dap_stream_ch_chain_go_idle(l_ch_chain); + if (l_ch_chain->callback_notify_packet_out) + l_ch_chain->callback_notify_packet_out(l_ch_chain, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB, + NULL, 0, l_ch_chain->callback_notify_arg); + } } break; // Update list of atoms to remote @@ -1478,6 +1467,8 @@ void s_stream_ch_packet_out(dap_stream_ch_t* a_ch, void* a_arg) } // Then get next atom and populate new last l_ch_chain->request_atom_iter->chain->callback_atom_iter_get_next(l_ch_chain->request_atom_iter, NULL); + if (l_was_sent_smth) + break; } if(!l_ch_chain->request_atom_iter || !l_ch_chain->request_atom_iter->cur) { // All chains synced dap_stream_ch_chain_sync_request_t l_request = {0}; diff --git a/modules/channel/chain/include/dap_stream_ch_chain.h b/modules/channel/chain/include/dap_stream_ch_chain.h index 07cd345916bd4ac0b1567405d083743aa4539418..5fd46f5c682158bb1b8c4b9323297161383170e6 100644 --- a/modules/channel/chain/include/dap_stream_ch_chain.h +++ b/modules/channel/chain/include/dap_stream_ch_chain.h @@ -65,31 +65,23 @@ typedef struct dap_stream_ch_chain { uint64_t stats_request_atoms_processed; uint64_t stats_request_gdb_processed; - - dap_stream_ch_chain_update_element_t *local_gdbs; - uint64_t local_gdbs_count; dap_stream_ch_chain_hash_item_t * remote_atoms; // Remote atoms dap_stream_ch_chain_hash_item_t * remote_gdbs; // Remote gdbs // request section dap_chain_atom_iter_t *request_atom_iter; - dap_db_log_list_t *request_global_db_trs; // list of global db records + dap_db_log_list_t *request_db_log; // list of global db records dap_stream_ch_chain_sync_request_t request; dap_stream_ch_chain_pkt_hdr_t request_hdr; dap_list_t *request_db_iter; - bool request_updates_complete; - - bool is_on_request; // Protects request section - bool is_on_reverse_request; - dap_stream_ch_chain_callback_packet_t callback_notify_packet_out; dap_stream_ch_chain_callback_packet_t callback_notify_packet_in; void *callback_notify_arg; } dap_stream_ch_chain_t; #define DAP_STREAM_CH_CHAIN(a) ((dap_stream_ch_chain_t *) ((a)->internal) ) - +#define DAP_CHAIN_PKT_EXPECT_SIZE 7168 int dap_stream_ch_chain_init(void); void dap_stream_ch_chain_deinit(void); diff --git a/modules/common/dap_chain_datum_tx_items.c b/modules/common/dap_chain_datum_tx_items.c index 7af1ea5a5130319edef32298a345619a4b11366e..96f0ae56df8970dd701729f088e9d0bcc0607efa 100644 --- a/modules/common/dap_chain_datum_tx_items.c +++ b/modules/common/dap_chain_datum_tx_items.c @@ -156,7 +156,6 @@ dap_chain_tx_token_t* dap_chain_datum_tx_item_token_create(dap_chain_hash_fast_t l_item->header.type = TX_ITEM_TYPE_TOKEN; memcpy (& l_item->header.token_emission_hash, a_datum_token_hash, sizeof ( *a_datum_token_hash ) ); strncpy(l_item->header.ticker, a_ticker, sizeof(l_item->header.ticker) - 1); - return l_item; } diff --git a/modules/consensus/none/dap_chain_cs_none.c b/modules/consensus/none/dap_chain_cs_none.c index 707465f28882e1a2f4fbd0d152680aa410c1972d..b3bae67c29784c400075212ca7816f8bb8fcb6a5 100644 --- a/modules/consensus/none/dap_chain_cs_none.c +++ b/modules/consensus/none/dap_chain_cs_none.c @@ -128,7 +128,7 @@ int dap_chain_gdb_init(void) * @param a_value * @param a_value_len */ -static void s_history_callback_notify(void * a_arg, const char a_op_code, const char * a_prefix, const char * a_group, +static void s_history_callback_notify(void * a_arg, const char a_op_code, const char * a_group, const char * a_key, const void * a_value, const size_t a_value_size) { if (a_arg){ @@ -136,8 +136,8 @@ static void s_history_callback_notify(void * a_arg, const char a_op_code, const dap_chain_net_t *l_net = dap_chain_net_by_id( l_gdb->chain->net_id); log_it(L_DEBUG,"%s.%s: op_code='%c' group=\"%s\" key=\"%s\" value_size=%u",l_net->pub.name, l_gdb->chain->name, a_op_code, a_group, a_key, a_value_size); - dap_chain_node_mempool_autoproc_notify((void *)l_net, a_op_code, a_prefix, a_group, a_key, a_value, a_value_size); - dap_chain_net_sync_gdb_broadcast((void *)l_net, a_op_code, a_prefix, a_group, a_key, a_value, a_value_size); + dap_chain_node_mempool_autoproc_notify((void *)l_net, a_op_code, a_group, a_key, a_value, a_value_size); + dap_chain_net_sync_gdb_broadcast((void *)l_net, a_op_code, a_group, a_key, a_value, a_value_size); } } @@ -174,9 +174,7 @@ int dap_chain_gdb_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg) } // Add group prefix that will be tracking all changes - dap_chain_global_db_add_history_group_prefix("chain-gdb", GROUP_LOCAL_HISTORY); - - dap_chain_global_db_add_history_callback_notify("chain-gdb", s_history_callback_notify,l_gdb); + dap_chain_global_db_add_sync_group("chain-gdb", s_history_callback_notify, l_gdb); // load ledger l_gdb_priv->is_load_mode = true; diff --git a/modules/global-db/dap_chain_global_db.c b/modules/global-db/dap_chain_global_db.c index 4a6ca4f938b1284b2f59c8845c23d91e8948505a..829c573e043ad52c2c514062ad86dadc3243d31b 100644 --- a/modules/global-db/dap_chain_global_db.c +++ b/modules/global-db/dap_chain_global_db.c @@ -62,135 +62,68 @@ static inline void unlock() } // Callback table item -typedef struct history_group_item +typedef struct sync_group_item { - char prefix[32]; - uint8_t padding[7]; - bool auto_track; // Track history actions automaticly - dap_global_db_obj_callback_notify_t callback_notify; - void * callback_arg; - char *group_name_for_history; - UT_hash_handle hh; -} history_group_item_t; - -// Callback table item -typedef struct history_extra_group_item -{ - char *group_name; + char *group_mask; char *group_name_for_history; dap_global_db_obj_callback_notify_t callback_notify; void * callback_arg; UT_hash_handle hh; -} history_extra_group_item_t; +} sync_group_item_t; // Tacked group callbacks -static history_group_item_t * s_history_group_items = NULL; -static history_extra_group_item_t * s_history_extra_group_items = NULL; -char * extract_group_prefix(const char * a_group); +static sync_group_item_t *s_sync_group_items = NULL; +static sync_group_item_t *s_sync_group_extra_items = NULL; +static bool s_track_history = false; /** - * @brief extract_group_prefix - * @param a_group - * @return - */ -char * extract_group_prefix(const char* a_group) -{ - char * l_group_prefix = NULL, *l_delimeter; - size_t l_group_prefix_size; - -// l_delimeter = index(a_group, '.'); - l_delimeter = strchr(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 = strndup(a_group, l_group_prefix_size); - } - return l_group_prefix; -} - - -/* - * Get history group by group name + * @brief dap_chain_global_db_add_sync_group + * @details Add group name for synchronization + * @param a_group_prefix */ -char* dap_chain_global_db_get_history_group_by_group_name(const char * a_group_name) +void dap_chain_global_db_add_sync_group(const char *a_group_prefix, dap_global_db_obj_callback_notify_t a_callback, void *a_arg) { - if(!s_history_extra_group_items || !a_group_name) - return NULL; - history_extra_group_item_t * l_history_extra_group_item = NULL; - HASH_FIND_STR(s_history_extra_group_items, a_group_name, l_history_extra_group_item); - if(l_history_extra_group_item) { - return dap_strdup(l_history_extra_group_item->group_name_for_history); - }else - return NULL; + sync_group_item_t * l_item = DAP_NEW_Z(sync_group_item_t); + l_item->group_mask = dap_strdup_printf("%s.*", a_group_prefix); + l_item->group_name_for_history = dap_strdup(GROUP_LOCAL_HISTORY); + l_item->callback_notify = a_callback; + l_item->callback_arg = a_arg; + HASH_ADD_STR(s_sync_group_items, group_mask, l_item); } /** - * @brief dap_chain_global_db_add_history_group_prefix - * @details Add group prefix that will be tracking all changes + * @brief dap_chain_global_db_add_sync_extra_group + * @details Add group name for synchronization with especially node addresses * @param a_group_prefix - * @param a_group_name_for_history */ -void dap_chain_global_db_add_history_group_prefix(const char * a_group_prefix, const char * a_group_name_for_history) +void dap_chain_global_db_add_sync_extra_group(const char *a_group_mask, dap_global_db_obj_callback_notify_t a_callback, void *a_arg) { - 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); - l_item->group_name_for_history = dap_strdup(a_group_name_for_history);//GROUP_LOCAL_HISTORY - l_item->auto_track = true; - HASH_ADD_STR(s_history_group_items, prefix, l_item); + sync_group_item_t* l_item = DAP_NEW_Z(sync_group_item_t); + l_item->group_mask = dap_strdup(a_group_mask); + l_item->group_name_for_history = dap_strdup(GROUP_LOCAL_HISTORY".extra"); + l_item->callback_notify = a_callback; + l_item->callback_arg = a_arg; + HASH_ADD_STR(s_sync_group_extra_items, group_mask, l_item); } -/** - * @brief dap_chain_global_db_add_history_callback_notify - * @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) +dap_list_t *dap_chain_db_get_sync_groups_internal(sync_group_item_t *a_table) { - history_group_item_t * l_item = NULL; - HASH_FIND_STR(s_history_group_items, a_group_prefix, 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); + dap_list_t *l_ret = NULL; + sync_group_item_t *l_item = NULL, *l_item_tmp = NULL; + HASH_ITER(hh, a_table, l_item, l_item_tmp) { + l_ret = dap_list_append(l_ret, l_item->group_mask); + } + return l_ret; } -/** - * @brief dap_chain_global_db_add_history_extra_group - * @details Add group prefix that will be tracking all changes - * @param a_group_prefix - */ -const char* dap_chain_global_db_add_history_extra_group(const char * a_group_name, dap_chain_node_addr_t *a_nodes, uint16_t *a_nodes_count) +dap_list_t *dap_chain_db_get_sync_groups() { - history_extra_group_item_t* l_item = DAP_NEW_Z(history_extra_group_item_t); - l_item->group_name = dap_strdup(a_group_name); - l_item->group_name_for_history = dap_strdup_printf("local.history.%s", a_group_name); - HASH_ADD_STR(s_history_extra_group_items, group_name, l_item); - return (const char*)l_item->group_name_for_history; + return dap_chain_db_get_sync_groups_internal(s_sync_group_items); } -/** - * @brief dap_chain_global_db_add_history_extra_group_callback_notify - * @param a_group_prefix - * @param a_callback - */ -void dap_chain_global_db_add_history_extra_group_callback_notify(const char * a_group_prefix, - dap_global_db_obj_callback_notify_t a_callback, void * a_arg) +dap_list_t *dap_chain_db_get_sync_extra_groups() { - history_extra_group_item_t * l_item = NULL; - HASH_FIND_STR(s_history_extra_group_items, a_group_prefix, 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 extra groups with prefix %s. Possible not in history track state", - a_group_prefix); + return dap_chain_db_get_sync_groups_internal(s_sync_group_extra_items); } /** @@ -220,13 +153,8 @@ void dap_chain_global_db_obj_delete(dap_global_db_obj_t *obj) */ void dap_chain_global_db_objs_delete(dap_global_db_obj_t *objs, size_t a_count) { - //int i = 0; - //while(objs) { for(size_t i = 0; i < a_count; i++) { - //if(!(objs[i])) - // break; dap_chain_global_db_obj_clean(objs + i); - //i++; } DAP_DELETE(objs); } @@ -239,8 +167,9 @@ void dap_chain_global_db_objs_delete(dap_global_db_obj_t *objs, size_t a_count) int dap_chain_global_db_init(dap_config_t * g_config) { const char *l_storage_path = dap_config_get_item_str(g_config, "resources", "dap_global_db_path"); - //const char *l_driver_name = dap_config_get_item_str_default(g_config, "resources", "dap_global_db_driver", "sqlite"); - const char *l_driver_name = dap_config_get_item_str_default(g_config, "resources", "dap_global_db_driver", "cdb"); + const char *l_driver_name = dap_config_get_item_str_default(g_config, "resources", "dap_global_db_driver", "sqlite"); + //const char *l_driver_name = dap_config_get_item_str_default(g_config, "resources", "dap_global_db_driver", "cdb"); + s_track_history = dap_config_get_item_bool_default(g_config, "resources", "dap_global_db_track_history", s_track_history); lock(); int res = dap_db_driver_init(l_driver_name, l_storage_path); unlock(); @@ -260,20 +189,20 @@ void dap_chain_global_db_deinit(void) dap_db_driver_deinit(); //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) + sync_group_item_t * l_item = NULL, *l_item_tmp = NULL; + HASH_ITER(hh, s_sync_group_items, l_item, l_item_tmp) { DAP_DELETE(l_item->group_name_for_history); DAP_DELETE(l_item); } - history_extra_group_item_t * l_add_item = NULL, *l_add_item_tmp = NULL; - HASH_ITER(hh, s_history_extra_group_items, l_add_item, l_add_item_tmp) + sync_group_item_t * l_add_item = NULL, *l_add_item_tmp = NULL; + HASH_ITER(hh, s_sync_group_extra_items, l_add_item, l_add_item_tmp) { - DAP_DELETE(l_add_item->group_name); + DAP_DELETE(l_add_item->group_mask); DAP_DELETE(l_add_item->group_name_for_history); DAP_DELETE(l_add_item); } - s_history_group_items = NULL; + s_sync_group_items = NULL; } @@ -299,19 +228,6 @@ void* dap_chain_global_db_obj_get(const char *a_key, const char *a_group) // 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;*/ } /** @@ -323,18 +239,14 @@ 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 *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_data_len_out;//l_store_data->value_len; - //dap_store_obj_free(l_store_data, l_data_len_out); + *a_data_len_out = l_data_len_out; } return l_store_data; } @@ -363,28 +275,6 @@ uint8_t * dap_chain_global_db_gr_get(const char *a_key, size_t *a_data_len_out, dap_store_obj_free(l_store_data, l_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; - } - 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) @@ -398,18 +288,20 @@ uint8_t * dap_chain_global_db_get(const char *a_key, size_t *a_data_out) */ 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)); + dap_store_obj_t store_data; memset(&store_data, 0, sizeof(dap_store_obj_t)); store_data.type = 'a'; - store_data.key = a_key;//dap_strdup(a_key); + store_data.key = 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); + store_data.timestamp = a_timestamp; lock(); - int l_res = dap_chain_global_db_driver_add(&store_data, 1); + int l_res = 0; + if (!dap_chain_global_db_driver_is(store_data.group, store_data.key)) + l_res = dap_chain_global_db_driver_add(&store_data, 1); unlock(); DAP_DELETE(store_data.group); if(l_res>=0) @@ -420,11 +312,11 @@ static bool global_db_gr_del_add(char *a_key,const char *a_group, time_t a_times /** * Delete info about the deleted entry from the base */ -static bool global_db_gr_del_del(char *a_key,const char *a_group) +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)); + 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; @@ -456,7 +348,7 @@ time_t global_db_gr_del_get_timestamp(const char *a_group, char *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)) { + 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); @@ -468,155 +360,7 @@ time_t global_db_gr_del_get_timestamp(const char *a_group, char *a_key) return l_timestamp; } -/** - * - */ - -/** - * @brief dap_chain_global_db_gr_set - * @param a_key - * @param a_value - * @param a_value_len - * @param a_group - * @details Set one entry to base. IMPORTANT: a_key and a_value should be passed without free after (it will be released by gdb itself) - * @return - */ -bool dap_chain_global_db_gr_set(char *a_key, void *a_value, size_t a_value_len, const char *a_group) -{ - 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); - store_data.value = a_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) ? dap_strlen((const char*) a_value) : a_value_len; - store_data.group = (char*)a_group;//dap_strdup(a_group); - store_data.timestamp = time(NULL); - lock(); - 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) { - // 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) - 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('a', &store_data, 1, l_history_group_item->group_name_for_history); - 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); - } - // looking for extra group - else { - history_extra_group_item_t * l_history_extra_group_item = NULL; - HASH_FIND_STR(s_history_extra_group_items, a_group, l_history_extra_group_item); - - if(l_history_extra_group_item) { - lock(); - dap_db_history_add('a', &store_data, 1, l_history_extra_group_item->group_name_for_history); - unlock(); - if(l_history_extra_group_item->callback_notify) - l_history_extra_group_item->callback_notify(l_history_extra_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); - } - //DAP_DELETE(store_data); - - return !l_res; -} - -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 - */ -bool dap_chain_global_db_gr_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.group = (char*)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; - 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('d', &store_data, 1, l_history_group_item->group_name_for_history); - 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); - } - // looking for extra group - else { - history_extra_group_item_t * l_history_extra_group_item = NULL; - HASH_FIND_STR(s_history_extra_group_items, a_group, l_history_extra_group_item); - - if(l_history_extra_group_item) { - lock(); - dap_db_history_add('d', &store_data, 1, l_history_extra_group_item->group_name_for_history); - unlock(); - if(l_history_extra_group_item->callback_notify) - l_history_extra_group_item->callback_notify(l_history_extra_group_item->callback_arg, 'd', - l_group_prefix, a_group, a_key, NULL, 0); - } - } - if(l_group_prefix) - DAP_DELETE(l_group_prefix); - } - //DAP_DELETE(store_data); - 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) { return dap_chain_global_db_gr_del(a_key, GROUP_LOCAL_GENERAL); @@ -687,6 +431,120 @@ dap_global_db_obj_t* dap_chain_global_db_load(size_t *a_data_size_out) { return dap_chain_global_db_gr_load(GROUP_LOCAL_GENERAL, a_data_size_out); } + +/** + * @brief extract_group_mask + * @param a_group + * @return + */ +static sync_group_item_t *find_item_by_mask(sync_group_item_t *a_items, const char *a_group) +{ + sync_group_item_t * l_item = NULL, *l_item_tmp = NULL; + HASH_ITER(hh, a_items, l_item, l_item_tmp) { + if (!dap_fnmatch(l_item->group_mask, a_group, 0)) + return l_item; + } + return NULL; +} + + +void dap_global_db_obj_track_history(void* a_store_data) +{ + if (!s_track_history) + return; + dap_store_obj_t *l_obj = (dap_store_obj_t *)a_store_data; + sync_group_item_t *l_sync_group_item = find_item_by_mask(s_sync_group_items, l_obj->group); + if(l_sync_group_item) { + lock(); + dap_db_history_add((char)l_obj->type, l_obj, 1, l_sync_group_item->group_name_for_history); + unlock(); + if(l_sync_group_item->callback_notify) { + if(l_obj) { + l_sync_group_item->callback_notify(l_sync_group_item->callback_arg, + (const char)l_obj->type, + l_obj->group, l_obj->key, + l_obj->value, l_obj->value_len); + } + } + } else { // looking for extra group + sync_group_item_t *l_sync_extra_group_item = find_item_by_mask(s_sync_group_extra_items, l_obj->group); + if(l_sync_extra_group_item) { + lock(); + dap_db_history_add((char)l_obj->type, l_obj, 1, l_sync_extra_group_item->group_name_for_history); + unlock(); + if(l_sync_extra_group_item->callback_notify) + l_sync_extra_group_item->callback_notify(l_sync_extra_group_item->callback_arg, + (const char)l_obj->type, l_obj->group, l_obj->key, + l_obj->value, l_obj->value_len); + } + } +} + + +/** + * @brief dap_chain_global_db_gr_set + * @param a_key + * @param a_value + * @param a_value_len + * @param a_group + * @details Set one entry to base. IMPORTANT: a_key and a_value should be passed without free after (it will be released by gdb itself) + * @return + */ +bool dap_chain_global_db_gr_set(char *a_key, void *a_value, size_t a_value_len, const char *a_group) +{ + dap_store_obj_t store_data; + memset(&store_data, 0, sizeof(dap_store_obj_t)); + store_data.key = a_key; + store_data.value = a_value; + store_data.value_len = (a_value_len == (size_t) -1) ? dap_strlen((const char*) a_value) : a_value_len; + store_data.group = (char*)a_group; + store_data.timestamp = time(NULL); + lock(); + 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) { + // delete info about the deleted entry from the base if one present + global_db_gr_del_del(store_data.key, store_data.group); + dap_global_db_obj_track_history(&store_data); + } else { + log_it(L_ERROR, "Save error: %d", l_res); + } + + return !l_res; +} + +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 + */ +bool dap_chain_global_db_gr_del(char *a_key,const char *a_group) +{ + if(!a_key) + return NULL; + dap_store_obj_t store_data; + memset(&store_data, 0, sizeof(dap_store_obj_t)); + store_data.key = a_key; + store_data.group = (char*)a_group; + lock(); + int l_res = dap_chain_global_db_driver_delete(&store_data, 1); + unlock(); + if(l_res >= 0) { + // add to Del group + global_db_gr_del_add(store_data.key, store_data.group, store_data.timestamp); + } + // do not add to history if l_res=1 (already deleted) + if (!l_res) { + dap_global_db_obj_track_history(&store_data); + } + return !l_res; +} + /** * Write to the database from an array of data_size bytes * @@ -702,67 +560,19 @@ bool dap_chain_global_db_obj_save(void* a_store_data, size_t a_objs_count) 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++) { - - 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); - 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((char)l_obj->type, l_obj, 1, l_history_group_item->group_name_for_history); - unlock(); - } - if(l_history_group_item->callback_notify) { - if(l_obj) { - l_history_group_item->callback_notify(l_history_group_item->callback_arg, - (const char)l_obj->type, - l_group_prefix, l_obj->group, l_obj->key, - l_obj->value, l_obj->value_len); - } else { - break; - } - } - } - // looking for extra group - else { - history_extra_group_item_t * l_history_extra_group_item = NULL; - HASH_FIND_STR(s_history_extra_group_items, l_obj->group, l_history_extra_group_item); - - if(l_history_extra_group_item) { - lock(); - dap_db_history_add((char)l_obj->type, l_obj, 1, l_history_extra_group_item->group_name_for_history); - unlock(); - if(l_history_extra_group_item->callback_notify) - l_history_extra_group_item->callback_notify(l_history_extra_group_item->callback_arg, - (const char)l_obj->type, - l_group_prefix, l_obj->group, l_obj->key, - l_obj->value, l_obj->value_len); - } - } - - DAP_DELETE(l_group_prefix); - } - - } - if(l_res >= 0) { - return true; + for(size_t i = 0; i < a_objs_count; i++) { + dap_store_obj_t *a_store_obj = (dap_store_obj_t *)a_store_data + i; + if (a_store_obj->type == 'a' && !l_res) + // 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' && l_res >= 0) + // add to Del group + global_db_gr_del_add(a_store_obj->key, a_store_obj->group, a_store_obj->timestamp); + if (!l_res) + // Extract prefix if added successfuly, add history log and call notify callback if present + dap_global_db_obj_track_history(a_store_obj); } - return false; + return !l_res; } bool dap_chain_global_db_gr_save(dap_global_db_obj_t* a_objs, size_t a_objs_count, const char *a_group) @@ -783,39 +593,13 @@ bool dap_chain_global_db_gr_save(dap_global_db_obj_t* a_objs, size_t a_objs_coun //log_it(L_DEBUG,"Added %u objects", a_objs_count); int l_res = dap_chain_global_db_driver_add(l_store_data, a_objs_count); unlock(); - if(!l_res) { + 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) - 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('a', l_store_data, 1, l_history_group_item->group_name_for_history); - 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; - } - } - } - DAP_DELETE(l_group_prefix); + dap_global_db_obj_track_history(l_store_data + i); } - - } - DAP_DELETE(l_store_data); //dap_store_obj_free(store_data, a_objs_count); - if(!l_res) { - return true; } + DAP_DELETE(l_store_data); + return !l_res; } return false; } @@ -834,66 +618,3 @@ char* dap_chain_global_db_hash(const uint8_t *data, size_t data_size) { return dap_chain_global_db_driver_hash(data, data_size); } - -/** - * 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 || ! a_data_size) - return NULL; - if( (l_pkt->data_size+ sizeof(dap_store_obj_pkt_t)) != ((size_t) a_data_size )) - return NULL; - - size_t l_store_obj_count = 0; - 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; - - return l_obj; -} - -/** - * Get timestamp from dap_db_log_pack() - */ -time_t dap_db_log_unpack_get_timestamp(uint8_t *a_data, size_t a_data_size) -{ - dap_store_obj_pkt_t *l_pkt = (dap_store_obj_pkt_t*) a_data; - if(!l_pkt || l_pkt->data_size != (a_data_size - sizeof(dap_store_obj_pkt_t))) - return 0; - return l_pkt->timestamp; -} - -/** - * Get log diff as string - */ -char* dap_db_log_get_diff(size_t *a_data_size_out) -{ - //DapList *l_group_list = dap_list_append(l_group_list,GROUP_HISTORY); - size_t l_data_size_out = 0; - dap_global_db_obj_t *l_objs = dap_chain_global_db_gr_load(GROUP_LOCAL_HISTORY, &l_data_size_out); - // make keys & val vector - char **l_keys_vals0 = DAP_NEW_SIZE(char*, sizeof(char*) * (l_data_size_out * 2 + 2)); - char **l_keys_vals = l_keys_vals0 + 1; - size_t i; - // first element - number of records - l_keys_vals0[0] = dap_strdup_printf("%d", l_data_size_out); - for(i = 0; i < l_data_size_out; i++) { - dap_global_db_obj_t *l_obj_cur = l_objs + i; - 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) - *a_data_size_out = l_data_size_out; - // last element - NULL (marker) - l_keys_vals[l_data_size_out * 2] = NULL; - char *l_keys_vals_flat = dap_strjoinv(GLOBAL_DB_HIST_KEY_SEPARATOR, l_keys_vals0); - DAP_DELETE(l_keys_vals0[0]); - DAP_DELETE(l_keys_vals0); - //dap_strfreev(l_keys_vals0); - dap_chain_global_db_objs_delete(l_objs, l_data_size_out); - return l_keys_vals_flat; -} diff --git a/modules/global-db/dap_chain_global_db_driver.c b/modules/global-db/dap_chain_global_db_driver.c index 542d5758af4b53788311cf2a6543c897cca5ef88..ed6511d71dedcdef65effcee2f5bb9d908adeaa1 100644 --- a/modules/global-db/dap_chain_global_db_driver.c +++ b/modules/global-db/dap_chain_global_db_driver.c @@ -198,148 +198,6 @@ 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) - + sizeof(uint64_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_list_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; - - // calculate output structure size - dap_list_t *l_ret = NULL; - dap_store_obj_pkt_t *l_pkt; - uint32_t l_obj_count = 0, l_data_size_out = 0; - 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]); - if (l_data_size_out > DAP_CHAIN_PKT_EXPECT_SIZE || (l_q == a_store_obj_count - 1 && l_data_size_out)) { - 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; - l_pkt->obj_count = l_q + 1 - l_obj_count; - l_ret = dap_list_append(l_ret, l_pkt); - l_data_size_out = 0; - l_obj_count = l_q + 1; - } - } - l_obj_count = 0; - for (dap_list_t *l_iter = l_ret; l_iter; l_iter = dap_list_next(l_iter)) { - l_pkt = (dap_store_obj_pkt_t *)l_iter->data; - uint64_t l_offset = 0; - for(size_t l_q = 0; l_q < l_pkt->obj_count; ++l_q) { - dap_store_obj_t obj = a_store_obj[l_obj_count + 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.id, sizeof(uint64_t)); - l_offset += sizeof(uint64_t); - 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; - } - l_obj_count += l_pkt->obj_count; - assert(l_pkt->data_size == l_offset); - } - return l_ret; -} -/** - * 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 = pkt->obj_count; - 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_length; - - if (offset+sizeof (int)> pkt->data_size) {log_it(L_ERROR, "Broken GDB element: can't read 'type' field"); break;} // Check for buffer boundries - 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; - - if (offset+sizeof (uint16_t)> pkt->data_size) {log_it(L_ERROR, "Broken GDB element: can't read 'group_length' field"); break;} // Check for buffer boundries - memcpy(&str_length, pkt->data + offset, sizeof(uint16_t)); - offset += sizeof(uint16_t); - - if (offset+str_length> pkt->data_size) {log_it(L_ERROR, "Broken GDB element: can't read 'group' field"); break;} // Check for buffer boundries - obj->group = DAP_NEW_Z_SIZE(char, str_length + 1); - memcpy(obj->group, pkt->data + offset, str_length); - offset += str_length; - - if (offset+sizeof (uint64_t)> pkt->data_size) {log_it(L_ERROR, "Broken GDB element: can't read 'id' field"); break;} // Check for buffer boundries - memcpy(&obj->id, pkt->data + offset, sizeof(uint64_t)); - offset += sizeof(uint64_t); - - if (offset+sizeof (time_t)> pkt->data_size) {log_it(L_ERROR, "Broken GDB element: can't read 'timestamp' field"); break;} // Check for buffer boundries - memcpy(&obj->timestamp, pkt->data + offset, sizeof(time_t)); - offset += sizeof(time_t); - - if (offset+sizeof (uint16_t)> pkt->data_size) {log_it(L_ERROR, "Broken GDB element: can't read 'key_length' field"); break;} // Check for buffer boundries - memcpy(&str_length, pkt->data + offset, sizeof(uint16_t)); - offset += sizeof(uint16_t); - - if (offset+ str_length > pkt->data_size) {log_it(L_ERROR, "Broken GDB element: can't read 'key' field"); break;} // Check for buffer boundries - obj->key = DAP_NEW_Z_SIZE(char, str_length + 1); - memcpy(obj->key, pkt->data + offset, str_length); - offset += str_length; - - if (offset+sizeof (size_t)> pkt->data_size) {log_it(L_ERROR, "Broken GDB element: can't read 'value_length' field"); break;} // Check for buffer boundries - memcpy(&obj->value_len, pkt->data + offset, sizeof(size_t)); - offset += sizeof(size_t); - - if (offset+obj->value_len> pkt->data_size) {log_it(L_ERROR, "Broken GDB element: can't read 'value' field"); break;} // Check for buffer boundries - 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 * diff --git a/modules/global-db/dap_chain_global_db_driver_cdb.c b/modules/global-db/dap_chain_global_db_driver_cdb.c index d22d8759a303932481e88db1010ff67f36f8b02c..1aeba149aaf31a97e43ef8511a2c7ccf1a0c0b20 100644 --- a/modules/global-db/dap_chain_global_db_driver_cdb.c +++ b/modules/global-db/dap_chain_global_db_driver_cdb.c @@ -121,6 +121,23 @@ bool dap_cdb_get_cond_obj_iter_callback(void *arg, const char *key, int ksize, c return true; } +bool dap_cdb_get_count_iter_callback(void *arg, const char *key, int ksize, const char *val, int vsize, uint32_t expire, uint64_t oid) { + UNUSED(ksize); + UNUSED(val); + UNUSED(vsize); + UNUSED(expire); + UNUSED(oid); + UNUSED(key); + + if (dap_hex_to_uint(val, sizeof(uint64_t)) < ((pobj_arg)arg)->id) { + return true; + } + if (--((pobj_arg)arg)->q == 0) { + return false; + } + return true; +} + pcdb_instance dap_cdb_init_group(char *a_group, int a_flags) { pcdb_instance l_cdb_i = NULL; pthread_mutex_lock(&cdb_mutex); @@ -421,19 +438,23 @@ dap_store_obj_t* dap_db_driver_cdb_read_cond_store_obj(const char *a_group, uint size_t dap_db_driver_cdb_read_count_store(const char *a_group, uint64_t a_id) { - if(!a_group) { + if (!a_group) { return 0; } pcdb_instance l_cdb_i = dap_cdb_get_db_by_group(a_group); - if(!l_cdb_i) { + if (!l_cdb_i) { return 0; } CDB *l_cdb = l_cdb_i->cdb; CDBSTAT l_cdb_stat; cdb_stat(l_cdb, &l_cdb_stat); - if(a_id > l_cdb_stat.rnum) - return 0; - return (size_t) l_cdb_stat.rnum - a_id + 1; + obj_arg l_arg; + l_arg.q = l_cdb_stat.rnum; + l_arg.id = a_id; + void *l_iter = cdb_iterate_new(l_cdb, 0); + cdb_iterate(l_cdb, dap_cdb_get_count_iter_callback, (void*)&l_arg, l_iter); + cdb_iterate_destroy(l_cdb, l_iter); + return l_cdb_stat.rnum - l_arg.q; } /** @@ -446,11 +467,10 @@ dap_list_t* dap_db_driver_cdb_get_groups_by_mask(const char *a_group_mask) return NULL; cdb_instance *cur_cdb, *tmp; pthread_rwlock_rdlock(&cdb_rwlock); - HASH_ITER(hh, s_cdb, cur_cdb, tmp) - { - if(!dap_fnmatch(a_group_mask, cur_cdb->local_group, 0)) - if(dap_fnmatch("*.del", cur_cdb->local_group, 0)) - l_ret_list = dap_list_prepend(l_ret_list, dap_strdup(cur_cdb->local_group)); + HASH_ITER(hh, s_cdb, cur_cdb, tmp) { + char *l_table_name = cur_cdb->local_group; + if(!dap_fnmatch(a_group_mask, l_table_name, 0)) + l_ret_list = dap_list_prepend(l_ret_list, dap_strdup(l_table_name)); } pthread_rwlock_unlock(&cdb_rwlock); return l_ret_list; diff --git a/modules/global-db/dap_chain_global_db_driver_sqlite.c b/modules/global-db/dap_chain_global_db_driver_sqlite.c index 7f8a9ba6a720a5e675681e9b30aefdc34d24f2b7..9b90abff137a177a9727ab6da13d1a65a2bdc5c9 100644 --- a/modules/global-db/dap_chain_global_db_driver_sqlite.c +++ b/modules/global-db/dap_chain_global_db_driver_sqlite.c @@ -36,6 +36,7 @@ #include "dap_hash.h" #include "dap_file_utils.h" #include "dap_strfuncs.h" +#include "dap_file_utils.h" #include "dap_chain_global_db_driver_sqlite.h" #define LOG_TAG "db_sqlite" @@ -90,6 +91,7 @@ int dap_db_driver_sqlite_init(const char *a_filename_db, dap_db_driver_callbacks log_it(L_ERROR, "Can't init sqlite err=%d (%s)", l_ret, sqlite3_errstr(l_ret)); return -2; } + // Check paths and create them if nessesary char * l_filename_dir = dap_path_get_dirname(a_filename_db); if(!dap_dir_test(l_filename_dir)){ log_it(L_NOTICE, "No directory %s, trying to create...",l_filename_dir); @@ -106,7 +108,7 @@ int dap_db_driver_sqlite_init(const char *a_filename_db, dap_db_driver_callbacks log_it(L_NOTICE,"Directory created"); } DAP_DEL_Z(l_filename_dir); - + // Open Sqlite file, create if nessesary char *l_error_message = NULL; s_db = dap_db_driver_sqlite_open(a_filename_db, SQLITE_OPEN_READWRITE|SQLITE_OPEN_CREATE, &l_error_message); if(!s_db) { @@ -131,6 +133,9 @@ int dap_db_driver_sqlite_init(const char *a_filename_db, dap_db_driver_callbacks a_drv_callback->read_last_store_obj = dap_db_driver_sqlite_read_last_store_obj; a_drv_callback->transaction_start = dap_db_driver_sqlite_start_transaction; a_drv_callback->transaction_end = dap_db_driver_sqlite_end_transaction; + a_drv_callback->get_groups_by_mask = dap_db_driver_sqlite_get_groups_by_mask; + a_drv_callback->read_count_store = dap_db_driver_sqlite_read_count_store; + a_drv_callback->is_obj = dap_db_driver_sqlite_is_obj; a_drv_callback->deinit = dap_db_driver_sqlite_deinit; a_drv_callback->flush = dap_db_driver_sqlite_flush; s_filename_db = strdup(a_filename_db); @@ -415,7 +420,6 @@ static int dap_db_driver_sqlite_fetch_array(sqlite3_stmt *l_res, SQLITE_ROW_VALU if(cur_val->type == SQLITE_INTEGER) { cur_val->val.val_int64 = sqlite3_column_int64(l_res, l_iCol); - cur_val->val.val_int = sqlite3_column_int(l_res, l_iCol); } else if(cur_val->type == SQLITE_FLOAT) cur_val->val.val_float = sqlite3_column_double(l_res, l_iCol); @@ -518,6 +522,22 @@ int dap_db_driver_sqlite_end_transaction(void) } } +char *dap_db_driver_sqlite_make_group_name(const char *a_table_name) +{ + char *l_table_name = dap_strdup(a_table_name); + ssize_t l_table_name_len = (ssize_t)dap_strlen(l_table_name); + const char *l_needle = "_"; + // replace '_' to '.' + while(1){ + char *l_str = dap_strstr_len(l_table_name, l_table_name_len, l_needle); + if(l_str) + *l_str = '.'; + else + break; + } + return l_table_name; +} + char *dap_db_driver_sqlite_make_table_name(const char *a_group_name) { char *l_group_name = dap_strdup(a_group_name); @@ -726,10 +746,10 @@ dap_store_obj_t* dap_db_driver_sqlite_read_cond_store_obj(const char *a_group, u l_count_out = (int)*a_count_out; char *l_str_query; if(l_count_out) - l_str_query = sqlite3_mprintf("SELECT id,ts,key,value FROM '%s' WHERE id>'%lld' ORDER BY id ASC LIMIT %d", + l_str_query = sqlite3_mprintf("SELECT id,ts,key,value FROM '%s' WHERE id>='%lld' ORDER BY id ASC LIMIT %d", l_table_name, a_id, l_count_out); else - l_str_query = sqlite3_mprintf("SELECT id,ts,key,value FROM '%s' WHERE id>'%lld' ORDER BY id ASC", + l_str_query = sqlite3_mprintf("SELECT id,ts,key,value FROM '%s' WHERE id>='%lld' ORDER BY id ASC", l_table_name, a_id); pthread_rwlock_wrlock(&s_db_rwlock); if(!s_db){ @@ -790,12 +810,10 @@ dap_store_obj_t* dap_db_driver_sqlite_read_cond_store_obj(const char *a_group, u */ dap_store_obj_t* dap_db_driver_sqlite_read_store_obj(const char *a_group, const char *a_key, size_t *a_count_out) { + if(!a_group || !s_db) + return NULL; dap_store_obj_t *l_obj = NULL; - char *l_error_message = NULL; sqlite3_stmt *l_res; - if(!a_group) - return NULL; - char * l_table_name = dap_db_driver_sqlite_make_table_name(a_group); // no limit uint64_t l_count_out = 0; @@ -818,18 +836,13 @@ dap_store_obj_t* dap_db_driver_sqlite_read_store_obj(const char *a_group, const l_str_query = sqlite3_mprintf("SELECT id,ts,key,value FROM '%s' ORDER BY id ASC", l_table_name); } pthread_rwlock_wrlock(&s_db_rwlock); - if(!s_db){ - pthread_rwlock_unlock(&s_db_rwlock); - return NULL; - } - - int l_ret = dap_db_driver_sqlite_query(s_db, l_str_query, &l_res, &l_error_message); + int l_ret = dap_db_driver_sqlite_query(s_db, l_str_query, &l_res, NULL); pthread_rwlock_unlock(&s_db_rwlock); + sqlite3_free(l_str_query); DAP_DEL_Z(l_table_name); if(l_ret != SQLITE_OK) { //log_it(L_ERROR, "read l_ret=%d, %s\n", sqlite3_errcode(s_db), sqlite3_errmsg(s_db)); - dap_db_driver_sqlite_free(l_error_message); return NULL; } @@ -864,3 +877,85 @@ dap_store_obj_t* dap_db_driver_sqlite_read_store_obj(const char *a_group, const *a_count_out = l_count_out; return l_obj; } + +dap_list_t* dap_db_driver_sqlite_get_groups_by_mask(const char *a_group_mask) +{ + if(!a_group_mask || !s_db) + return NULL; + sqlite3_stmt *l_res; + const char *l_str_query = "SELECT name FROM sqlite_master WHERE type ='table' AND name NOT LIKE 'sqlite_%'"; + dap_list_t *l_ret_list = NULL; + pthread_rwlock_wrlock(&s_db_rwlock); + int l_ret = dap_db_driver_sqlite_query(s_db, (char *)l_str_query, &l_res, NULL); + pthread_rwlock_unlock(&s_db_rwlock); + if(l_ret != SQLITE_OK) { + //log_it(L_ERROR, "Get tables l_ret=%d, %s\n", sqlite3_errcode(s_db), sqlite3_errmsg(s_db)); + return NULL; + } + char * l_mask = dap_db_driver_sqlite_make_table_name(a_group_mask); + SQLITE_ROW_VALUE *l_row = NULL; + while (dap_db_driver_sqlite_fetch_array(l_res, &l_row) == SQLITE_ROW && l_row) { + char *l_table_name = (char *)l_row->val->val.val_str; + if(!dap_fnmatch(l_mask, l_table_name, 0)) + l_ret_list = dap_list_prepend(l_ret_list, dap_db_driver_sqlite_make_group_name(l_table_name)); + dap_db_driver_sqlite_row_free(l_row); + } + dap_db_driver_sqlite_query_free(l_res); + return l_ret_list; +} + +size_t dap_db_driver_sqlite_read_count_store(const char *a_group, uint64_t a_id) +{ + sqlite3_stmt *l_res; + if(!a_group || ! s_db) + return 0; + + char * l_table_name = dap_db_driver_sqlite_make_table_name(a_group); + char *l_str_query = sqlite3_mprintf("SELECT COUNT(*) FROM '%s' WHERE id>='%lld'", l_table_name, a_id); + pthread_rwlock_wrlock(&s_db_rwlock); + int l_ret = dap_db_driver_sqlite_query(s_db, l_str_query, &l_res, NULL); + pthread_rwlock_unlock(&s_db_rwlock); + sqlite3_free(l_str_query); + DAP_DEL_Z(l_table_name); + + if(l_ret != SQLITE_OK) { + //log_it(L_ERROR, "Count l_ret=%d, %s\n", sqlite3_errcode(s_db), sqlite3_errmsg(s_db)); + return 0; + } + size_t l_ret_val; + SQLITE_ROW_VALUE *l_row = NULL; + if (dap_db_driver_sqlite_fetch_array(l_res, &l_row) == SQLITE_ROW && l_row) { + l_ret_val = (size_t)l_row->val->val.val_int64; + dap_db_driver_sqlite_row_free(l_row); + } + dap_db_driver_sqlite_query_free(l_res); + return l_ret_val; +} + +bool dap_db_driver_sqlite_is_obj(const char *a_group, const char *a_key) +{ + sqlite3_stmt *l_res; + if(!a_group || ! s_db) + return false; + + char * l_table_name = dap_db_driver_sqlite_make_table_name(a_group); + char *l_str_query = sqlite3_mprintf("SELECT EXISTS(SELECT * FROM '%s' WHERE key='%s')", l_table_name, a_key); + pthread_rwlock_wrlock(&s_db_rwlock); + int l_ret = dap_db_driver_sqlite_query(s_db, l_str_query, &l_res, NULL); + pthread_rwlock_unlock(&s_db_rwlock); + sqlite3_free(l_str_query); + DAP_DEL_Z(l_table_name); + + if(l_ret != SQLITE_OK) { + //log_it(L_ERROR, "Exists l_ret=%d, %s\n", sqlite3_errcode(s_db), sqlite3_errmsg(s_db)); + return false; + } + bool l_ret_val; + SQLITE_ROW_VALUE *l_row = NULL; + if (dap_db_driver_sqlite_fetch_array(l_res, &l_row) == SQLITE_ROW && l_row) { + l_ret_val = (size_t)l_row->val->val.val_int64; + dap_db_driver_sqlite_row_free(l_row); + } + dap_db_driver_sqlite_query_free(l_res); + return l_ret_val; +} diff --git a/modules/global-db/dap_chain_global_db_hist.c b/modules/global-db/dap_chain_global_db_hist.c index 05950ebc8ca0c32765d3777cfd685931a263351f..2fea00e1c06b8e2360a4746a9c70179f5051fe2a 100644 --- a/modules/global-db/dap_chain_global_db_hist.c +++ b/modules/global-db/dap_chain_global_db_hist.c @@ -8,7 +8,7 @@ #include <dap_string.h> #include <dap_hash.h> #include "dap_chain_datum_tx_items.h" - +#include "dap_chain_global_db_remote.h" #include "dap_chain_global_db_hist.h" #include "uthash.h" @@ -72,1006 +72,6 @@ static char* dap_db_new_history_timestamp() return l_str; } -/** - * Get data according the history log - * - * return dap_store_obj_pkt_t* - */ -dap_list_t* dap_db_log_pack(dap_global_db_obj_t *a_obj, size_t *a_data_size_out) -{ - if(!a_obj) - return NULL; - dap_global_db_hist_t l_rec; - if(dap_db_history_unpack_hist((char*) a_obj->value, &l_rec) == -1) - return NULL; - time_t l_timestamp = strtoll(a_obj->key, NULL, 10); - - // parse global_db records in a history record - char **l_keys = dap_strsplit(l_rec.keys, GLOBAL_DB_HIST_KEY_SEPARATOR, -1); - size_t l_count = dap_str_countv(l_keys); - // read records from global_db - int i = 0; - dap_store_obj_t *l_store_obj = DAP_NEW_Z_SIZE(dap_store_obj_t, l_count * sizeof(dap_store_obj_t)); - while(l_keys[i]) { - dap_store_obj_t *l_obj = NULL; - // add record - read record - if(l_rec.type == 'a'){ - l_obj = (dap_store_obj_t*) dap_chain_global_db_obj_get(l_keys[i], l_rec.group); - // l_obj may be NULL, if this record has been deleted but it is present in history - if(l_obj) - l_obj->id = a_obj->id; - } - // delete record - save only key for record - else if(l_rec.type == 'd') { // //section=strdup("kelvin_nodes"); - l_obj = (dap_store_obj_t*) DAP_NEW_Z(dap_store_obj_t); - 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); - dap_strfreev(l_keys); - return NULL; - } - // save record type: 'a' or 'd' - l_obj->type = (uint8_t)l_rec.type; - - memcpy(l_store_obj + i, l_obj, sizeof(dap_store_obj_t)); - DAP_DELETE(l_obj); - i++; - } - // serialize data - dap_list_t *l_data_out = dap_store_packet_multiple(l_store_obj, l_timestamp, l_count); - - dap_store_obj_free(l_store_obj, l_count); - dap_strfreev(l_keys); - - if(l_data_out && a_data_size_out) { - *a_data_size_out = 0; - for (dap_list_t *l_iter = l_data_out; l_iter; l_iter = dap_list_next(l_iter)) { - *a_data_size_out += sizeof(dap_store_obj_pkt_t) + ((dap_store_obj_pkt_t *)l_data_out)->data_size; - } - } - return l_data_out; - -} - - -// for dap_db_history() -static dap_store_obj_t* get_prev_tx(dap_global_db_obj_t *a_objs, dap_tx_data_t *a_tx_data) -{ - if(!a_objs || !a_tx_data) - return NULL; - dap_global_db_obj_t *l_obj_cur = a_objs + a_tx_data->obj_num; - dap_global_db_hist_t l_rec; - if(dap_db_history_unpack_hist((char*) l_obj_cur->value, &l_rec) == -1) - return NULL; - char **l_keys = dap_strsplit(l_rec.keys, GLOBAL_DB_HIST_KEY_SEPARATOR, -1); - size_t l_count = dap_str_countv(l_keys); - if(a_tx_data->pos_num >= l_count) { - dap_strfreev(l_keys); - return NULL; - } - dap_store_obj_t *l_obj = - (dap_store_obj_t*) l_keys ? dap_chain_global_db_obj_get(l_keys[a_tx_data->pos_num], l_rec.group) : NULL; - dap_strfreev(l_keys); - return l_obj; -} - -/** - * Get data according the history log - * - * return history string - */ -#if 0 -char* dap_db_history_tx(dap_chain_hash_fast_t* a_tx_hash, const char *a_group_mempool) -{ - dap_string_t *l_str_out = dap_string_new(NULL); - // load history - size_t l_data_size_out = 0; - dap_global_db_obj_t *l_objs = dap_chain_global_db_gr_load(GROUP_LOCAL_HISTORY, &l_data_size_out); - size_t i, j; - bool l_tx_hash_found = false; - dap_tx_data_t *l_tx_data_hash = NULL; - for(i = 0; i < l_data_size_out; i++) { - dap_global_db_obj_t *l_obj_cur = l_objs + i; - - // parse global_db records in a history record - dap_global_db_hist_t l_rec; - if(dap_db_history_unpack_hist((char*) l_obj_cur->value, &l_rec) == -1) - continue; - // use only groups with datums - if(dap_strcmp(a_group_mempool, l_rec.group)) - continue; - - char **l_keys = dap_strsplit(l_rec.keys, GLOBAL_DB_HIST_KEY_SEPARATOR, -1); - size_t l_count = dap_str_countv(l_keys); - dap_store_obj_t *l_obj = NULL; - // all objs in one history records - for(j = 0; j < l_count; j++) { - - if(l_rec.type != 'a') - continue; - l_obj = (dap_store_obj_t*) dap_chain_global_db_obj_get(l_keys[j], l_rec.group); - if(!l_obj) - continue; - // datum - dap_chain_datum_t *l_datum = (dap_chain_datum_t*) l_obj->value; - if(!l_datum && l_datum->header.type_id != DAP_CHAIN_DATUM_TX) - continue; - - dap_tx_data_t *l_tx_data = NULL; - - // transaction - dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t*) l_datum->data; - - // find Token items - present in emit transaction - dap_list_t *l_list_tx_token = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_TOKEN, NULL); - - // find OUT items - dap_list_t *l_list_out_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_OUT, NULL); - dap_list_t *l_list_tmp = l_list_out_items; - while(l_list_tmp) { - const dap_chain_tx_out_t *l_tx_out = (const dap_chain_tx_out_t*) l_list_tmp->data; - // save OUT item l_tx_out - if(!l_tx_data) - { - // save tx hash - l_tx_data = DAP_NEW_Z(dap_tx_data_t); - dap_chain_hash_fast_t l_tx_hash; - dap_hash_fast(l_tx, dap_chain_datum_tx_get_size(l_tx), &l_tx_hash); - memcpy(&l_tx_data->tx_hash, &l_tx_hash, sizeof(dap_chain_hash_fast_t)); - memcpy(&l_tx_data->addr, &l_tx_out->addr, sizeof(dap_chain_addr_t)); - dap_chain_hash_fast_to_str(&l_tx_data->tx_hash, l_tx_data->tx_hash_str, - sizeof(l_tx_data->tx_hash_str)); - l_tx_data->obj_num = i; - l_tx_data->pos_num = j; - // save token name - if(l_list_tx_token) { - dap_chain_tx_token_t *tk = l_list_tx_token->data; - int d = sizeof(l_tx_data->token_ticker); - memcpy(l_tx_data->token_ticker, tk->header.ticker, sizeof(l_tx_data->token_ticker)); - } - // take token from prev out item - else { - - // find IN items - dap_list_t *l_list_in_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_IN, NULL); - dap_list_t *l_list_tmp_in = l_list_in_items; - // find token_ticker in prev OUT items - while(l_list_tmp_in) { - const dap_chain_tx_in_t *l_tx_in = - (const dap_chain_tx_in_t*) l_list_tmp_in->data; - dap_chain_hash_fast_t tx_prev_hash = l_tx_in->header.tx_prev_hash; - - //find prev OUT item - dap_tx_data_t *l_tx_data_prev = NULL; - HASH_FIND(hh, l_tx_data_hash, &tx_prev_hash, sizeof(dap_chain_hash_fast_t), - l_tx_data_prev); - if(l_tx_data_prev != NULL) { - // fill token in l_tx_data from prev transaction - if(l_tx_data) { - // get token from prev tx - memcpy(l_tx_data->token_ticker, l_tx_data_prev->token_ticker, - sizeof(l_tx_data->token_ticker)); - break; - } - l_list_tmp_in = dap_list_next(l_list_tmp_in); - } - } - if(l_list_in_items) - dap_list_free(l_list_in_items); - } - HASH_ADD(hh, l_tx_data_hash, tx_hash, sizeof(dap_chain_hash_fast_t), l_tx_data); - } - l_list_tmp = dap_list_next(l_list_tmp); - } - if(l_list_out_items) - dap_list_free(l_list_out_items); - - // calc hash - dap_chain_hash_fast_t l_tx_hash; - dap_hash_fast(l_tx, dap_chain_datum_tx_get_size(l_tx), &l_tx_hash); - // search tx with a_tx_hash - if(!dap_hash_fast_compare(a_tx_hash, &l_tx_hash)) - continue; - // found a_tx_hash now - - // transaction time - char *l_time_str = NULL; - if(l_tx->header.ts_created > 0) { - time_t rawtime = (time_t) l_tx->header.ts_created; - struct tm * timeinfo; - timeinfo = localtime(&rawtime); - if(timeinfo) { - dap_string_append_printf(l_str_out, " %s", asctime(timeinfo)); - } - } - - // find all OUT items in transaction - l_list_out_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_OUT, NULL); - l_list_tmp = l_list_out_items; - while(l_list_tmp) { - const dap_chain_tx_out_t *l_tx_out = (const dap_chain_tx_out_t*) l_list_tmp->data; - dap_tx_data_t *l_tx_data_prev = NULL; - - const char *l_token_str = NULL; - if(l_tx_data) - l_token_str = l_tx_data->token_ticker; - char *l_dst_to_str = - (l_tx_out) ? dap_chain_addr_to_str(&l_tx_out->addr) : - NULL; - dap_string_append_printf(l_str_out, " OUT item %lld %s to %s\n", - l_tx_out->header.value, - dap_strlen(l_token_str) > 0 ? l_token_str : "?", - l_dst_to_str ? l_dst_to_str : "?" - ); - DAP_DELETE(l_dst_to_str); - l_list_tmp = dap_list_next(l_list_tmp); - } - // find all IN items in transaction - dap_list_t *l_list_in_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_IN, NULL); - l_list_tmp = l_list_in_items; - // find cur addr in prev OUT items - while(l_list_tmp) { - const dap_chain_tx_in_t *l_tx_in = (const dap_chain_tx_in_t*) l_list_tmp->data; - dap_chain_hash_fast_t tx_prev_hash = l_tx_in->header.tx_prev_hash; - char l_tx_hash_str[70]; - if(!dap_hash_fast_is_blank(&tx_prev_hash)) - dap_chain_hash_fast_to_str(&tx_prev_hash, l_tx_hash_str, sizeof(l_tx_hash_str)); - else - strcpy(l_tx_hash_str,"Null"); - dap_string_append_printf(l_str_out, " IN item \n prev tx_hash %s\n", l_tx_hash_str); - - //find prev OUT item - dap_tx_data_t *l_tx_data_prev = NULL; - HASH_FIND(hh, l_tx_data_hash, &tx_prev_hash, sizeof(dap_chain_hash_fast_t), l_tx_data_prev); - if(l_tx_data_prev != NULL) { - - dap_store_obj_t *l_obj_prev = get_prev_tx(l_objs, l_tx_data_prev); - dap_chain_datum_t *l_datum_prev = - l_obj_prev ? (dap_chain_datum_t*) l_obj_prev->value : NULL; - dap_chain_datum_tx_t *l_tx_prev = - l_datum_prev ? (dap_chain_datum_tx_t*) l_datum_prev->data : NULL; - - // find OUT items in prev datum - dap_list_t *l_list_out_prev_items = dap_chain_datum_tx_items_get(l_tx_prev, - TX_ITEM_TYPE_OUT, NULL); - // find OUT item for IN item; - dap_list_t *l_list_out_prev_item = dap_list_nth(l_list_out_prev_items, - l_tx_in->header.tx_out_prev_idx); - dap_chain_tx_out_t *l_tx_prev_out = - l_list_out_prev_item ? - (dap_chain_tx_out_t*) l_list_out_prev_item->data : - NULL; - // print value from prev out item - dap_string_append_printf(l_str_out, " prev OUT item value=%lld", - l_tx_prev_out->header.value - ); - } - dap_string_append_printf(l_str_out, "\n"); - l_list_tmp = dap_list_next(l_list_tmp); - } - - if(l_list_tx_token) - dap_list_free(l_list_tx_token); - if(l_list_out_items) - dap_list_free(l_list_out_items); - if(l_list_in_items) - dap_list_free(l_list_in_items); - l_tx_hash_found = true; - break; - } - dap_list_t *l_records_out = NULL; - - DAP_DELETE(l_obj); - dap_strfreev(l_keys); - // transaction was found -> exit - if(l_tx_hash_found) - break; - } - dap_chain_global_db_objs_delete(l_objs, l_data_size_out); - // if no history - if(!l_str_out->len) - dap_string_append(l_str_out, "empty"); - char *l_ret_str = l_str_out ? dap_string_free(l_str_out, false) : NULL; - return l_ret_str; -} -#endif - -/** - * Get data according the history log - * - * return history string - */ -#if 0 -char* dap_db_history_addr(dap_chain_addr_t * a_addr, const char *a_group_mempool) -{ - dap_string_t *l_str_out = dap_string_new(NULL); - // load history - size_t l_data_size_out = 0; - dap_global_db_obj_t *l_objs = dap_chain_global_db_gr_load(GROUP_LOCAL_HISTORY, &l_data_size_out); - size_t i, j; - dap_tx_data_t *l_tx_data_hash = NULL; - for(i = 0; i < l_data_size_out; i++) { - dap_global_db_obj_t *l_obj_cur = l_objs + i; - // parse global_db records in a history record - dap_global_db_hist_t l_rec; - if(dap_db_history_unpack_hist((char*) l_obj_cur->value, &l_rec) == -1) - continue; - // use only groups with datums - if(dap_strcmp(a_group_mempool, l_rec.group)) - continue; - - char **l_keys = dap_strsplit(l_rec.keys, GLOBAL_DB_HIST_KEY_SEPARATOR, -1); - size_t l_count = dap_str_countv(l_keys); - dap_store_obj_t *l_obj = NULL; - // all objs in one history records - for(j = 0; j < l_count; j++) { - if(l_rec.type != 'a') - continue; - l_obj = (dap_store_obj_t*) dap_chain_global_db_obj_get(l_keys[j], l_rec.group); - if(!l_obj) - continue; - // datum - dap_chain_datum_t *l_datum = (dap_chain_datum_t*) l_obj->value; - if(!l_datum && l_datum->header.type_id != DAP_CHAIN_DATUM_TX) - continue; - - // transaction - dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t*) l_datum->data; - dap_list_t *l_records_out = NULL; - // transaction time - char *l_time_str = NULL; - { - if(l_tx->header.ts_created > 0) { - time_t rawtime = (time_t) l_tx->header.ts_created; - struct tm * timeinfo; - timeinfo = localtime(&rawtime); - if(timeinfo) - l_time_str = dap_strdup(asctime(timeinfo)); - } - else - l_time_str = dap_strdup(" "); - } - - // transaction - dap_tx_data_t *l_tx_data = NULL; - - // find Token items - present in emit transaction - dap_list_t *l_list_tx_token = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_TOKEN, NULL); - - // find OUT items - dap_list_t *l_list_out_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_OUT, NULL); - dap_list_t *l_list_tmp = l_list_out_items; - while(l_list_tmp) { - const dap_chain_tx_out_t *l_tx_out = (const dap_chain_tx_out_t*) l_list_tmp->data; - // save OUT item l_tx_out - { - // save tx hash - l_tx_data = DAP_NEW_Z(dap_tx_data_t); - dap_chain_hash_fast_t l_tx_hash; - dap_hash_fast(l_tx, dap_chain_datum_tx_get_size(l_tx), &l_tx_hash); - memcpy(&l_tx_data->tx_hash, &l_tx_hash, sizeof(dap_chain_hash_fast_t)); - memcpy(&l_tx_data->addr, &l_tx_out->addr, sizeof(dap_chain_addr_t)); - dap_chain_hash_fast_to_str(&l_tx_data->tx_hash, l_tx_data->tx_hash_str, - sizeof(l_tx_data->tx_hash_str)); - l_tx_data->obj_num = i; - l_tx_data->pos_num = j; - // save token name - if(l_tx_data && l_list_tx_token) { - dap_chain_tx_token_t *tk = l_list_tx_token->data; - int d = sizeof(l_tx_data->token_ticker); - memcpy(l_tx_data->token_ticker, tk->header.ticker, sizeof(l_tx_data->token_ticker)); - } - HASH_ADD(hh, l_tx_data_hash, tx_hash, sizeof(dap_chain_hash_fast_t), l_tx_data); - - // save OUT items to list - { - l_records_out = dap_list_append(l_records_out, (void*) l_tx_out); - } - } - l_list_tmp = dap_list_next(l_list_tmp); - } - - // find IN items - l_count = 0; - dap_list_t *l_list_in_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_IN, NULL); - l_list_tmp = l_list_in_items; - // find cur addr in prev OUT items - bool l_is_use_all_cur_out = false; - { - while(l_list_tmp) { - const dap_chain_tx_in_t *l_tx_in = (const dap_chain_tx_in_t*) l_list_tmp->data; - dap_chain_hash_fast_t tx_prev_hash = l_tx_in->header.tx_prev_hash; - - //find prev OUT item - dap_tx_data_t *l_tx_data_prev = NULL; - HASH_FIND(hh, l_tx_data_hash, &tx_prev_hash, sizeof(dap_chain_hash_fast_t), l_tx_data_prev); - if(l_tx_data_prev != NULL) { - // fill token in l_tx_data from prev transaction - if(l_tx_data) { - // get token from prev tx - memcpy(l_tx_data->token_ticker, l_tx_data_prev->token_ticker, - sizeof(l_tx_data->token_ticker)); - dap_store_obj_t *l_obj_prev = get_prev_tx(l_objs, l_tx_data_prev); - dap_chain_datum_t *l_datum_prev = - l_obj_prev ? (dap_chain_datum_t*) l_obj_prev->value : NULL; - dap_chain_datum_tx_t *l_tx_prev = - l_datum_prev ? (dap_chain_datum_tx_t*) l_datum_prev->data : NULL; - - // find OUT items in prev datum - dap_list_t *l_list_out_prev_items = dap_chain_datum_tx_items_get(l_tx_prev, - TX_ITEM_TYPE_OUT, NULL); - // find OUT item for IN item; - dap_list_t *l_list_out_prev_item = dap_list_nth(l_list_out_prev_items, - l_tx_in->header.tx_out_prev_idx); - dap_chain_tx_out_t *l_tx_prev_out = - l_list_out_prev_item ? - (dap_chain_tx_out_t*) l_list_out_prev_item->data : - NULL; - if(l_tx_prev_out && !memcmp(&l_tx_prev_out->addr, a_addr, sizeof(dap_chain_addr_t))) - l_is_use_all_cur_out = true; - - } - } - - // find prev OUT items for IN items - l_list_tmp = l_list_in_items; - while(l_list_tmp) { - const dap_chain_tx_in_t *l_tx_in = (const dap_chain_tx_in_t*) l_list_tmp->data; - dap_chain_hash_fast_t tx_prev_hash = l_tx_in->header.tx_prev_hash; - // if first transaction - empty prev OUT item - if(dap_hash_fast_is_blank(&tx_prev_hash)) { - // add emit info to ret string - if(!memcmp(&l_tx_data->addr, a_addr, sizeof(dap_chain_addr_t))) - { - dap_list_t *l_records_tmp = l_records_out; - while(l_records_tmp) { - - const dap_chain_tx_out_t *l_tx_out = (const dap_chain_tx_out_t*) l_records_tmp->data; - dap_string_append_printf(l_str_out, "tx hash %s \n emit %lld %s\n", - l_tx_data->tx_hash_str, - l_tx_out->header.value, - l_tx_data->token_ticker); - l_records_tmp = dap_list_next(l_records_tmp); - } - } - dap_list_free(l_records_out); - } - // in other transactions except first one - else { - //find prev OUT item - dap_tx_data_t *l_tx_data_prev = NULL; - HASH_FIND(hh, l_tx_data_hash, &tx_prev_hash, sizeof(dap_chain_hash_fast_t), l_tx_data_prev); - if(l_tx_data_prev != NULL) { - char *l_src_str = NULL; - bool l_src_str_is_cur = false; - if(l_tx_data) { - // get token from prev tx - memcpy(l_tx_data->token_ticker, l_tx_data_prev->token_ticker, - sizeof(l_tx_data->token_ticker)); - - dap_store_obj_t *l_obj_prev = get_prev_tx(l_objs, l_tx_data_prev); - dap_chain_datum_t *l_datum_prev = - l_obj_prev ? (dap_chain_datum_t*) l_obj_prev->value : NULL; - dap_chain_datum_tx_t *l_tx_prev = - l_datum_prev ? (dap_chain_datum_tx_t*) l_datum_prev->data : NULL; - - // find OUT items in prev datum - dap_list_t *l_list_out_prev_items = dap_chain_datum_tx_items_get(l_tx_prev, - TX_ITEM_TYPE_OUT, NULL); - // find OUT item for IN item; - dap_list_t *l_list_out_prev_item = dap_list_nth(l_list_out_prev_items, - l_tx_in->header.tx_out_prev_idx); - dap_chain_tx_out_t *l_tx_prev_out = - l_list_out_prev_item ? - (dap_chain_tx_out_t*) l_list_out_prev_item->data : - NULL; - // if use src addr - bool l_is_use_src_addr = false; - // find source addrs - dap_string_t *l_src_addr = dap_string_new(NULL); - { - // find IN items in prev datum - for get destination addr - dap_list_t *l_list_in_prev_items = dap_chain_datum_tx_items_get(l_tx_prev, - TX_ITEM_TYPE_IN, NULL); - dap_list_t *l_list_tmp = l_list_in_prev_items; - while(l_list_tmp) { - dap_chain_tx_in_t *l_tx_prev_in = l_list_tmp->data; - dap_chain_hash_fast_t l_tx_prev_prev_hash = - l_tx_prev_in->header.tx_prev_hash; - //find prev OUT item - dap_tx_data_t *l_tx_data_prev_prev = NULL; - HASH_FIND(hh, l_tx_data_hash, &l_tx_prev_prev_hash, - sizeof(dap_chain_hash_fast_t), l_tx_data_prev_prev); - if(l_tx_data_prev_prev) { - // if use src addr - if(!memcmp(&l_tx_data_prev_prev->addr, a_addr, - sizeof(dap_chain_addr_t))) - l_is_use_src_addr = true; - char *l_str = dap_chain_addr_to_str(&l_tx_data_prev_prev->addr); - if(l_src_addr->len > 0) - dap_string_append_printf(l_src_addr, "\n %s", l_str); - else - dap_string_append_printf(l_src_addr, "%s", l_str); // first record - DAP_DELETE(l_str); - } - l_list_tmp = dap_list_next(l_list_tmp); - } - } - - char *l_dst_to_str = - (l_tx_prev_out) ? dap_chain_addr_to_str(&l_tx_prev_out->addr) : - NULL; - // if use dst addr - bool l_is_use_dst_addr = false; - if(!memcmp(&l_tx_prev_out->addr, a_addr, sizeof(dap_chain_addr_t))) - l_is_use_dst_addr = true; - - l_src_str_is_cur = l_is_use_src_addr; - if(l_src_addr->len <= 1) { - l_src_str = - (l_tx_data) ? dap_chain_addr_to_str(&l_tx_data->addr) : - NULL; - if(!memcmp(&l_tx_prev_out->addr, a_addr, sizeof(dap_chain_addr_t))) - l_src_str_is_cur = true; - dap_string_free(l_src_addr, true); - } - else - l_src_str = dap_string_free(l_src_addr, false); - if(l_is_use_src_addr && !l_is_use_dst_addr) { - dap_string_append_printf(l_str_out, - "tx hash %s \n %s in send %lld %s from %s\n to %s\n", - l_tx_data->tx_hash_str, - l_time_str ? l_time_str : "", - l_tx_prev_out->header.value, - l_tx_data->token_ticker, - l_src_str ? l_src_str : "", - l_dst_to_str); - } else if(l_is_use_dst_addr && !l_is_use_src_addr) { - if(!l_src_str_is_cur) - dap_string_append_printf(l_str_out, - "tx hash %s \n %s in recv %lld %s from %s\n", - l_tx_data->tx_hash_str, - l_time_str ? l_time_str : "", - l_tx_prev_out->header.value, - l_tx_data->token_ticker, - l_src_str ? l_src_str : ""); - } - - DAP_DELETE(l_dst_to_str); - dap_list_free(l_list_out_prev_items); - DAP_DELETE(l_obj_prev); - } - - // OUT items - dap_list_t *l_records_tmp = l_records_out; - while(l_records_tmp) { - - const dap_chain_tx_out_t *l_tx_out = (const dap_chain_tx_out_t*) l_records_tmp->data; - - if(l_is_use_all_cur_out - || !memcmp(&l_tx_out->addr, a_addr, sizeof(dap_chain_addr_t))) { - - char *l_addr_str = (l_tx_out) ? dap_chain_addr_to_str(&l_tx_out->addr) : NULL; - - if(!memcmp(&l_tx_out->addr, a_addr, sizeof(dap_chain_addr_t))) { - if(!l_src_str_is_cur) - dap_string_append_printf(l_str_out, "tx hash %s \n %s recv %lld %s from %s\n", - l_tx_data->tx_hash_str, - l_time_str ? l_time_str : "", - l_tx_out->header.value, - l_tx_data_prev->token_ticker, - l_src_str ? l_src_str : "?"); - } - else { - dap_string_append_printf(l_str_out, "tx hash %s \n %s send %lld %s to %sd\n", - l_tx_data->tx_hash_str, - l_time_str ? l_time_str : "", - l_tx_out->header.value, - l_tx_data_prev->token_ticker, - l_addr_str ? l_addr_str : ""); - } - DAP_DELETE(l_addr_str); - } - l_records_tmp = dap_list_next(l_records_tmp); - } - dap_list_free(l_records_out); - DAP_DELETE(l_src_str); - - } - } - l_list_tmp = dap_list_next(l_list_tmp); - } - l_list_tmp = dap_list_next(l_list_tmp); - } - } - - - - if(l_list_tx_token) - dap_list_free(l_list_tx_token); - if(l_list_out_items) - dap_list_free(l_list_out_items); - if(l_list_in_items) - dap_list_free(l_list_in_items); - - DAP_DELETE(l_time_str); - } - DAP_DELETE(l_obj); - dap_strfreev(l_keys); - - } - // delete hashes - dap_tx_data_t *l_iter_current, *l_item_tmp; - HASH_ITER(hh, l_tx_data_hash , l_iter_current, l_item_tmp) - { - // delete struct - DAP_DELETE(l_iter_current); - HASH_DEL(l_tx_data_hash, l_iter_current); - } - dap_chain_global_db_objs_delete(l_objs, l_data_size_out); - // if no history - if(!l_str_out->len) - dap_string_append(l_str_out, " empty"); - char *l_ret_str = l_str_out ? dap_string_free(l_str_out, false) : NULL; - return l_ret_str; -} -#endif - - -/** - * Get data according the history log - * - * return history string - */ -char* dap_db_history(dap_chain_addr_t * a_addr, const char *a_group_mempool) -{ - dap_string_t *l_str_out = dap_string_new(NULL); - // load history - size_t l_data_size_out = 0; - dap_global_db_obj_t *l_objs = dap_chain_global_db_gr_load(GROUP_LOCAL_HISTORY, &l_data_size_out); - size_t i, j; - dap_tx_data_t *l_tx_data_hash = NULL; - for(i = 0; i < l_data_size_out; i++) { - dap_global_db_obj_t *l_obj_cur = l_objs + i; - - // parse global_db records in a history record - dap_global_db_hist_t l_rec; - if(dap_db_history_unpack_hist((char*) l_obj_cur->value, &l_rec) == -1) - continue; - // use only groups with datums - if(dap_strcmp(a_group_mempool, l_rec.group)) - continue; - - char **l_keys = dap_strsplit(l_rec.keys, GLOBAL_DB_HIST_KEY_SEPARATOR, -1); - size_t l_count = dap_str_countv(l_keys); - dap_store_obj_t *l_obj = NULL; - // all objs in one history records - for(j = 0; j < l_count; j++) { - // add record - if(l_rec.type == 'a') { - l_obj = (dap_store_obj_t*) dap_chain_global_db_obj_get(l_keys[j], l_rec.group); - if(!l_obj) - continue; - dap_chain_datum_t *l_datum = (dap_chain_datum_t*) l_obj->value; - if(!l_datum) - continue; - switch (l_datum->header.type_id) { - /* case DAP_CHAIN_DATUM_TOKEN_DECL: { - dap_chain_datum_token_t *l_token = (dap_chain_datum_token_t*) l_datum->data; - } - break; - case DAP_CHAIN_DATUM_TOKEN_EMISSION: { - dap_chain_datum_token_emission_t *l_token_emission = - (dap_chain_datum_token_emission_t*) l_datum->data; - } - break;*/ - // find transaction - case DAP_CHAIN_DATUM_TX: { - dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t*) l_datum->data; - dap_list_t *l_records_out = NULL; - - // transaction time - char *l_time_str = NULL; - if(l_tx->header.ts_created > 0) { - time_t rawtime = (time_t) l_tx->header.ts_created; - struct tm * timeinfo; - timeinfo = localtime(&rawtime); - if(timeinfo) - l_time_str = dap_strdup(asctime(timeinfo)); - } - else - l_time_str = dap_strdup(" "); - - int l_count = 0; - dap_tx_data_t *l_tx_data = NULL; - // find Token items - present in emit transaction - l_count = 0; - dap_list_t *l_list_tx_token = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_TOKEN, &l_count); - - // find OUT items - dap_list_t *l_list_out_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_OUT, &l_count); - dap_list_t *l_list_tmp = l_list_out_items; - while(l_list_tmp) { - dap_chain_tx_out_t *l_tx_out = (dap_chain_tx_out_t*) l_list_tmp->data; - // save OUT item l_tx_out - { - // save tx hash - l_tx_data = DAP_NEW_Z(dap_tx_data_t); - dap_chain_hash_fast_t l_tx_hash; - dap_hash_fast(l_tx, dap_chain_datum_tx_get_size(l_tx), &l_tx_hash); - memcpy(&l_tx_data->tx_hash, &l_tx_hash, sizeof(dap_chain_hash_fast_t)); - memcpy(&l_tx_data->addr, &l_tx_out->addr, sizeof(dap_chain_addr_t)); - l_tx_data->obj_num = i; - l_tx_data->pos_num = j; - // save token name - if(l_tx_data && l_list_tx_token) { - dap_chain_tx_token_t *tk = l_list_tx_token->data; -// int d = sizeof(l_tx_data->token_ticker); - memcpy(l_tx_data->token_ticker, tk->header.ticker, sizeof(l_tx_data->token_ticker)); - } - HASH_ADD(hh, l_tx_data_hash, tx_hash, sizeof(dap_chain_hash_fast_t), l_tx_data); - - // save OUT items to list - { - l_records_out = dap_list_append(l_records_out, (void*) l_tx_out); - } - } - l_list_tmp = dap_list_next(l_list_tmp); - } - - // find IN items - l_count = 0; - dap_list_t *l_list_in_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_IN, &l_count); - l_list_tmp = l_list_in_items; - - // find cur addr in prev OUT items - bool l_is_use_all_cur_out = false; - { - while(l_list_tmp) { - const dap_chain_tx_in_t *l_tx_in = (const dap_chain_tx_in_t*) l_list_tmp->data; - dap_chain_hash_fast_t tx_prev_hash = l_tx_in->header.tx_prev_hash; - - //find prev OUT item - dap_tx_data_t *l_tx_data_prev = NULL; - HASH_FIND(hh, l_tx_data_hash, &tx_prev_hash, sizeof(dap_chain_hash_fast_t), l_tx_data_prev); - if(l_tx_data_prev != NULL) { - // fill token in l_tx_data from prev transaction - if(l_tx_data) { - // get token from prev tx - memcpy(l_tx_data->token_ticker, l_tx_data_prev->token_ticker, - sizeof(l_tx_data->token_ticker)); - dap_store_obj_t *l_obj_prev = get_prev_tx(l_objs, l_tx_data_prev); - dap_chain_datum_t *l_datum_prev = - l_obj_prev ? (dap_chain_datum_t*) l_obj_prev->value : NULL; - dap_chain_datum_tx_t *l_tx_prev = - l_datum_prev ? (dap_chain_datum_tx_t*) l_datum_prev->data : NULL; - - // find OUT items in prev datum - dap_list_t *l_list_out_prev_items = dap_chain_datum_tx_items_get(l_tx_prev, - TX_ITEM_TYPE_OUT, &l_count); - // find OUT item for IN item; - dap_list_t *l_list_out_prev_item = dap_list_nth(l_list_out_prev_items, - l_tx_in->header.tx_out_prev_idx); - dap_chain_tx_out_t *l_tx_prev_out = - l_list_out_prev_item ? - (dap_chain_tx_out_t*) l_list_out_prev_item->data : - NULL; - if(l_tx_prev_out && !memcmp(&l_tx_prev_out->addr, a_addr, sizeof(dap_chain_addr_t))) - l_is_use_all_cur_out = true; - - } - } - l_list_tmp = dap_list_next(l_list_tmp); - } - } - - // find prev OUT items for IN items - l_list_tmp = l_list_in_items; - while(l_list_tmp) { - const dap_chain_tx_in_t *l_tx_in = (const dap_chain_tx_in_t*) l_list_tmp->data; - dap_chain_hash_fast_t tx_prev_hash = l_tx_in->header.tx_prev_hash; - // if first transaction - empty prev OUT item - if(dap_hash_fast_is_blank(&tx_prev_hash)) { - // add emit info to ret string - if(l_tx_data && a_addr && - ( memcmp(&l_tx_data->addr, a_addr, sizeof(dap_chain_addr_t) ) == 0 ) - ) { - dap_list_t *l_records_tmp = l_records_out; - while(l_records_tmp) { - const dap_chain_tx_out_t *l_tx_out = (const dap_chain_tx_out_t*) l_records_tmp->data; - dap_string_append_printf(l_str_out, "emit %lld %s\n", - l_tx_out->header.value, - l_tx_data->token_ticker); - l_records_tmp = dap_list_next(l_records_tmp); - } - } - dap_list_free(l_records_out); - } - // in other transactions except first one - else { - //find prev OUT item - dap_tx_data_t *l_tx_data_prev = NULL; - HASH_FIND(hh, l_tx_data_hash, &tx_prev_hash, sizeof(dap_chain_hash_fast_t), l_tx_data_prev); - if(l_tx_data_prev != NULL) { - char *l_src_str = NULL; - bool l_src_str_is_cur = false; - if(l_tx_data) { - // get token from prev tx - memcpy(l_tx_data->token_ticker, l_tx_data_prev->token_ticker, - sizeof(l_tx_data->token_ticker)); - - dap_store_obj_t *l_obj_prev = get_prev_tx(l_objs, l_tx_data_prev); - dap_chain_datum_t *l_datum_prev = - l_obj_prev ? (dap_chain_datum_t*) l_obj_prev->value : NULL; - dap_chain_datum_tx_t *l_tx_prev = - l_datum_prev ? (dap_chain_datum_tx_t*) l_datum_prev->data : NULL; - - // find OUT items in prev datum - dap_list_t *l_list_out_prev_items = dap_chain_datum_tx_items_get(l_tx_prev, - TX_ITEM_TYPE_OUT, &l_count); - // find OUT item for IN item; - dap_list_t *l_list_out_prev_item = dap_list_nth(l_list_out_prev_items, - l_tx_in->header.tx_out_prev_idx); - dap_chain_tx_out_t *l_tx_prev_out = - l_list_out_prev_item ? - (dap_chain_tx_out_t*) l_list_out_prev_item->data : - NULL; - // if use src addr - bool l_is_use_src_addr = false; - // find source addrs - dap_string_t *l_src_addr = dap_string_new(NULL); - { - // find IN items in prev datum - for get destination addr - dap_list_t *l_list_in_prev_items = dap_chain_datum_tx_items_get(l_tx_prev, - TX_ITEM_TYPE_IN, &l_count); - dap_list_t *l_list_tmp = l_list_in_prev_items; - while(l_list_tmp) { - dap_chain_tx_in_t *l_tx_prev_in = l_list_tmp->data; - dap_chain_hash_fast_t l_tx_prev_prev_hash = - l_tx_prev_in->header.tx_prev_hash; - //find prev OUT item - dap_tx_data_t *l_tx_data_prev_prev = NULL; - HASH_FIND(hh, l_tx_data_hash, &l_tx_prev_prev_hash, - sizeof(dap_chain_hash_fast_t), l_tx_data_prev_prev); - if(l_tx_data_prev_prev) { - // if use src addr - if(!memcmp(&l_tx_data_prev_prev->addr, a_addr, - sizeof(dap_chain_addr_t))) - l_is_use_src_addr = true; - char *l_str = dap_chain_addr_to_str(&l_tx_data_prev_prev->addr); - if(l_src_addr->len > 0) - dap_string_append_printf(l_src_addr, "\n %s", l_str); - else - dap_string_append_printf(l_src_addr, "%s", l_str); // first record - DAP_DELETE(l_str); - } - l_list_tmp = dap_list_next(l_list_tmp); - } - } - - char *l_dst_to_str = - (l_tx_prev_out) ? dap_chain_addr_to_str(&l_tx_prev_out->addr) : - NULL; - // if use dst addr - bool l_is_use_dst_addr = false; - if(l_tx_prev_out && a_addr && - ( memcmp(&l_tx_prev_out->addr, a_addr, sizeof(dap_chain_addr_t) ) == 0 )){ - l_is_use_dst_addr = true; - } - - l_src_str_is_cur = l_is_use_src_addr; - if(l_src_addr->len <= 1) { - l_src_str = - (l_tx_data) ? dap_chain_addr_to_str(&l_tx_data->addr) : - NULL; - if(!memcmp(&l_tx_prev_out->addr, a_addr, sizeof(dap_chain_addr_t))) - l_src_str_is_cur = true; - dap_string_free(l_src_addr, true); - } - else - l_src_str = dap_string_free(l_src_addr, false); - if(l_is_use_src_addr && !l_is_use_dst_addr) { - dap_string_append_printf(l_str_out, - "%s in send %lld %s from %s\n to %s\n", - l_time_str ? l_time_str : "", - l_tx_prev_out?l_tx_prev_out->header.value:0, - l_tx_data->token_ticker, - l_src_str ? l_src_str : "", - l_dst_to_str); - } else if(l_is_use_dst_addr && !l_is_use_src_addr) { - if(!l_src_str_is_cur) - dap_string_append_printf(l_str_out, - "%s in recv %lld %s from %s\n", - l_time_str ? l_time_str : "", - l_tx_prev_out->header.value, - l_tx_data->token_ticker, - l_src_str ? l_src_str : ""); - } - - DAP_DELETE(l_dst_to_str); - dap_list_free(l_list_out_prev_items); - DAP_DELETE(l_obj_prev); - } - - // OUT items - dap_list_t *l_records_tmp = l_records_out; - while(l_records_tmp) { - - const dap_chain_tx_out_t *l_tx_out = (const dap_chain_tx_out_t*) l_records_tmp->data; - - if(l_is_use_all_cur_out - || !memcmp(&l_tx_out->addr, a_addr, sizeof(dap_chain_addr_t))) { - - char *l_addr_str = (l_tx_out) ? dap_chain_addr_to_str(&l_tx_out->addr) : NULL; - - if(!memcmp(&l_tx_out->addr, a_addr, sizeof(dap_chain_addr_t))) { - if(!l_src_str_is_cur) - dap_string_append_printf(l_str_out, "%s recv %lld %s from %s\n", - l_time_str ? l_time_str : "", - l_tx_out->header.value, - l_tx_data_prev->token_ticker, - l_src_str ? l_src_str : "?"); - } - else { - dap_string_append_printf(l_str_out, "%s send %lld %s to %sd\n", - l_time_str ? l_time_str : "", - l_tx_out->header.value, - l_tx_data_prev->token_ticker, - l_addr_str ? l_addr_str : ""); - } - DAP_DELETE(l_addr_str); - } - l_records_tmp = dap_list_next(l_records_tmp); - } - dap_list_free(l_records_out); - DAP_DELETE(l_src_str); - - } - } - l_list_tmp = dap_list_next(l_list_tmp); - } - if(l_list_tx_token) - dap_list_free(l_list_tx_token); - if(l_list_out_items) - dap_list_free(l_list_out_items); - if(l_list_in_items) - dap_list_free(l_list_in_items); - - DAP_DELETE(l_time_str); - } - break; - default: - continue; - } - } - // delete record - else if(l_rec.type == 'd') { - //printf("del_gr%d_%d=%s\n", i, j, l_rec.group); - } - } - DAP_DELETE(l_obj); - dap_strfreev(l_keys); - } - // delete hashes - dap_tx_data_t *l_iter_current, *l_item_tmp; - HASH_ITER(hh, l_tx_data_hash , l_iter_current, l_item_tmp) - { - // delete struct - DAP_DELETE(l_iter_current); - HASH_DEL(l_tx_data_hash, l_iter_current); - } - dap_chain_global_db_objs_delete(l_objs, l_data_size_out); - // if no history - if(!l_str_out->len) - dap_string_append(l_str_out, "empty"); - char *l_ret_str = l_str_out ? dap_string_free(l_str_out, false) : NULL; - return l_ret_str; -} - /** * Add data to the history log */ @@ -1121,22 +121,13 @@ bool dap_db_history_add(char a_type, pdap_store_obj_t a_store_obj, size_t a_dap_ return false; } -/** - * Truncate the history log - */ -bool dap_db_history_truncate(void) -{ - // TODO - return true; -} - /** * Get last id in log */ -uint64_t dap_db_log_get_group_history_last_id(const char *a_history_group_name) +uint64_t dap_db_log_get_group_last_id(const char *a_group_name) { uint64_t result = 0; - dap_store_obj_t *l_last_obj = dap_chain_global_db_get_last(a_history_group_name); + dap_store_obj_t *l_last_obj = dap_chain_global_db_get_last(a_group_name); if(l_last_obj) { result = l_last_obj->id; dap_store_obj_free(l_last_obj, 1); @@ -1149,170 +140,69 @@ uint64_t dap_db_log_get_group_history_last_id(const char *a_history_group_name) */ uint64_t dap_db_log_get_last_id(void) { - return dap_db_log_get_group_history_last_id(GROUP_LOCAL_HISTORY); -} - -/*static int compare_items(const void * l_a, const void * l_b) -{ - const dap_global_db_obj_t *l_item_a = (const dap_global_db_obj_t*) l_a; - const dap_global_db_obj_t *l_item_b = (const dap_global_db_obj_t*) l_b; - int l_ret = strcmp(l_item_a->key, l_item_b->key); - return l_ret; -}*/ - -/** - * Get log diff as list - */ -dap_list_t* dap_db_log_get_list(uint64_t first_id) -{ - dap_list_t *l_list = NULL; - size_t l_data_size_out = 0; - //log_it(L_DEBUG,"loading db list..."); - dap_store_obj_t *l_objs = dap_chain_global_db_cond_load(GROUP_LOCAL_HISTORY, first_id, &l_data_size_out); - //dap_global_db_obj_t *l_objs = dap_chain_global_db_gr_load(GROUP_LOCAL_HISTORY, first_timestamp, &l_data_size_out); - for(size_t i = 0; i < l_data_size_out; i++) { - dap_store_obj_t *l_obj_cur = l_objs + i; - dap_global_db_obj_t *l_item = DAP_NEW(dap_global_db_obj_t); - l_item->id = l_obj_cur->id; - l_item->key = dap_strdup(l_obj_cur->key); - l_item->value = (uint8_t*) dap_strdup((char*) l_obj_cur->value); - l_list = dap_list_append(l_list, l_item); - } - //log_it(L_DEBUG,"loaded db list n=%d", l_data_size_out); - dap_store_obj_free(l_objs, l_data_size_out); - - return l_list; - /* - size_t l_list_count = 0; - char *l_first_key_str = dap_strdup_printf("%lld", (int64_t) first_timestamp); - size_t l_data_size_out = 0; - - for(size_t i = 0; i < l_data_size_out; i++) { - dap_global_db_obj_t *l_obj_cur = l_objs[i]; - // log_it(L_DEBUG,"%lld and %lld tr",strtoll(l_obj_cur->key,NULL,10), first_timestamp ); - if( strtoll(l_obj_cur->key,NULL,10) > (long long) first_timestamp ) { - dap_global_db_obj_t *l_item = DAP_NEW(dap_global_db_obj_t); - l_item->key = dap_strdup(l_obj_cur->key); - l_item->value =(uint8_t*) dap_strdup((char*) l_obj_cur->value); - l_list = dap_list_append(l_list, l_item); - l_list_count++; - } - } - // sort list by key (time str) - //dap_list_sort(l_list, (dap_callback_compare_t) compare_items); - log_it(L_DEBUG,"Prepared %u items (list size %u)", l_list_count, dap_list_length(l_list)); - DAP_DELETE(l_first_key_str); - dap_chain_global_db_objs_delete(l_objs); - */ - /*/ dbg - sort result - l_data_size_out = dap_list_length(l_list); - for(size_t i = 0; i < l_data_size_out; i++) { - dap_list_t *l_list_tmp = dap_list_nth(l_list, i); - dap_global_db_obj_t *l_item = l_list_tmp->data; - printf("2 %d %s\n", i, l_item->key); - }*/ - -} - -/** - * Free list getting from dap_db_log_get_list() - */ -void dap_db_log_del_list(dap_list_t *a_list) -{ - dap_list_free_full(a_list, (dap_callback_destroyed_t) dap_chain_global_db_obj_delete); + return dap_db_log_get_group_last_id(GROUP_LOCAL_HISTORY); } - - - /** * Thread for reading log list * instead dap_db_log_get_list() */ static void *s_list_thread_proc(void *arg) { - dap_db_log_list_t *l_dap_db_log_list = (dap_db_log_list_t*) arg; - size_t l_items_number = 0; - while(1) { - bool is_process; - char *l_group_cur_name = NULL; - // check for break process - pthread_mutex_lock(&l_dap_db_log_list->list_mutex); - is_process = l_dap_db_log_list->is_process; - size_t l_item_start = l_dap_db_log_list->item_start; - size_t l_item_last = l_dap_db_log_list->item_last; - if(l_dap_db_log_list->group_cur == -1) - l_group_cur_name = GROUP_LOCAL_HISTORY; - else - l_group_cur_name = l_dap_db_log_list->group_names[l_dap_db_log_list->group_cur]; - pthread_mutex_unlock(&l_dap_db_log_list->list_mutex); - if(!is_process) - break; - // calculating how many items required to read - size_t l_item_count =(uint64_t) min(10, (int64_t)l_item_last - (int64_t)l_item_start + 1); - dap_store_obj_t *l_objs = NULL; - // read next 1...10 items - if(l_item_count > 0) - l_objs = dap_chain_global_db_cond_load(l_group_cur_name, l_item_start, &l_item_count); - // go to next group - if(!l_objs) { - pthread_mutex_lock(&l_dap_db_log_list->list_mutex); - while(l_dap_db_log_list->group_cur < l_dap_db_log_list->group_number) { - l_dap_db_log_list->group_cur++; - // check for empty group - if( !(l_dap_db_log_list->group_number) || (l_dap_db_log_list->group_number_items[l_dap_db_log_list->group_cur] < 1)) { - continue; - } - break; - } - // end of all groups - if(l_dap_db_log_list->group_cur >= l_dap_db_log_list->group_number) { - pthread_mutex_unlock(&l_dap_db_log_list->list_mutex); + dap_db_log_list_t *l_dap_db_log_list = (dap_db_log_list_t *)arg; + for (dap_list_t *l_groups = l_dap_db_log_list->groups; l_groups && l_dap_db_log_list->is_process; l_groups = dap_list_next(l_groups)) { + dap_db_log_list_group_t *l_group_cur = (dap_db_log_list_group_t *)l_groups->data; + char *l_del_group_name_replace = NULL; + char l_obj_type; + if (!dap_fnmatch("*.del", l_group_cur->name, 0)) { + l_obj_type = 'd'; + size_t l_del_name_len = strlen(l_group_cur->name) - 4; //strlen(".del"); + l_del_group_name_replace = DAP_NEW_SIZE(char, l_del_name_len + 1); + memcpy(l_del_group_name_replace, l_group_cur->name, l_del_name_len); + l_del_group_name_replace[l_del_name_len] = '\0'; + } else { + l_obj_type = 'a'; + } + uint64_t l_item_start = l_group_cur->last_id_synced + 1; + while (l_group_cur->count && l_dap_db_log_list->is_process) { // Number of records to be synchronized + size_t l_item_count = min(32, l_group_cur->count); + dap_store_obj_t *l_objs = dap_chain_global_db_cond_load(l_group_cur->name, l_item_start, &l_item_count); + // go to next group + if (!l_objs) break; + // set new start pos = lastitem pos + 1 + l_item_start = l_objs[l_item_count - 1].id + 1; + l_group_cur->count -= l_item_count; + dap_list_t *l_list = NULL; + for (size_t i = 0; i < l_item_count; i++) { + dap_store_obj_t *l_obj_cur = l_objs + i; + l_obj_cur->type = l_obj_type; + if (l_obj_type == 'd') { + DAP_DELETE(l_obj_cur->group); + l_obj_cur->group = dap_strdup(l_del_group_name_replace); + } + dap_db_log_list_obj_t *l_list_obj = DAP_NEW_Z(dap_db_log_list_obj_t); + uint64_t l_cur_id = l_obj_cur->id; + l_obj_cur->id = 0; + dap_store_obj_pkt_t *l_pkt = dap_store_packet_single(l_obj_cur); + dap_hash_fast(l_pkt->data, l_pkt->data_size, &l_list_obj->hash); + dap_store_packet_change_id(l_pkt, l_cur_id); + l_list_obj->pkt = l_pkt; + l_list = dap_list_append(l_list, l_list_obj); + if (!l_dap_db_log_list->is_process) + break; } - l_dap_db_log_list->item_start = 0; - l_dap_db_log_list->item_last = l_dap_db_log_list->group_last_id[l_dap_db_log_list->group_cur]; - l_item_start = l_dap_db_log_list->item_start; - l_item_last = l_dap_db_log_list->item_last; - if(l_dap_db_log_list->group_cur == -1) - l_group_cur_name = GROUP_LOCAL_HISTORY; - else - l_group_cur_name = l_dap_db_log_list->group_names[l_dap_db_log_list->group_cur]; + dap_store_obj_free(l_objs, l_item_count); + pthread_mutex_lock(&l_dap_db_log_list->list_mutex); + // add l_list to list_write + l_dap_db_log_list->list_write = dap_list_concat(l_dap_db_log_list->list_write, l_list); + // init read list if it ended already + if(!l_dap_db_log_list->list_read) + l_dap_db_log_list->list_read = l_list; pthread_mutex_unlock(&l_dap_db_log_list->list_mutex); - - //l_item_count = min(10, (int64_t)l_item_last - (int64_t)l_item_start + 1); - //if(l_item_count<=0) - // continue; - // read next 1...10 items - //l_objs = dap_chain_global_db_cond_load(l_group_cur_name, l_item_start, &l_item_count); - continue; - } - //if(!l_objs) - //continue; - dap_list_t *l_list = NULL; - for(size_t i = 0; i < l_item_count; i++) { - dap_store_obj_t *l_obj_cur = l_objs + i; - dap_global_db_obj_t *l_item = DAP_NEW(dap_global_db_obj_t); - l_item->id = l_obj_cur->id; - l_item->key = dap_strdup(l_obj_cur->key); - l_item->value = (uint8_t*) dap_strdup((char*) l_obj_cur->value); - l_list = dap_list_append(l_list, l_item); } - pthread_mutex_lock(&l_dap_db_log_list->list_mutex); - // add l_list to list_write - l_dap_db_log_list->list_write = dap_list_concat(l_dap_db_log_list->list_write, l_list); - // init read list if it ended already - if(!l_dap_db_log_list->list_read) - l_dap_db_log_list->list_read = l_list; - // set new start pos = lastitem pos + 1 - if(l_item_count > 0) - l_dap_db_log_list->item_start = l_objs[l_item_count - 1].id + 1; - //else - // l_dap_db_log_list->item_start += l_data_size_out; - pthread_mutex_unlock(&l_dap_db_log_list->list_mutex); - l_items_number += l_item_count; - //log_it(L_DEBUG, "loaded items n=%u/%u", l_data_size_out, l_items_number); - dap_store_obj_free(l_objs, l_item_count); + if (l_del_group_name_replace) + DAP_DELETE(l_del_group_name_replace); } pthread_mutex_lock(&l_dap_db_log_list->list_mutex); @@ -1324,70 +214,39 @@ static void *s_list_thread_proc(void *arg) /** * instead dap_db_log_get_list() */ -dap_db_log_list_t* dap_db_log_list_start(uint64_t first_id, dap_list_t *a_add_groups_mask) +dap_db_log_list_t* dap_db_log_list_start(dap_chain_node_addr_t a_addr, int a_flags) { - +#ifdef GDB_SYNC_ALWAYS_FROM_ZERO + a_flags |= F_DB_LOG_SYNC_FROM_ZERO; +#endif //log_it(L_DEBUG, "Start loading db list_write..."); - - size_t l_add_groups_num = 0;// number of group - dap_list_t *l_add_groups_mask = a_add_groups_mask; - // calc l_add_groups_num - while(l_add_groups_mask) { - // не Ñчитать группы del - dap_list_t *l_groups = dap_chain_global_db_driver_get_groups_by_mask(l_add_groups_mask->data); - l_add_groups_num += dap_list_length(l_groups); - dap_list_free_full(l_groups, (dap_callback_destroyed_t) free); - l_add_groups_mask = dap_list_next(l_add_groups_mask); + dap_db_log_list_t *l_dap_db_log_list = DAP_NEW_Z(dap_db_log_list_t); + dap_list_t *l_groups_masks = dap_chain_db_get_sync_groups(); + if (a_flags & F_DB_LOG_ADD_EXTRA_GROUPS) { + l_groups_masks = dap_list_concat(l_groups_masks, dap_chain_db_get_sync_extra_groups()); } - if(l_add_groups_num == 0) - return NULL; + for (dap_list_t *l_cur_mask = l_groups_masks; l_cur_mask; l_cur_mask = dap_list_next(l_cur_mask)) { + l_dap_db_log_list->groups = dap_list_concat(l_dap_db_log_list->groups, + dap_chain_global_db_driver_get_groups_by_mask(l_cur_mask->data)); + } + dap_list_free(l_groups_masks); - size_t l_data_size_out_main = dap_db_log_get_last_id() - first_id + 1; - //dap_chain_global_db_driver_count(GROUP_LOCAL_HISTORY, first_id); - not working for sqlite - size_t *l_data_size_out_add_items = DAP_NEW_Z_SIZE(size_t, sizeof(size_t) * l_add_groups_num); - uint64_t *l_group_last_id = DAP_NEW_Z_SIZE(uint64_t, sizeof(uint64_t) * l_add_groups_num); - char **l_group_names = DAP_NEW_Z_SIZE(char*, sizeof(char*) * l_add_groups_num); - size_t l_data_size_out_add_items_count = 0; - l_add_groups_mask = a_add_groups_mask; - while(l_add_groups_mask){ - dap_list_t *l_groups0 = dap_chain_global_db_driver_get_groups_by_mask(l_add_groups_mask->data); - dap_list_t *l_groups = l_groups0; - size_t l_group_cur = 0; - while(l_groups){ - const char *l_group_name = (const char *) l_groups->data; - l_group_names[l_group_cur] = dap_strdup(dap_chain_global_db_get_history_group_by_group_name(l_group_name)); - dap_store_obj_t *l_obj = dap_chain_global_db_driver_read_last(l_group_names[l_group_cur]); - if(l_obj) { - l_group_last_id[l_group_cur] = l_obj->id; - dap_store_obj_free(l_obj, 1); - } - l_data_size_out_add_items[l_group_cur] = dap_chain_global_db_driver_count(l_group_names[l_group_cur], 1); - l_data_size_out_add_items_count += l_data_size_out_add_items[l_group_cur]; - l_group_cur++; - l_groups = dap_list_next(l_groups); - } - dap_list_free_full(l_groups0, (dap_callback_destroyed_t) free); - l_add_groups_mask = dap_list_next(l_add_groups_mask); + for (dap_list_t *l_groups = l_dap_db_log_list->groups; l_groups; l_groups = dap_list_next(l_groups)) { + dap_db_log_list_group_t *l_replace = DAP_NEW_Z(dap_db_log_list_group_t); + l_replace->name = (char *)l_groups->data; + if (a_flags & F_DB_LOG_SYNC_FROM_ZERO) + l_replace->last_id_synced = 0; + else + l_replace->last_id_synced = dap_db_get_last_id_remote(a_addr.uint64, l_replace->name); + l_replace->count = dap_chain_global_db_driver_count(l_replace->name, l_replace->last_id_synced + 1); + l_dap_db_log_list->items_number += l_replace->count; + l_groups->data = (void *)l_replace; } - if(!(l_data_size_out_main + l_data_size_out_add_items_count)){ - DAP_DELETE(l_data_size_out_add_items); - DAP_DELETE(l_group_last_id); - DAP_DELETE(l_group_names); + l_dap_db_log_list->items_rest = l_dap_db_log_list->items_number; + if (!l_dap_db_log_list->items_number) { + DAP_DELETE(l_dap_db_log_list); return NULL; } - dap_db_log_list_t *l_dap_db_log_list = DAP_NEW_Z(dap_db_log_list_t); - l_dap_db_log_list->item_start = first_id; - l_dap_db_log_list->item_last = first_id + l_data_size_out_main; - l_dap_db_log_list->items_number_main = l_data_size_out_main; - l_dap_db_log_list->items_number_add = l_data_size_out_add_items_count; - l_dap_db_log_list->items_number = l_data_size_out_main + l_data_size_out_add_items_count; - l_dap_db_log_list->items_rest = l_dap_db_log_list->items_number; - l_dap_db_log_list->group_number = (int64_t)l_add_groups_num; - l_dap_db_log_list->group_number_items = l_data_size_out_add_items; - l_dap_db_log_list->group_last_id = l_group_last_id; - l_dap_db_log_list->group_names = l_group_names; - l_dap_db_log_list->group_cur = -1; - l_dap_db_log_list->add_groups = a_add_groups_mask; l_dap_db_log_list->is_process = true; pthread_mutex_init(&l_dap_db_log_list->list_mutex, NULL); pthread_create(&l_dap_db_log_list->thread, NULL, s_list_thread_proc, l_dap_db_log_list); @@ -1421,7 +280,7 @@ size_t dap_db_log_list_get_count_rest(dap_db_log_list_t *a_db_log_list) /** * Get one item from log_list */ -dap_global_db_obj_t* dap_db_log_list_get(dap_db_log_list_t *a_db_log_list) +dap_db_log_list_obj_t* dap_db_log_list_get(dap_db_log_list_t *a_db_log_list) { if(!a_db_log_list) return NULL; @@ -1449,10 +308,17 @@ dap_global_db_obj_t* dap_db_log_list_get(dap_db_log_list_t *a_db_log_list) break; } //log_it(L_DEBUG, "get item n=%d", a_db_log_list->items_number - a_db_log_list->items_rest); - return (dap_global_db_obj_t*) l_list ? l_list->data : NULL; + return l_list ? (dap_db_log_list_obj_t *)l_list->data : NULL; //return l_list; } +void dap_db_log_list_delete_item(void *a_item) +{ + dap_db_log_list_obj_t *l_list_item = (dap_db_log_list_obj_t *)a_item; + DAP_DELETE(l_list_item->pkt); + DAP_DELETE(l_list_item); +} + /** * Get log diff as list_write */ @@ -1467,13 +333,8 @@ void dap_db_log_list_delete(dap_db_log_list_t *a_db_log_list) pthread_mutex_unlock(&a_db_log_list->list_mutex); pthread_join(a_db_log_list->thread, NULL); } - for(int64_t i = 0; i < a_db_log_list->group_number; i++) - DAP_DELETE(a_db_log_list->group_names[i]); - DAP_DELETE(a_db_log_list->group_names); - DAP_DELETE(a_db_log_list->group_last_id); - DAP_DELETE(a_db_log_list->group_number_items); - dap_list_free(a_db_log_list->add_groups); - dap_list_free_full(a_db_log_list->list_write, (dap_callback_destroyed_t) dap_chain_global_db_obj_delete); + dap_list_free_full(a_db_log_list->groups, free); + dap_list_free_full(a_db_log_list->list_write, (dap_callback_destroyed_t)dap_db_log_list_delete_item); pthread_mutex_destroy(&a_db_log_list->list_mutex); DAP_DELETE(a_db_log_list); } diff --git a/modules/global-db/dap_chain_global_db_remote.c b/modules/global-db/dap_chain_global_db_remote.c index e0b3650be62a68a18ea1de4104c3a2dd06f46a5a..8075026a12d0dd7fc54ecb491d1a546d9b1b0f3d 100644 --- a/modules/global-db/dap_chain_global_db_remote.c +++ b/modules/global-db/dap_chain_global_db_remote.c @@ -90,7 +90,6 @@ uint64_t dap_db_get_cur_node_addr(char *a_net_name) time_t l_dt = time(NULL) - l_node_time; //NODE_TIME_EXPIRED if(l_node_time && l_dt > addr_time_expired) { - //log_it(L_NOTICE, "Node 0x%016X set last synced timestamp %"DAP_UINT64_FORMAT_U"", a_id); l_node_addr_ret = 0; } DAP_DELETE(l_key); @@ -103,31 +102,33 @@ uint64_t dap_db_get_cur_node_addr(char *a_net_name) /** * Set last id for remote node */ -bool dap_db_set_last_id_remote(uint64_t a_node_addr, uint64_t a_id) +bool dap_db_set_last_id_remote(uint64_t a_node_addr, uint64_t a_id, char *a_group) { - //log_it( L_DEBUG, "Node 0x%016X set last synced timestamp %"DAP_UINT64_FORMAT_U"", a_node_addr, a_id); - uint64_t *l_id = DAP_NEW(uint64_t); - *l_id = a_id; - return dap_chain_global_db_gr_set(dap_strdup_printf("%ju", a_node_addr), - l_id, sizeof(uint64_t), - GROUP_LOCAL_NODE_LAST_ID); + //log_it( L_DEBUG, "Node 0x%016X set last synced id %"DAP_UINT64_FORMAT_u"", a_node_addr, a_id); + char *l_node_addr_str = dap_strdup_printf("%ju%s", a_node_addr, a_group); + bool l_ret = dap_chain_global_db_gr_set(l_node_addr_str, &a_id, sizeof(uint64_t), + GROUP_LOCAL_NODE_LAST_ID); + DAP_DELETE(l_node_addr_str); + return l_ret; } /** * Get last id for remote node */ -uint64_t dap_db_get_last_id_remote(uint64_t a_node_addr) +uint64_t dap_db_get_last_id_remote(uint64_t a_node_addr, char *a_group) { - 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); - uint64_t l_ret_timestamp = 0; - if(l_timestamp && l_timestamp_len == sizeof(uint64_t)) - memcpy(&l_ret_timestamp, l_timestamp, l_timestamp_len); + char *l_node_addr_str = dap_strdup_printf("%ju%s", a_node_addr, a_group); + size_t l_id_len = 0; + uint8_t *l_id = dap_chain_global_db_gr_get((const char*) l_node_addr_str, &l_id_len, + GROUP_LOCAL_NODE_LAST_ID); + uint64_t l_ret_id = 0; + if (l_id) { + if (l_id_len == sizeof(uint64_t)) + memcpy(&l_ret_id, l_id, l_id_len); + DAP_DELETE(l_id); + } DAP_DELETE(l_node_addr_str); - DAP_DELETE(l_timestamp); - return l_ret_timestamp; + return l_ret_id; } /** @@ -152,3 +153,166 @@ dap_chain_hash_fast_t *dap_db_get_last_hash_remote(uint64_t a_node_addr, dap_cha DAP_DELETE(l_node_chain_str); return (dap_chain_hash_fast_t *)l_hash; } + +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(time_t) + + 2 * sizeof(uint64_t) + dap_strlen(store_obj->group) + + dap_strlen(store_obj->key) + store_obj->value_len; + return size; +} + +/** + * serialization + * @param a_old_pkt an object for multiplexation + * @param a_new_pkt an object for multiplexation + * @return NULL in case of an error + */ +dap_store_obj_pkt_t *dap_store_packet_multiple(dap_store_obj_pkt_t *a_old_pkt, dap_store_obj_pkt_t *a_new_pkt) +{ + if (!a_new_pkt) + return a_old_pkt; + if (a_old_pkt) + a_old_pkt = (dap_store_obj_pkt_t *)DAP_REALLOC(a_old_pkt, + a_old_pkt->data_size + a_new_pkt->data_size + sizeof(dap_store_obj_pkt_t)); + else + a_old_pkt = DAP_NEW_Z_SIZE(dap_store_obj_pkt_t, a_new_pkt->data_size + sizeof(dap_store_obj_pkt_t)); + memcpy(a_old_pkt->data + a_old_pkt->data_size, a_new_pkt->data, a_new_pkt->data_size); + a_old_pkt->data_size += a_new_pkt->data_size; + a_old_pkt->obj_count++; + return a_old_pkt; +} + +char *dap_store_packet_get_group(dap_store_obj_pkt_t *a_pkt) +{ + uint16_t l_gr_len; + memcpy(&l_gr_len, a_pkt->data + sizeof(uint32_t), sizeof(uint16_t)); + char *l_ret_str = DAP_NEW_SIZE(char, l_gr_len + 1); + size_t l_gr_offset = sizeof(uint32_t) + sizeof(uint16_t); + memcpy(l_ret_str, a_pkt->data + l_gr_offset, l_gr_len); + l_ret_str[l_gr_len] = '\0'; + return l_ret_str; +} + +uint64_t dap_store_packet_get_id(dap_store_obj_pkt_t *a_pkt) +{ + uint16_t l_gr_len; + memcpy(&l_gr_len, a_pkt->data + sizeof(uint32_t), sizeof(uint16_t)); + size_t l_id_offset = sizeof(uint32_t) + sizeof(uint16_t) + l_gr_len; + uint64_t l_ret_id; + memcpy(&l_ret_id, a_pkt->data + l_id_offset, sizeof(uint64_t)); + return l_ret_id; +} + +void dap_store_packet_change_id(dap_store_obj_pkt_t *a_pkt, uint64_t a_id) +{ + uint16_t l_gr_len; + memcpy(&l_gr_len, a_pkt->data + sizeof(uint32_t), sizeof(uint16_t)); + size_t l_id_offset = sizeof(uint32_t) + sizeof(uint16_t) + l_gr_len; + memcpy(a_pkt->data + l_id_offset, &a_id, sizeof(uint64_t)); +} + +/** + * serialization + * @param a_store_obj an object for serialization + * @return NULL in case of an error + */ +dap_store_obj_pkt_t *dap_store_packet_single(pdap_store_obj_t a_store_obj) +{ + if (!a_store_obj) + return NULL; + + uint32_t l_data_size_out = dap_db_get_size_pdap_store_obj_t(a_store_obj); + dap_store_obj_pkt_t *l_pkt = DAP_NEW_SIZE(dap_store_obj_pkt_t, l_data_size_out + sizeof(dap_store_obj_pkt_t)); + l_pkt->data_size = l_data_size_out; + l_pkt->obj_count = 1; + l_pkt->timestamp = 0; + uint32_t l_type = a_store_obj->type; + memcpy(l_pkt->data, &l_type, sizeof(uint32_t)); + uint64_t l_offset = sizeof(uint32_t); + uint16_t group_size = (uint16_t) dap_strlen(a_store_obj->group); + memcpy(l_pkt->data + l_offset, &group_size, sizeof(uint16_t)); + l_offset += sizeof(uint16_t); + memcpy(l_pkt->data + l_offset, a_store_obj->group, group_size); + l_offset += group_size; + memcpy(l_pkt->data + l_offset, &a_store_obj->id, sizeof(uint64_t)); + l_offset += sizeof(uint64_t); + memcpy(l_pkt->data + l_offset, &a_store_obj->timestamp, sizeof(time_t)); + l_offset += sizeof(time_t); + uint16_t key_size = (uint16_t) dap_strlen(a_store_obj->key); + memcpy(l_pkt->data + l_offset, &key_size, sizeof(uint16_t)); + l_offset += sizeof(uint16_t); + memcpy(l_pkt->data + l_offset, a_store_obj->key, key_size); + l_offset += key_size; + memcpy(l_pkt->data + l_offset, &a_store_obj->value_len, sizeof(uint64_t)); + l_offset += sizeof(uint64_t); + memcpy(l_pkt->data + l_offset, a_store_obj->value, a_store_obj->value_len); + l_offset += a_store_obj->value_len; + assert(l_offset == l_data_size_out); + 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 = pkt->obj_count; + dap_store_obj_t *store_obj = DAP_NEW_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_length; + + uint32_t l_type; + if (offset+sizeof (uint32_t)> pkt->data_size) {log_it(L_ERROR, "Broken GDB element: can't read 'type' field"); break;} // Check for buffer boundries + memcpy(&l_type, pkt->data + offset, sizeof(uint32_t)); + obj->type = l_type; + offset += sizeof(uint32_t); + + if (offset+sizeof (uint16_t)> pkt->data_size) {log_it(L_ERROR, "Broken GDB element: can't read 'group_length' field"); break;} // Check for buffer boundries + memcpy(&str_length, pkt->data + offset, sizeof(uint16_t)); + offset += sizeof(uint16_t); + + if (offset+str_length> pkt->data_size) {log_it(L_ERROR, "Broken GDB element: can't read 'group' field"); break;} // Check for buffer boundries + obj->group = DAP_NEW_SIZE(char, str_length + 1); + memcpy(obj->group, pkt->data + offset, str_length); + obj->group[str_length] = '\0'; + offset += str_length; + + if (offset+sizeof (uint64_t)> pkt->data_size) {log_it(L_ERROR, "Broken GDB element: can't read 'id' field"); break;} // Check for buffer boundries + memcpy(&obj->id, pkt->data + offset, sizeof(uint64_t)); + offset += sizeof(uint64_t); + + if (offset+sizeof (time_t)> pkt->data_size) {log_it(L_ERROR, "Broken GDB element: can't read 'timestamp' field"); break;} // Check for buffer boundries + memcpy(&obj->timestamp, pkt->data + offset, sizeof(time_t)); + offset += sizeof(time_t); + + if (offset+sizeof (uint16_t)> pkt->data_size) {log_it(L_ERROR, "Broken GDB element: can't read 'key_length' field"); break;} // Check for buffer boundries + memcpy(&str_length, pkt->data + offset, sizeof(uint16_t)); + offset += sizeof(uint16_t); + + if (offset+ str_length > pkt->data_size) {log_it(L_ERROR, "Broken GDB element: can't read 'key' field"); break;} // Check for buffer boundries + obj->key = DAP_NEW_SIZE(char, str_length + 1); + memcpy(obj->key, pkt->data + offset, str_length); + obj->key[str_length] = '\0'; + offset += str_length; + + if (offset+sizeof (uint64_t)> pkt->data_size) {log_it(L_ERROR, "Broken GDB element: can't read 'value_length' field"); break;} // Check for buffer boundries + memcpy(&obj->value_len, pkt->data + offset, sizeof(uint64_t)); + offset += sizeof(uint64_t); + + if (offset+obj->value_len> pkt->data_size) {log_it(L_ERROR, "Broken GDB element: can't read 'value' field"); break;} // Check for buffer boundries + obj->value = DAP_NEW_SIZE(uint8_t, obj->value_len); + 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; +} diff --git a/modules/global-db/include/dap_chain_global_db.h b/modules/global-db/include/dap_chain_global_db.h index 807ca35db612f1bbdbd069b07574d06efa6e11b7..0cefa57fac338ecbf91aceb9e88f51814dd23091 100644 --- a/modules/global-db/include/dap_chain_global_db.h +++ b/modules/global-db/include/dap_chain_global_db.h @@ -23,9 +23,8 @@ typedef struct dap_global_db_obj { size_t value_len; }DAP_ALIGN_PACKED dap_global_db_obj_t, *pdap_global_db_obj_t; -typedef void (*dap_global_db_obj_callback_notify_t) (void * a_arg, const char a_op_code, const char * a_prefix, const char * a_group, - const char * a_key, const void * a_value, - const size_t a_value_len); +typedef void (*dap_global_db_obj_callback_notify_t) (void * a_arg, const char a_op_code, const char * a_group, + const char * a_key, const void * a_value, const size_t a_value_len); /** * Flush DB @@ -49,22 +48,15 @@ void dap_chain_global_db_objs_delete(dap_global_db_obj_t *objs, size_t a_count); int dap_chain_global_db_init(dap_config_t * a_config); void dap_chain_global_db_deinit(void); - -/* - * Get history group by group name - */ -char* dap_chain_global_db_get_history_group_by_group_name(const char * a_group_name); - /** * Setup callbacks and filters */ -// Add group prefix that will be tracking all changes -void dap_chain_global_db_add_history_group_prefix(const char * a_group_prefix, const char * a_group_name_for_history); -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); -const char* dap_chain_global_db_add_history_extra_group(const char * a_group_name, dap_chain_node_addr_t *a_nodes, uint16_t *a_nodes_count); -void dap_chain_global_db_add_history_extra_group_callback_notify(const char * a_group_prefix, - dap_global_db_obj_callback_notify_t a_callback, void * a_arg); +// Add group name that will be synchronized +void dap_chain_global_db_add_sync_group(const char *a_group_prefix, dap_global_db_obj_callback_notify_t a_callback, void *a_arg); +void dap_chain_global_db_add_sync_extra_group(const char *a_group_mask, dap_global_db_obj_callback_notify_t a_callback, void *a_arg); +dap_list_t *dap_chain_db_get_sync_groups(); +dap_list_t *dap_chain_db_get_sync_extra_groups(); +void dap_global_db_obj_track_history(void* a_store_data); /** * Get entry from base */ @@ -116,26 +108,3 @@ 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); char* dap_chain_global_db_hash_fast(const uint8_t *data, size_t data_size); - -// Get data according the history log -dap_list_t* dap_db_log_pack(dap_global_db_obj_t *a_obj, size_t *a_data_size_out); - -// Get data according the history log -//char* dap_db_history_tx(dap_chain_hash_fast_t * a_tx_hash, const char *a_group_mempool); -//char* dap_db_history_addr(dap_chain_addr_t * a_addr, const char *a_group_mempool); -//char* dap_db_history(dap_chain_addr_t * a_addr, const char *a_group_mempool); - -// Parse data from dap_db_log_pack() -void* dap_db_log_unpack(const void *a_data, size_t a_data_size, size_t *a_store_obj_count); -// Get timestamp from dap_db_log_pack() -//time_t dap_db_log_unpack_get_timestamp(uint8_t *a_data, size_t a_data_size); - -// Get last id in log -uint64_t dap_db_log_get_group_history_last_id(const char *a_history_group_name); -uint64_t dap_db_log_get_last_id(void); -// Get log diff as list -dap_list_t* dap_db_log_get_list(uint64_t first_id); -// Free list getting from dap_db_log_get_list() -void dap_db_log_del_list(dap_list_t *a_list); -// Get log diff as string -char* dap_db_log_get_diff(size_t *a_data_size_out); diff --git a/modules/global-db/include/dap_chain_global_db_driver.h b/modules/global-db/include/dap_chain_global_db_driver.h index 4bccdc9e0905fa1ee4423aca3459065b331c29de..ecf75715ecb4423ec15d2d0cc05776b0a7b97c70 100644 --- a/modules/global-db/include/dap_chain_global_db_driver.h +++ b/modules/global-db/include/dap_chain_global_db_driver.h @@ -29,15 +29,12 @@ #include "dap_common.h" #include "dap_list.h" -#define DAP_CHAIN_PKT_EXPECT_SIZE 7168 - typedef struct dap_store_obj { uint64_t id; time_t timestamp; uint8_t type; char *group; char *key; - //const char *c_group; const char *c_key; uint8_t *value; size_t value_len; @@ -92,8 +89,3 @@ dap_store_obj_t* dap_chain_global_db_driver_read(const char *a_group, const char 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_list_t* dap_chain_global_db_driver_get_groups_by_mask(const char *a_group_mask); - -dap_list_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_multiple(const dap_store_obj_pkt_t *a_pkt, - size_t *a_store_obj_count); diff --git a/modules/global-db/include/dap_chain_global_db_driver_sqlite.h b/modules/global-db/include/dap_chain_global_db_driver_sqlite.h index 2d1175df09dee149211876af69383abed045162f..7c05f5fd33c4dcb73aaae0b62baf8e06c9296202 100644 --- a/modules/global-db/include/dap_chain_global_db_driver_sqlite.h +++ b/modules/global-db/include/dap_chain_global_db_driver_sqlite.h @@ -50,3 +50,6 @@ int dap_db_driver_sqlite_apply_store_obj(dap_store_obj_t *a_store_obj); dap_store_obj_t* dap_db_driver_sqlite_read_last_store_obj(const char *a_group); dap_store_obj_t* dap_db_driver_sqlite_read_cond_store_obj(const char *a_group, uint64_t a_id, size_t *a_count_out); 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_list_t* dap_db_driver_sqlite_get_groups_by_mask(const char *a_group_mask); +size_t dap_db_driver_sqlite_read_count_store(const char *a_group, uint64_t a_id); +bool dap_db_driver_sqlite_is_obj(const char *a_group, const char *a_key); diff --git a/modules/global-db/include/dap_chain_global_db_hist.h b/modules/global-db/include/dap_chain_global_db_hist.h index f50e902c1310e08ca1eea3b87873cf6a30eea7cb..a74fe304f15609d822c33b0bdca6aff353f94339 100644 --- a/modules/global-db/include/dap_chain_global_db_hist.h +++ b/modules/global-db/include/dap_chain_global_db_hist.h @@ -8,6 +8,9 @@ #define GLOBAL_DB_HIST_REC_SEPARATOR "\r;" #define GLOBAL_DB_HIST_KEY_SEPARATOR "\a;" +#define F_DB_LOG_ADD_EXTRA_GROUPS 1 +#define F_DB_LOG_SYNC_FROM_ZERO 2 + typedef struct dap_global_db_hist { char type;// 'a' add or 'd' delete const char *group; @@ -18,34 +21,36 @@ typedef struct dap_global_db_hist { //Add data to the history log bool dap_db_history_add(char a_type, pdap_store_obj_t a_store_obj, size_t a_dap_store_count, const char *a_group); -// Truncate the history log -bool dap_db_history_truncate(void); +// for dap_db_log_list_xxx() + +typedef struct dap_db_log_list_group { + char *name; + uint64_t last_id_synced; + uint64_t count; +} dap_db_log_list_group_t; +typedef struct dap_db_log_list_obj { + dap_store_obj_pkt_t *pkt; + dap_hash_fast_t hash; +} dap_db_log_list_obj_t; -// 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) bool is_process; - 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_main; - size_t items_number_add; - size_t items_number; // remaining items in list_write after reading from db - char **group_names; - int64_t group_number; // number of group - int64_t group_cur; // current group number, -1 for the main group, 0 ... group_count for the additional group - size_t *group_number_items; // number of items for each group - uint64_t *group_last_id; - dap_list_t *add_groups; // additional group for sync + size_t items_number; // total items in list_write after reading from db + dap_list_t *groups; pthread_t thread; pthread_mutex_t list_mutex; } dap_db_log_list_t; -dap_db_log_list_t* dap_db_log_list_start(uint64_t first_id, dap_list_t *a_add_groups); +dap_db_log_list_t* dap_db_log_list_start(dap_chain_node_addr_t a_addr, int flags); size_t dap_db_log_list_get_count(dap_db_log_list_t *a_db_log_list); size_t dap_db_log_list_get_count_rest(dap_db_log_list_t *a_db_log_list); -dap_global_db_obj_t* dap_db_log_list_get(dap_db_log_list_t *a_db_log_list); +dap_db_log_list_obj_t *dap_db_log_list_get(dap_db_log_list_t *a_db_log_list); void dap_db_log_list_delete(dap_db_log_list_t *a_db_log_list); +// Get last id in log +uint64_t dap_db_log_get_group_last_id(const char *a_group_name); +uint64_t dap_db_log_get_last_id(void); diff --git a/modules/global-db/include/dap_chain_global_db_remote.h b/modules/global-db/include/dap_chain_global_db_remote.h index 7a58f3b1e4a56b2c1eeac90ef15335a0de8c0c59..7e63ac02b733e85c6f07e49433e403065908a176 100644 --- a/modules/global-db/include/dap_chain_global_db_remote.h +++ b/modules/global-db/include/dap_chain_global_db_remote.h @@ -4,16 +4,24 @@ #include <time.h> #include "dap_chain.h" #include "dap_chain_common.h" +#include "dap_chain_global_db_driver.h" // Set addr for current node bool dap_db_set_cur_node_addr(uint64_t a_address, char *a_net_name); bool dap_db_set_cur_node_addr_exp(uint64_t a_address, char *a_net_name ); uint64_t dap_db_get_cur_node_addr(char *a_net_name); // Set last id for remote node -bool dap_db_set_last_id_remote(uint64_t a_node_addr, uint64_t a_id); +bool dap_db_set_last_id_remote(uint64_t a_node_addr, uint64_t a_id, char *a_group); // Get last id for remote node -uint64_t dap_db_get_last_id_remote(uint64_t a_node_addr); +uint64_t dap_db_get_last_id_remote(uint64_t a_node_addr, char *a_group); // Set last hash for chain for remote node bool dap_db_set_last_hash_remote(uint64_t a_node_addr, dap_chain_t *a_chain, dap_chain_hash_fast_t *a_hash); // Get last hash for chain for remote node dap_chain_hash_fast_t *dap_db_get_last_hash_remote(uint64_t a_node_addr, dap_chain_t *a_chain); + +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(dap_store_obj_pkt_t *a_old_pkt, dap_store_obj_pkt_t *a_new_pkt); +dap_store_obj_t *dap_store_unpacket_multiple(const dap_store_obj_pkt_t *a_pkt, size_t *a_store_obj_count); +char *dap_store_packet_get_group(dap_store_obj_pkt_t *a_pkt); +uint64_t dap_store_packet_get_id(dap_store_obj_pkt_t *a_pkt); +void dap_store_packet_change_id(dap_store_obj_pkt_t *a_pkt, uint64_t a_id); diff --git a/modules/net/CMakeLists.txt b/modules/net/CMakeLists.txt index 4085114464c3c8402f4581a3bc27ad5551eb0b02..4c05cea61e5af5c5a8710ee0c20c5a9904af0c74 100644 --- a/modules/net/CMakeLists.txt +++ b/modules/net/CMakeLists.txt @@ -37,7 +37,7 @@ endif() add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_NET_SRCS} ${DAP_CHAIN_NET_HEADERS} ${IPUTILS_SRCS} ${IPUTILS_HEADERS}) if(WIN32) - target_link_libraries(dap_core dap_chain_net dap_crypto dap_client dap_server_core dap_stream_ch_chain dap_stream_ch_chain_net dap_stream_ch_chain_net_srv dap_chain dap_chain_wallet dap_chain_net_srv + target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_client dap_server_core dap_notify_srv dap_stream_ch_chain dap_stream_ch_chain_net dap_stream_ch_chain_net_srv dap_chain dap_chain_wallet dap_chain_net_srv dap_chain_mempool dap_chain_global_db dap_chain_cs_none) endif() diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c index 90e3433e548957359715adaf185a5c7bdb97b80a..1d26565b6d0d7327d4b3f1e2271dbcfbcf744842 100644 --- a/modules/net/dap_chain_net.c +++ b/modules/net/dap_chain_net.c @@ -241,7 +241,7 @@ static void s_net_proc_kill( dap_chain_net_t * a_net ); int s_net_load(const char * a_net_name, uint16_t a_acl_idx); // Notify callback for GlobalDB changes -static void s_gbd_history_callback_notify (void * a_arg,const char a_op_code, const char * a_prefix, const char * a_group, +static void s_gbd_history_callback_notify (void * a_arg, const char a_op_code, const char * a_group, const char * a_key, const void * a_value, const size_t a_value_len); static void s_chain_callback_notify(void * a_arg, dap_chain_t *a_chain, dap_chain_cell_id_t a_id, void *a_atom, size_t a_atom_size); @@ -296,6 +296,7 @@ int dap_chain_net_state_go_to(dap_chain_net_t * a_net, dap_chain_net_state_t a_n pthread_mutex_lock( &PVT(a_net)->state_mutex_cond); // Preventing call of state_go_to before wait cond will be armed // set flag for sync PVT(a_net)->flags |= F_DAP_CHAIN_NET_GO_SYNC; + //PVT(a_net)->flags |= F_DAP_CHAIN_NET_SYNC_FROM_ZERO; #ifndef _WIN32 pthread_cond_signal( &PVT(a_net)->state_proc_cond ); #else @@ -312,10 +313,10 @@ void dap_chain_net_set_srv_callback_notify(dap_global_db_obj_callback_notify_t a s_srv_callback_notify = a_callback; } -void dap_chain_net_sync_gdb_broadcast(void *a_arg, const char a_op_code, const char *a_prefix, const char *a_group, +void dap_chain_net_sync_gdb_broadcast(void *a_arg, const char a_op_code, const char *a_group, const char *a_key, const void *a_value, const size_t a_value_len) { - UNUSED(a_prefix); + UNUSED(a_value); UNUSED(a_value_len); dap_chain_net_t *l_net = (dap_chain_net_t *)a_arg; if (PVT(l_net)->state == NET_STATE_ONLINE) { @@ -336,9 +337,7 @@ void dap_chain_net_sync_gdb_broadcast(void *a_arg, const char a_op_code, const c l_obj->type = (uint8_t)a_op_code; DAP_DELETE(l_obj->group); l_obj->group = dap_strdup(a_group); - dap_list_t *l_list_out = dap_store_packet_multiple(l_obj, l_obj->timestamp, 1); - // Expect only one element in list - dap_store_obj_pkt_t *l_data_out = (dap_store_obj_pkt_t *)l_list_out->data; + dap_store_obj_pkt_t *l_data_out = dap_store_packet_single(l_obj); dap_store_obj_free(l_obj, 1); dap_chain_t *l_chain = dap_chain_net_get_chain_by_name(l_net, "gdb"); dap_chain_id_t l_chain_id = l_chain ? l_chain->id : (dap_chain_id_t) {}; @@ -350,7 +349,7 @@ void dap_chain_net_sync_gdb_broadcast(void *a_arg, const char a_op_code, const c sizeof(dap_store_obj_pkt_t) + l_data_out->data_size); } pthread_rwlock_unlock(&PVT(l_net)->rwlock); - dap_list_free_full(l_list_out, free); + DAP_DELETE(l_data_out); } } @@ -364,16 +363,16 @@ void dap_chain_net_sync_gdb_broadcast(void *a_arg, const char a_op_code, const c * @param a_value * @param a_value_len */ -static void s_gbd_history_callback_notify (void * a_arg, const char a_op_code, const char * a_prefix, const char * a_group, +static void s_gbd_history_callback_notify (void * a_arg, const char a_op_code, const char * a_group, const char * a_key, const void * a_value, const size_t a_value_len) { if (!a_arg) { return; } - dap_chain_node_mempool_autoproc_notify(a_arg, a_op_code, a_prefix, a_group, a_key, a_value, a_value_len); - dap_chain_net_sync_gdb_broadcast(a_arg, a_op_code, a_prefix, a_group, a_key, a_value, a_value_len); + dap_chain_node_mempool_autoproc_notify(a_arg, a_op_code, a_group, a_key, a_value, a_value_len); + dap_chain_net_sync_gdb_broadcast(a_arg, a_op_code, a_group, a_key, a_value, a_value_len); if (s_srv_callback_notify) { - s_srv_callback_notify(a_arg, a_op_code, a_prefix, a_group, a_key, a_value, a_value_len); + s_srv_callback_notify(a_arg, a_op_code, a_group, a_key, a_value, a_value_len); } } @@ -445,9 +444,6 @@ static void s_node_link_callback_connected(dap_chain_node_client_t * a_node_clie { dap_chain_net_t * l_net = (dap_chain_net_t *) a_arg; dap_chain_net_pvt_t * l_net_pvt = PVT(l_net); - dap_chain_node_info_t * l_link_info = a_node_client->info; - - a_node_client->stream_worker = dap_client_get_stream_worker(a_node_client->client); if(a_node_client->stream_worker == NULL){ @@ -456,8 +452,7 @@ static void s_node_link_callback_connected(dap_chain_node_client_t * a_node_clie return; } - a_node_client->state = NODE_CLIENT_STATE_ESTABLISHED; - + a_node_client->resync_gdb = l_net_pvt->flags & F_DAP_CHAIN_NET_SYNC_FROM_ZERO; if( !a_node_client->is_reconnecting || s_debug_more ) log_it(L_NOTICE, "Established connection with %s."NODE_ADDR_FP_STR,l_net->pub.name, NODE_ADDR_FP_ARGS_S(a_node_client->remote_node_addr)); @@ -466,32 +461,6 @@ static void s_node_link_callback_connected(dap_chain_node_client_t * a_node_clie l_net_pvt->links_connected_count++; s_net_links_notify(l_net); - // If we're fist time here - initiate the GDB sync - if (! a_node_client->is_reconnecting){ - dap_stream_ch_chain_sync_request_t l_sync_gdb = {}; - // Get last timestamp in log if wasn't SYNC_FROM_ZERO flag - if (! (l_net_pvt->flags & F_DAP_CHAIN_NET_SYNC_FROM_ZERO) ) - l_sync_gdb.id_start = (uint64_t) dap_db_get_last_id_remote(a_node_client->remote_node_addr.uint64); - l_sync_gdb.node_addr.uint64 = dap_chain_net_get_cur_addr_int(l_net); - log_it(L_DEBUG, "Prepared request to gdb sync from %"DAP_UINT64_FORMAT_U" to %"DAP_UINT64_FORMAT_U"", l_sync_gdb.id_start, l_sync_gdb.id_end?l_sync_gdb.id_end:-1 ); - // find dap_chain_id_t - dap_chain_t *l_chain = l_net->pub.chains; - dap_chain_id_t l_chain_id = l_chain ? l_chain->id : (dap_chain_id_t ) {0}; - - a_node_client->ch_chain = dap_client_get_stream_ch_unsafe(a_node_client->client,dap_stream_ch_chain_get_id() ); - if (a_node_client->ch_chain) - a_node_client->ch_chain_uuid = a_node_client->ch_chain->uuid; - - a_node_client->ch_chain_net = dap_client_get_stream_ch_unsafe(a_node_client->client,dap_stream_ch_chain_get_id() ); - if(a_node_client->ch_chain_net) - a_node_client->ch_chain_net_uuid = a_node_client->ch_chain_net->uuid; - - dap_stream_ch_chain_pkt_write_unsafe( a_node_client->ch_chain , - DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB_REQ, l_net->pub.id.uint64, - l_chain_id.uint64, l_net->pub.cell_id.uint64, &l_sync_gdb, sizeof(l_sync_gdb)); - } - a_node_client->is_reconnecting = false; - if(l_net_pvt->state == NET_STATE_LINKS_CONNECTING ){ l_net_pvt->state = NET_STATE_LINKS_ESTABLISHED; dap_proc_queue_add_callback_inter(a_node_client->stream_worker->worker->proc_queue_input,s_net_states_proc,l_net ); @@ -1106,9 +1075,6 @@ int dap_chain_net_init() "net -net <chain net name> ledger reload\n" "\tPurge the cache of chain net ledger and recalculate it from chain file\n" ); s_seed_mode = dap_config_get_item_bool_default(g_config,"general","seed_mode",false); - dap_chain_global_db_add_history_group_prefix("global", GROUP_LOCAL_HISTORY); - - dap_chain_global_db_add_history_callback_notify("global", s_gbd_history_callback_notify, NULL ); // maximum number of connections to other nodes s_max_links_count = dap_config_get_item_int32_default(g_config, "general", "max_links", s_max_links_count); @@ -1216,7 +1182,7 @@ static int s_cli_net( int argc, char **argv, void *arg_func, char **a_str_reply) // command 'list' const char * l_list_cmd = NULL; - if(dap_chain_node_cli_find_option_val(argv, arg_index, argc, "list", &l_list_cmd) != 0) { + if(dap_chain_node_cli_find_option_val(argv, arg_index, argc, "list", &l_list_cmd) != 0 ) { dap_string_t *l_string_ret = dap_string_new(""); if (dap_strcmp(l_list_cmd,"chains")==0){ const char * l_net_str = NULL; @@ -1630,13 +1596,13 @@ int s_net_load(const char * a_net_name, uint16_t a_acl_idx) l_net->pub.gdb_groups_prefix = dap_strdup ( dap_config_get_item_str_default(l_cfg , "general" , "gdb_groups_prefix", dap_config_get_item_str(l_cfg , "general" , "name" ) ) ); - dap_chain_global_db_add_history_group_prefix( l_net->pub.gdb_groups_prefix, GROUP_LOCAL_HISTORY); - dap_chain_global_db_add_history_callback_notify(l_net->pub.gdb_groups_prefix, s_gbd_history_callback_notify, l_net ); + dap_chain_global_db_add_sync_group("global", s_gbd_history_callback_notify, l_net); + dap_chain_global_db_add_sync_group(l_net->pub.gdb_groups_prefix, s_gbd_history_callback_notify, l_net); l_net->pub.gdb_nodes = dap_strdup_printf("%s.nodes",l_net->pub.gdb_groups_prefix); l_net->pub.gdb_nodes_aliases = dap_strdup_printf("%s.nodes.aliases",l_net->pub.gdb_groups_prefix); - // for sync special groups - nodes + // nodes for special sync char **l_gdb_sync_nodes_addrs = dap_config_get_array_str(l_cfg, "general", "gdb_sync_nodes_addrs", &l_net_pvt->gdb_sync_nodes_addrs_count); if(l_gdb_sync_nodes_addrs && l_net_pvt->gdb_sync_nodes_addrs_count > 0) { @@ -1646,37 +1612,13 @@ int s_net_load(const char * a_net_name, uint16_t a_acl_idx) dap_chain_node_addr_from_str(l_net_pvt->gdb_sync_nodes_addrs + i, l_gdb_sync_nodes_addrs[i]); } } - // for sync special groups - groups - char **l_gdb_sync_groups = dap_config_get_array_str(l_cfg, "general", "gdb_sync_groups", &l_net_pvt->gdb_sync_groups_count); - if(l_gdb_sync_groups && l_net_pvt->gdb_sync_groups_count > 0) { - l_net_pvt->gdb_sync_groups = (char **) DAP_NEW_SIZE(char**, sizeof(char*)*l_net_pvt->gdb_sync_groups_count); - for(uint16_t i = 0; i < l_net_pvt->gdb_sync_groups_count; i++) { - l_net_pvt->gdb_sync_groups[i] = dap_strdup(l_gdb_sync_groups[i]); - // added group to history log - dap_list_t *l_groups0 = dap_chain_global_db_driver_get_groups_by_mask(l_net_pvt->gdb_sync_groups[i]); - dap_list_t *l_groups = l_groups0; - while(l_groups) { - char *l_group_name = l_groups->data; - // do not use groups with names like *.del - if(dap_fnmatch("*.del", l_group_name, 0)) { - const char *l_history_group = dap_chain_global_db_add_history_extra_group(l_group_name, - l_net_pvt->gdb_sync_nodes_addrs, - &l_net_pvt->gdb_sync_nodes_addrs_count); - dap_chain_global_db_add_history_extra_group_callback_notify(l_group_name, - s_gbd_history_callback_notify, l_net); - // create history for group - if(dap_db_log_get_group_history_last_id(l_history_group) <= 0) { - size_t l_data_size_out = 0; - dap_store_obj_t *l_obj = dap_chain_global_db_obj_gr_get(NULL, &l_data_size_out, l_group_name); - if(l_obj && l_data_size_out > 0) { - dap_db_history_add('a', l_obj, l_data_size_out, l_history_group); - dap_store_obj_free(l_obj, l_data_size_out); - } - } - } - l_groups = dap_list_next(l_groups); - } - dap_list_free_full(l_groups0, (dap_callback_destroyed_t)free); + // groups for special sync + uint16_t l_gdb_sync_groups_count; + char **l_gdb_sync_groups = dap_config_get_array_str(l_cfg, "general", "gdb_sync_groups", &l_gdb_sync_groups_count); + if (l_gdb_sync_groups && l_gdb_sync_groups_count > 0) { + for(uint16_t i = 0; i < l_gdb_sync_groups_count; i++) { + // add group to special sync + dap_chain_global_db_add_sync_extra_group(l_gdb_sync_groups[i], s_gbd_history_callback_notify, l_net); } } @@ -2383,7 +2325,7 @@ dap_list_t* dap_chain_net_get_node_list(dap_chain_net_t * l_net) * @param a_net * @param a_flag_sync_from_zero */ -void dap_chain_net_set_flag_sync_from_zero( dap_chain_net_t * a_net, bool a_flag_sync_from_zero) +void dap_chain_net_set_flag_sync_from_zero(dap_chain_net_t * a_net, bool a_flag_sync_from_zero) { if( a_flag_sync_from_zero) PVT(a_net)->flags |= F_DAP_CHAIN_NET_SYNC_FROM_ZERO; @@ -2519,18 +2461,16 @@ dap_chain_datum_tx_t * dap_chain_net_get_tx_by_hash(dap_chain_net_t * a_net, dap * @param a_node_addr * @return */ -dap_list_t * dap_chain_net_get_add_gdb_group(dap_chain_net_t * a_net, dap_chain_node_addr_t a_node_addr) +bool dap_chain_net_get_add_gdb_group(dap_chain_net_t *a_net, dap_chain_node_addr_t a_node_addr) { - dap_list_t *l_list_groups = NULL; if(!a_net || !PVT(a_net) || !PVT(a_net)->gdb_sync_nodes_addrs) - return NULL; + return false; for(uint16_t i = 0; i < PVT(a_net)->gdb_sync_nodes_addrs_count; i++) { if(a_node_addr.uint64 == PVT(a_net)->gdb_sync_nodes_addrs[i].uint64) { - for(uint16_t j = 0; j < PVT(a_net)->gdb_sync_groups_count; j++) - l_list_groups = dap_list_append(l_list_groups, PVT(a_net)->gdb_sync_groups[j]); + return true; } } - return l_list_groups; + return false; } /** diff --git a/modules/net/dap_chain_node.c b/modules/net/dap_chain_node.c index 5f9ac6fcd097343d087d8fd996dec54b8d70977a..817455ff9e922ce73b65281a17ff5d93668e425a 100644 --- a/modules/net/dap_chain_node.c +++ b/modules/net/dap_chain_node.c @@ -323,10 +323,9 @@ void dap_chain_node_mempool_autoproc_deinit() s_mempool_auto = false; } -void dap_chain_node_mempool_autoproc_notify(void *a_arg, const char a_op_code, const char *a_prefix, const char *a_group, +void dap_chain_node_mempool_autoproc_notify(void *a_arg, const char a_op_code, const char *a_group, const char *a_key, const void *a_value, const size_t a_value_len) { - UNUSED(a_prefix); UNUSED(a_value_len); if (!a_arg || !a_value || !s_mempool_auto || a_op_code != 'a') { return; diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c index 4453a28d30dd2c478a551d7d2d64653ec8b9dd0a..bdb5a2e59ddebf06ae084f86fdf55b2d4cbc4339 100644 --- a/modules/net/dap_chain_node_cli_cmd.c +++ b/modules/net/dap_chain_node_cli_cmd.c @@ -1053,7 +1053,7 @@ int com_node(int a_argc, char ** a_argv, void *arg_func, char **a_str_reply) dap_stream_ch_chain_sync_request_t l_sync_request = { { 0 } }; dap_stream_ch_t * l_ch_chain = dap_client_get_stream_ch_unsafe(l_node_client->client, dap_stream_ch_chain_get_id()); // fill begin id - l_sync_request.id_start = dap_db_get_last_id_remote(l_remote_node_info->hdr.address.uint64); + l_sync_request.id_start = 1; // fill current node address l_sync_request.node_addr.uint64 = dap_chain_net_get_cur_addr_int(l_net); diff --git a/modules/net/dap_chain_node_client.c b/modules/net/dap_chain_node_client.c index 85116dd2e4034a69dc1c5a91613b736b0b4eac21..59e71bf6363bbf1319e2c8cdc7c6cdf70aa150e7 100644 --- a/modules/net/dap_chain_node_client.c +++ b/modules/net/dap_chain_node_client.c @@ -84,11 +84,10 @@ typedef struct dap_chain_node_client_handle { static dap_chain_node_client_handle_t * s_clients = NULL; - //static int listen_port_tcp = 8079; static void s_stage_connected_callback(dap_client_t *a_client, void *a_arg); -static bool s_timer_update_states_callback(void * a_arg ); +static bool s_timer_update_states_callback(void *a_arg); static void s_ch_chain_callback_notify_packet_out(dap_stream_ch_chain_t*, uint8_t a_pkt_type, dap_stream_ch_chain_pkt_t *a_pkt, size_t a_pkt_data_size, @@ -165,7 +164,9 @@ static void s_stage_status_error_callback(dap_client_t *a_client, void *a_arg) pthread_mutex_unlock(&l_node_client->wait_mutex); l_node_client->esocket_uuid = 0; - if (l_node_client->keep_connection) { + if (l_node_client->callbacks.disconnected) { + l_node_client->callbacks.disconnected(l_node_client, l_node_client->callbacks_arg); + } else if (l_node_client->keep_connection) { dap_events_socket_uuid_t *l_uuid = DAP_NEW(dap_events_socket_uuid_t); memcpy(l_uuid, &l_node_client->uuid, sizeof(dap_events_socket_uuid_t)); dap_timerfd_start_on_worker(l_node_client->stream_worker? l_node_client->stream_worker->worker: dap_events_worker_get_auto(),s_timer_update_states*1000,s_timer_update_states_callback, l_uuid); @@ -177,12 +178,19 @@ static void s_stage_status_error_callback(dap_client_t *a_client, void *a_arg) l_node_client->callbacks.error(l_node_client, EINVAL,l_node_client->callbacks_arg ); } +static void s_node_client_connected_synchro_start_callback(dap_worker_t *a_worker, void *a_arg) +{ + UNUSED(a_worker); + if (s_timer_update_states_callback(a_arg)) + DAP_DELETE(a_arg); +} + /** * @brief s_timer_update_states_callback * @param a_arg * @return */ -static bool s_timer_update_states_callback(void * a_arg ) +static bool s_timer_update_states_callback(void *a_arg) { dap_chain_node_client_handle_t *l_client_found = NULL; dap_events_socket_uuid_t *l_uuid = (dap_events_socket_uuid_t *)a_arg; @@ -201,7 +209,7 @@ static bool s_timer_update_states_callback(void * a_arg ) dap_events_socket_t * l_es = NULL; dap_events_socket_uuid_t l_es_uuid = l_me->esocket_uuid; // check if esocket still in worker - if( (l_es = dap_worker_esocket_find_uuid(l_worker, l_es_uuid)) != NULL ){ + if( (l_es = dap_worker_esocket_find_uuid(l_worker, l_es_uuid)) != NULL ) { dap_client_t * l_client = dap_client_from_esocket(l_es); if (l_client ) { dap_chain_node_client_t * l_node_client = (dap_chain_node_client_t*) l_client->_inheritor; @@ -212,27 +220,21 @@ static bool s_timer_update_states_callback(void * a_arg ) assert(l_ch_chain); dap_chain_net_t * l_net = l_node_client->net; assert(l_net); - // If we do nothing - init sync process if (l_ch_chain->state == CHAIN_STATE_IDLE ||l_ch_chain->state == CHAIN_STATE_SYNC_ALL ){ + log_it(L_INFO, "Start synchronization process with "NODE_ADDR_FP_STR, NODE_ADDR_FP_ARGS_S(l_node_client->remote_node_addr)); dap_stream_ch_chain_sync_request_t l_sync_gdb = {}; - l_sync_gdb.id_start = (uint64_t) dap_db_get_last_id_remote(l_node_client->remote_node_addr.uint64); l_sync_gdb.node_addr.uint64 = dap_chain_net_get_cur_addr_int(l_net); - log_it(L_DEBUG, "Prepared request to gdb sync from %"DAP_UINT64_FORMAT_U" to %"DAP_UINT64_FORMAT_U"", l_sync_gdb.id_start, - l_sync_gdb.id_end?l_sync_gdb.id_end:-1 ); - // find dap_chain_id_t - dap_chain_t *l_chain = l_net->pub.chains; - dap_chain_id_t l_chain_id = l_chain ? l_chain->id : (dap_chain_id_t ) {0}; - dap_stream_ch_chain_pkt_write_unsafe( l_node_client->ch_chain , - DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB_REQ, l_net->pub.id.uint64, - l_chain_id.uint64, l_net->pub.cell_id.uint64, - &l_sync_gdb, sizeof(l_sync_gdb)); + dap_stream_ch_chain_pkt_write_unsafe(l_node_client->ch_chain, DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB_REQ, + l_net->pub.id.uint64, 0, l_net->pub.cell_id.uint64, + &l_sync_gdb, sizeof(l_sync_gdb)); } return true; } } } } + // if we not returned yet l_me->state = NODE_CLIENT_STATE_DISCONNECTED; if (l_me->keep_connection) { @@ -277,8 +279,11 @@ static void s_stage_connected_callback(dap_client_t *a_client, void *a_arg) l_node_client->stream_worker = l_stream->stream_worker; if (l_node_client->keep_connection) { dap_events_socket_uuid_t *l_uuid = DAP_NEW(dap_events_socket_uuid_t); - memcpy(l_uuid, &l_node_client->uuid, sizeof(dap_events_socket_uuid_t)); - dap_timerfd_start_on_worker(l_stream->esocket->worker,s_timer_update_states*1000,s_timer_update_states_callback, l_uuid); + DAP_DUP(l_uuid, &l_node_client->uuid); + dap_worker_exec_callback_on(l_stream->esocket->worker, s_node_client_connected_synchro_start_callback, l_uuid); + dap_events_socket_uuid_t *l_uuid_timer = DAP_NEW(dap_events_socket_uuid_t); + DAP_DUP(l_uuid_timer, &l_node_client->uuid); + dap_timerfd_start_on_worker(l_stream->esocket->worker, s_timer_update_states * 1000, s_timer_update_states_callback, l_uuid_timer); } } #ifndef _WIN32 @@ -595,13 +600,14 @@ dap_chain_node_client_t* dap_chain_node_client_create_n_connect(dap_chain_net_t return NULL; } dap_chain_node_client_t *l_node_client = DAP_NEW_Z(dap_chain_node_client_t); + l_node_client->state = NODE_CLIENT_STATE_DISCONNECTED; l_node_client->callbacks_arg = a_callback_arg; if(a_callbacks) memcpy(&l_node_client->callbacks,a_callbacks,sizeof (*a_callbacks)); l_node_client->info = a_node_info; + l_node_client->uuid = dap_uuid_generate_uint64(); l_node_client->net = a_net; - l_node_client->uuid = dap_uuid_generate_uint128(); dap_chain_node_client_handle_t * l_client_handle = DAP_NEW_Z(dap_chain_node_client_handle_t); l_client_handle->uuid = l_node_client->uuid; l_client_handle->client = l_node_client; @@ -655,9 +661,6 @@ static bool dap_chain_node_client_connect_internal(dap_chain_node_client_t *a_no return false; } dap_client_set_uplink_unsafe(a_node_client->client, strdup(host), a_node_client->info->hdr.ext_port); -// dap_client_stage_t a_stage_target = STAGE_ENC_INIT; -// dap_client_stage_t l_stage_target = STAGE_STREAM_STREAMING; - a_node_client->state = NODE_CLIENT_STATE_CONNECTING ; // ref pvt client //dap_client_pvt_ref(DAP_CLIENT_PVT(a_node_client->client)); @@ -832,6 +835,7 @@ int dap_chain_node_client_set_callbacks(dap_client_t *a_client, uint8_t a_ch_id) l_ch_chain->callback_notify_packet_out = s_ch_chain_callback_notify_packet_out; l_ch_chain->callback_notify_packet_in = s_ch_chain_callback_notify_packet_in; l_ch_chain->callback_notify_arg = l_node_client; + l_node_client->ch_chain = l_ch; memcpy(&l_node_client->ch_chain_uuid, &l_ch->uuid, sizeof(dap_stream_ch_uuid_t)); } // N @@ -839,6 +843,7 @@ int dap_chain_node_client_set_callbacks(dap_client_t *a_client, uint8_t a_ch_id) dap_stream_ch_chain_net_t *l_ch_chain = DAP_STREAM_CH_CHAIN_NET(l_ch); l_ch_chain->notify_callback = s_ch_chain_callback_notify_packet_in2; l_ch_chain->notify_callback_arg = l_node_client; + l_node_client->ch_chain_net = l_ch; memcpy(&l_node_client->ch_chain_net_uuid, &l_ch->uuid, sizeof(dap_stream_ch_uuid_t)); } // R diff --git a/modules/net/include/dap_chain_net.h b/modules/net/include/dap_chain_net.h index 7f59409edf8f0064568b68497f8dcbe2d7fa4d68..ad6475656fd92064aedf39b4d6575657eeec38b8 100644 --- a/modules/net/include/dap_chain_net.h +++ b/modules/net/include/dap_chain_net.h @@ -115,7 +115,7 @@ static inline const char * dap_chain_net_state_to_str(dap_chain_net_state_t a_st void dap_chain_net_delete( dap_chain_net_t * a_net); void dap_chain_net_proc_mempool (dap_chain_net_t * a_net); -void dap_chain_net_set_flag_sync_from_zero( dap_chain_net_t * a_net, bool a_flag_sync_from_zero); +void dap_chain_net_set_flag_sync_from_zero(dap_chain_net_t * a_net, bool a_flag_sync_from_zero); bool dap_chain_net_get_flag_sync_from_zero( dap_chain_net_t * a_net); @@ -170,12 +170,12 @@ DAP_STATIC_INLINE char * dap_chain_net_get_gdb_group_mempool(dap_chain_t * l_cha dap_chain_t * dap_chain_net_get_chain_by_chain_type(dap_chain_net_t * l_net, dap_chain_type_t a_datum_type); char * dap_chain_net_get_gdb_group_mempool_by_chain_type(dap_chain_net_t * l_net, dap_chain_type_t a_datum_type); dap_chain_net_t **dap_chain_net_list(uint16_t *a_size); -dap_list_t * dap_chain_net_get_add_gdb_group(dap_chain_net_t * a_net, dap_chain_node_addr_t a_node_addr); +bool dap_chain_net_get_add_gdb_group(dap_chain_net_t *a_net, dap_chain_node_addr_t a_node_addr); int dap_chain_net_verify_datum_for_add(dap_chain_net_t *a_net, dap_chain_datum_t * a_datum ); void dap_chain_net_dump_datum(dap_string_t * a_str_out, dap_chain_datum_t * a_datum, const char *a_hash_out_type); void dap_chain_net_set_srv_callback_notify(dap_global_db_obj_callback_notify_t a_callback); -void dap_chain_net_sync_gdb_broadcast(void *a_arg, const char a_op_code, const char *a_prefix, const char *a_group, +void dap_chain_net_sync_gdb_broadcast(void *a_arg, const char a_op_code, const char *a_group, const char *a_key, const void *a_value, const size_t a_value_len); struct dap_chain_node_client * dap_chain_net_client_create_n_connect( dap_chain_net_t * a_net, struct dap_chain_node_info *a_link_info); diff --git a/modules/net/include/dap_chain_node.h b/modules/net/include/dap_chain_node.h index 4bfc7f23c1f150d29d4afb76aaa283bb2131f1f9..9d84beabcc2a289a3024f185ffea98de15c43d8a 100644 --- a/modules/net/include/dap_chain_node.h +++ b/modules/net/include/dap_chain_node.h @@ -147,6 +147,6 @@ inline static char* dap_chain_node_addr_to_hash_str(dap_chain_node_addr_t *addre bool dap_chain_node_mempool_process(dap_chain_t *a_chain, dap_chain_node_role_t a_role, dap_chain_datum_t *a_datum); bool dap_chain_node_mempool_autoproc_init(); void dap_chain_node_mempool_autoproc_deinit(); -void dap_chain_node_mempool_autoproc_notify(void *a_arg, const char a_op_code, const char *a_prefix, const char *a_group, +void dap_chain_node_mempool_autoproc_notify(void *a_arg, const char a_op_code, const char *a_group, const char *a_key, const void *a_value, const size_t a_value_len); diff --git a/modules/net/include/dap_chain_node_client.h b/modules/net/include/dap_chain_node_client.h index ca18108812d5b57e3f4f9e0f030ea68b80273ea2..92a7ba56d3479fbf01a31fe3d3ea3f0b78142ec2 100644 --- a/modules/net/include/dap_chain_node_client.h +++ b/modules/net/include/dap_chain_node_client.h @@ -66,10 +66,10 @@ typedef struct dap_chain_node_client_callbacks{ // state for a client connection typedef struct dap_chain_node_client { dap_chain_node_client_state_t state; - uint64_t uuid; - bool sync_gdb; - bool sync_chains; + dap_events_socket_uuid_t uuid; + bool resync_gdb; + bool resync_chains; dap_chain_cell_id_t cell_id; @@ -119,6 +119,7 @@ typedef struct dap_chain_node_client { dap_chain_node_client_callbacks_t callbacks; void * callbacks_arg; } dap_chain_node_client_t; + #define DAP_CHAIN_NODE_CLIENT(a) (a ? (dap_chain_node_client_t *) (a)->_inheritor : NULL) int dap_chain_node_client_init(void); diff --git a/modules/net/srv/dap_chain_net_srv_order.c b/modules/net/srv/dap_chain_net_srv_order.c index 1c06eaf7e86da81d408533b846161ed6fb4c7c30..9e1f98e2e0ee816778c967e791ac86dd599eefd2 100644 --- a/modules/net/srv/dap_chain_net_srv_order.c +++ b/modules/net/srv/dap_chain_net_srv_order.c @@ -63,7 +63,7 @@ char *s_server_continents[]={ "Antarctica" }; -static void s_srv_order_callback_notify(void *a_arg, const char a_op_code, const char *a_prefix, const char *a_group, +static void s_srv_order_callback_notify(void *a_arg, const char a_op_code, const char *a_group, const char *a_key, const void *a_value, const size_t a_value_len); /** @@ -520,10 +520,9 @@ void dap_chain_net_srv_order_dump_to_string(dap_chain_net_srv_order_t *a_order,d } } -static void s_srv_order_callback_notify(void *a_arg, const char a_op_code, const char *a_prefix, const char *a_group, +static void s_srv_order_callback_notify(void *a_arg, const char a_op_code, const char *a_group, const char *a_key, const void *a_value, const size_t a_value_len) { - UNUSED(a_prefix); UNUSED(a_value_len); if (!a_arg || !a_value || a_op_code != 'a' || !dap_config_get_item_bool_default(g_config, "srv", "order_signed_only", false)) { return;