From afda7c4de85a94560a9be0c5097efbf34db78117 Mon Sep 17 00:00:00 2001 From: Roman Khlopkov <roman.khlopkov@demlabs.net> Date: Fri, 22 Mar 2024 12:38:17 +0000 Subject: [PATCH] feature-10492-atomic --- modules/chain/dap_chain.c | 5 +- modules/chain/dap_chain_cell.c | 6 +- modules/chain/dap_chain_ch.c | 743 ++++++++++++------ modules/chain/dap_chain_ch_pkt.c | 13 +- modules/chain/include/dap_chain.h | 36 +- modules/chain/include/dap_chain_ch.h | 45 +- modules/chain/include/dap_chain_ch_pkt.h | 104 +-- .../chain-net/dap_stream_ch_chain_net.c | 4 +- modules/net/dap_chain_net.c | 137 +++- modules/net/dap_chain_node_cli_cmd.c | 8 +- modules/net/dap_chain_node_cli_cmd_tx.c | 18 +- modules/net/dap_chain_node_client.c | 42 +- modules/type/blocks/dap_chain_cs_blocks.c | 240 ++---- modules/type/dag/dap_chain_cs_dag.c | 355 +++------ modules/type/none/dap_chain_cs_none.c | 169 +--- 15 files changed, 1009 insertions(+), 916 deletions(-) diff --git a/modules/chain/dap_chain.c b/modules/chain/dap_chain.c index bf022e9559..70870d8821 100644 --- a/modules/chain/dap_chain.c +++ b/modules/chain/dap_chain.c @@ -683,8 +683,7 @@ void dap_chain_add_callback_notify(dap_chain_t * a_chain, dap_chain_callback_not bool dap_chain_get_atom_last_hash(dap_chain_t *a_chain, dap_hash_fast_t *a_atom_hash, dap_chain_cell_id_t a_cell_id) { dap_chain_atom_iter_t *l_iter = a_chain->callback_atom_iter_create(a_chain, a_cell_id, false); - dap_chain_atom_ptr_t *l_ptr_list = a_chain->callback_atom_iter_get_lasts(l_iter, NULL, NULL); - DAP_DEL_Z(l_ptr_list); + a_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_LAST, NULL); *a_atom_hash = l_iter->cur_hash ? *l_iter->cur_hash : (dap_hash_fast_t){0}; bool l_ret = l_iter->cur_hash; a_chain->callback_atom_iter_delete(l_iter); @@ -722,7 +721,7 @@ ssize_t dap_chain_atom_save(dap_chain_cell_t *a_chain_cell, const uint8_t *a_ato dap_chain_ch_pkt_t *l_pkt = dap_chain_ch_pkt_new(l_chain->net_id.uint64, l_chain->id.uint64, a_chain_cell->id.uint64, a_atom, a_atom_size); if (l_pkt) { - dap_gossip_msg_issue(l_net_cluster, DAP_STREAM_CH_CHAIN_ID, l_pkt, l_pkt_size, a_new_atom_hash); + dap_gossip_msg_issue(l_net_cluster, DAP_CHAIN_CH_ID, l_pkt, l_pkt_size, a_new_atom_hash); DAP_DELETE(l_pkt); } } diff --git a/modules/chain/dap_chain_cell.c b/modules/chain/dap_chain_cell.c index 9d72785363..8149da8d74 100644 --- a/modules/chain/dap_chain_cell.c +++ b/modules/chain/dap_chain_cell.c @@ -347,12 +347,12 @@ ssize_t dap_chain_cell_file_append(dap_chain_cell_t *a_cell, const void *a_atom, pthread_rwlock_unlock(&a_cell->storage_rwlock); return -4; } - dap_chain_atom_iter_t *l_atom_iter = a_cell->chain->callback_atom_iter_create(a_cell->chain, a_cell->id, 0); + dap_chain_atom_iter_t *l_atom_iter = a_cell->chain->callback_atom_iter_create(a_cell->chain, a_cell->id, NULL); dap_chain_atom_ptr_t l_atom; uint64_t l_atom_size = 0; - for (l_atom = a_cell->chain->callback_atom_iter_get_first(l_atom_iter, &l_atom_size); + for (l_atom = a_cell->chain->callback_atom_iter_get(l_atom_iter, DAP_CHAIN_ITER_OP_FIRST, &l_atom_size); l_atom && l_atom_size; - l_atom = a_cell->chain->callback_atom_iter_get_next(l_atom_iter, &l_atom_size)) + l_atom = a_cell->chain->callback_atom_iter_get(l_atom_iter, DAP_CHAIN_ITER_OP_NEXT, &l_atom_size)) { if (s_file_atom_add(a_cell, l_atom, l_atom_size)) { l_err = true; diff --git a/modules/chain/dap_chain_ch.c b/modules/chain/dap_chain_ch.c index 4187dec847..5276e274ac 100644 --- a/modules/chain/dap_chain_ch.c +++ b/modules/chain/dap_chain_ch.c @@ -95,15 +95,34 @@ struct sync_request }; }; +enum sync_context_state { + SYNC_STATE_IDLE, + SYNC_STATE_READY, + SYNC_STATE_BUSY, + SYNC_STATE_OVER +}; + +struct sync_context { + atomic_uint_fast64_t allowed_num; + atomic_uint_fast16_t state; + dap_chain_atom_iter_t *iter; + dap_stream_node_addr_t addr; + dap_chain_net_id_t net_id; + dap_chain_id_t chain_id; + dap_chain_cell_id_t cell_id; + uint64_t num_last; + dap_time_t last_activity; +}; + static void s_ch_chain_go_idle(dap_chain_ch_t *a_ch_chain); -static inline bool s_ch_chain_get_idle(dap_chain_ch_t *a_ch_chain) { return a_ch_chain->state == CHAIN_STATE_IDLE; } +static inline bool s_ch_chain_get_idle(dap_chain_ch_t *a_ch_chain) { return a_ch_chain->state == DAP_CHAIN_CH_STATE_IDLE; } static void s_stream_ch_new(dap_stream_ch_t* a_ch, void* a_arg); static void s_stream_ch_delete(dap_stream_ch_t* a_ch, void* a_arg); static void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg); static bool s_stream_ch_packet_out(dap_stream_ch_t* a_ch, void* a_arg); static void s_stream_ch_io_complete(dap_events_socket_t *a_es, void *a_arg); -static void s_stream_ch_write_error_unsafe(dap_stream_ch_t *a_ch, uint64_t a_net_id, uint64_t a_chain_id, uint64_t a_cell_id, const char * a_err_string); +static void s_stream_ch_write_error_unsafe(dap_stream_ch_t *a_ch, uint64_t a_net_id, uint64_t a_chain_id, uint64_t a_cell_id, dap_chain_ch_error_type_t a_error); static bool s_sync_out_chains_proc_callback(void *a_arg); static void s_sync_out_chains_last_worker_callback(dap_worker_t *a_worker, void *a_arg); @@ -119,14 +138,20 @@ static bool s_gdb_in_pkt_proc_set_raw_callback(dap_global_db_instance_t *a_dbi, const size_t a_values_total, const size_t a_values_count, dap_store_obj_t *a_values, void *a_arg); static void s_gdb_in_pkt_error_worker_callback(dap_worker_t *a_thread, void *a_arg); -static void s_free_log_list_gdb ( dap_chain_ch_t * a_ch_chain); static void s_stream_ch_chain_pkt_write(dap_stream_ch_t *a_ch, uint8_t a_type, uint64_t a_net_id, uint64_t a_chain_id, uint64_t a_cell_id, const void * a_data, size_t a_data_size); static void s_gossip_payload_callback(void *a_payload, size_t a_payload_size, dap_stream_node_addr_t a_sender_addr); +static bool s_chain_iter_callback(void *a_arg); +static bool s_chain_iter_delete_callback(void *a_arg); +static bool s_sync_timer_callback(void *a_arg); + +static bool s_debug_more = false; +static uint32_t s_sync_timeout = 30; +static uint32_t s_sync_packets_per_thread_call = 10; +static uint32_t s_sync_ack_window_size = 100; // atoms -static bool s_debug_more=false; static uint_fast16_t s_update_pack_size=100; // Number of hashes packed into the one packet static uint_fast16_t s_skip_in_reactor_count=50; // Number of hashes packed to skip in one reactor loop callback out packet @@ -139,6 +164,30 @@ static dap_memstat_rec_t s_memstat [MEMSTAT$K_NR] = { #endif +static const char *s_error_type_to_string(dap_chain_ch_error_type_t a_error) +{ + switch (a_error) { + case DAP_CHAIN_CH_ERROR_SYNC_REQUEST_ALREADY_IN_PROCESS: + return "SYNC_REQUEST_ALREADY_IN_PROCESS"; + case DAP_CHAIN_CH_ERROR_INCORRECT_SYNC_SEQUENCE: + return "INCORRECT_SYNC_SEQUENCE"; + case DAP_CHAIN_CH_ERROR_CHAIN_PKT_DATA_SIZE: + return "IVALID_PACKET_SIZE"; + case DAP_CHAIN_CH_ERROR_NET_INVALID_ID: + return "INVALID_NET_ID"; + case DAP_CHAIN_CH_ERROR_CHAIN_NOT_FOUND: + return "CHAIN_NOT_FOUND"; + case DAP_CHAIN_CH_ERROR_ATOM_NOT_FOUND: + return "ATOM_NOT_FOUND"; + case DAP_CHAIN_CH_ERROR_UNKNOWN_CHAIN_PKT_TYPE: + return "UNKNOWN_CHAIN_PACKET_TYPE"; + case DAP_CHAIN_CH_ERROR_GLOBAL_DB_INTERNAL_NOT_SAVED: + return "GLOBAL_DB_INTERNAL_SAVING_ERROR"; + default: + return "UNKNOWN_ERROR"; + } +} + /** * @brief dap_chain_ch_init * @return @@ -146,15 +195,17 @@ static dap_memstat_rec_t s_memstat [MEMSTAT$K_NR] = { int dap_chain_ch_init() { log_it(L_NOTICE, "Chains and global db exchange channel initialized"); - dap_stream_ch_proc_add(DAP_STREAM_CH_CHAIN_ID, s_stream_ch_new, s_stream_ch_delete, s_stream_ch_packet_in, + dap_stream_ch_proc_add(DAP_CHAIN_CH_ID, s_stream_ch_new, s_stream_ch_delete, s_stream_ch_packet_in, s_stream_ch_packet_out); - s_debug_more = dap_config_get_item_bool_default(g_config,"stream_ch_chain","debug_more",false); - s_update_pack_size = dap_config_get_item_int16_default(g_config,"stream_ch_chain","update_pack_size",100); + s_sync_timeout = dap_config_get_item_uint32_default(g_config, "chain", "sync_timeout", s_sync_timeout); + s_sync_ack_window_size = dap_config_get_item_uint32_default(g_config, "chain", "sync_ack_window_size", s_sync_ack_window_size); + s_sync_packets_per_thread_call = dap_config_get_item_int16_default(g_config, "chain", "pack_size", s_sync_packets_per_thread_call); + s_debug_more = dap_config_get_item_bool_default(g_config, "chain", "debug_more", false); #ifdef DAP_SYS_DEBUG for (int i = 0; i < MEMSTAT$K_NR; i++) dap_memstat_reg(&s_memstat[i]); #endif - assert(!dap_stream_ch_gossip_callback_add(DAP_STREAM_CH_CHAIN_ID, s_gossip_payload_callback)); + assert(!dap_stream_ch_gossip_callback_add(DAP_CHAIN_CH_ID, s_gossip_payload_callback)); return 0; } @@ -178,7 +229,7 @@ void s_stream_ch_new(dap_stream_ch_t* a_ch, void* a_arg) log_it(L_CRITICAL, "Memory allocation error"); return; }; - dap_chain_ch_t *l_ch_chain = DAP_STREAM_CH_CHAIN(a_ch); + dap_chain_ch_t *l_ch_chain = DAP_CHAIN_CH(a_ch); l_ch_chain->_inheritor = a_ch; a_ch->stream->esocket->callbacks.write_finished_callback = s_stream_ch_io_complete; @@ -196,9 +247,9 @@ void s_stream_ch_new(dap_stream_ch_t* a_ch, void* a_arg) static void s_stream_ch_delete(dap_stream_ch_t *a_ch, void *a_arg) { UNUSED(a_arg); - dap_chain_ch_t *l_ch_chain = DAP_STREAM_CH_CHAIN(a_ch); + dap_chain_ch_t *l_ch_chain = DAP_CHAIN_CH(a_ch); if (l_ch_chain->callback_notify_packet_out) - l_ch_chain->callback_notify_packet_out(l_ch_chain, DAP_STREAM_CH_CHAIN_PKT_TYPE_DELETE, NULL, 0, + l_ch_chain->callback_notify_packet_out(l_ch_chain, DAP_CHAIN_CH_PKT_TYPE_DELETE, NULL, 0, l_ch_chain->callback_notify_arg); s_ch_chain_go_idle(l_ch_chain); debug_if(s_debug_more, L_DEBUG, "[stm_ch_chain:%p] --- deleted chain:%p", a_ch, l_ch_chain); @@ -253,25 +304,25 @@ static void s_sync_out_chains_first_worker_callback(dap_worker_t *a_worker, void return; } - dap_chain_ch_t * l_ch_chain = DAP_STREAM_CH_CHAIN(l_ch); + dap_chain_ch_t * l_ch_chain = DAP_CHAIN_CH(l_ch); if (!l_ch_chain) { log_it(L_CRITICAL, "Channel without chain, dump it"); s_sync_request_delete(l_sync_request); return; } - if (l_ch_chain->state != CHAIN_STATE_UPDATE_CHAINS_REMOTE) { + if (l_ch_chain->state != DAP_CHAIN_CH_STATE_UPDATE_CHAINS_REMOTE) { log_it(L_INFO, "Timeout fired before we sent the reply"); s_sync_request_delete(l_sync_request); return; } - l_ch_chain->state = CHAIN_STATE_SYNC_CHAINS; + l_ch_chain->state = DAP_CHAIN_CH_STATE_SYNC_CHAINS; l_ch_chain->request_atom_iter = l_sync_request->chain.request_atom_iter; if (s_debug_more ) - log_it(L_INFO,"Out: DAP_STREAM_CH_CHAIN_PKT_TYPE_FIRST_CHAIN"); + log_it(L_INFO,"Out: DAP_CHAIN_CH_PKT_TYPE_FIRST_CHAIN"); - dap_chain_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_FIRST_CHAIN, + dap_chain_ch_pkt_write_unsafe(l_ch, DAP_CHAIN_CH_PKT_TYPE_FIRST_CHAIN, l_ch_chain->request_hdr.net_id.uint64, l_ch_chain->request_hdr.chain_id.uint64, l_ch_chain->request_hdr.cell_id.uint64, &g_node_addr, sizeof(dap_chain_node_addr_t)); DAP_DELETE(l_sync_request); @@ -293,7 +344,7 @@ static void s_sync_out_chains_last_worker_callback(dap_worker_t *a_worker, void return; } - dap_chain_ch_t * l_ch_chain = DAP_STREAM_CH_CHAIN(l_ch); + dap_chain_ch_t * l_ch_chain = DAP_CHAIN_CH(l_ch); if (!l_ch_chain) { log_it(L_CRITICAL, "Channel without chain, dump it"); s_sync_request_delete(l_sync_request); @@ -303,13 +354,13 @@ static void s_sync_out_chains_last_worker_callback(dap_worker_t *a_worker, void // last packet dap_chain_ch_sync_request_t l_request = {}; if (s_debug_more ) - log_it(L_INFO,"Out: DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_CHAINS"); - dap_chain_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_CHAINS, + log_it(L_INFO,"Out: DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAINS"); + dap_chain_ch_pkt_write_unsafe(l_ch, DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAINS, l_sync_request->request_hdr.net_id.uint64, l_sync_request->request_hdr.chain_id.uint64, l_sync_request->request_hdr.cell_id.uint64, &l_request, sizeof(l_request)); s_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_CHAINS, + l_ch_chain->callback_notify_packet_out(l_ch_chain, DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAINS, NULL, 0, l_ch_chain->callback_notify_arg); DAP_DELETE(l_sync_request); } @@ -325,9 +376,9 @@ static bool s_sync_out_chains_proc_callback(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); assert(l_chain); - l_sync_request->chain.request_atom_iter = l_chain->callback_atom_iter_create(l_chain, l_sync_request->request_hdr.cell_id, 1); + l_sync_request->chain.request_atom_iter = l_chain->callback_atom_iter_create(l_chain, l_sync_request->request_hdr.cell_id, NULL); size_t l_first_size = 0; - dap_chain_atom_ptr_t l_atom = l_chain->callback_atom_iter_get_first(l_sync_request->chain.request_atom_iter, &l_first_size); + dap_chain_atom_ptr_t l_atom = l_chain->callback_atom_iter_get(l_sync_request->chain.request_atom_iter, DAP_CHAIN_ITER_OP_FIRST, &l_first_size); if (l_atom && l_first_size) { // first packet dap_chain_hash_fast_t l_hash_from = l_sync_request->request.hash_from; @@ -359,7 +410,7 @@ static void s_sync_out_gdb_first_worker_callback(dap_worker_t *a_worker, void *a return; } - dap_chain_ch_t *l_ch_chain = DAP_STREAM_CH_CHAIN( l_ch ); + dap_chain_ch_t *l_ch_chain = DAP_CHAIN_CH( l_ch ); if (!l_ch_chain) { log_it(L_CRITICAL, "Channel without chain, dump it"); @@ -367,21 +418,21 @@ static void s_sync_out_gdb_first_worker_callback(dap_worker_t *a_worker, void *a return; } - if (l_ch_chain->state != CHAIN_STATE_UPDATE_GLOBAL_DB_REMOTE) { + if (l_ch_chain->state != DAP_CHAIN_CH_STATE_UPDATE_GLOBAL_DB_REMOTE) { log_it(L_INFO, "Timeout fired before we sent the reply"); s_sync_request_delete(l_sync_request); return; } // Add it to outgoing list - l_ch_chain->state = CHAIN_STATE_SYNC_GLOBAL_DB; + l_ch_chain->state = DAP_CHAIN_CH_STATE_SYNC_GLOBAL_DB; if (s_debug_more ) - log_it(L_INFO,"Out: DAP_STREAM_CH_CHAIN_PKT_TYPE_FIRST_GLOBAL_DB"); - dap_chain_ch_pkt_write_unsafe(DAP_STREAM_CH(l_ch_chain), DAP_STREAM_CH_CHAIN_PKT_TYPE_FIRST_GLOBAL_DB, + log_it(L_INFO,"Out: DAP_CHAIN_CH_PKT_TYPE_FIRST_GLOBAL_DB"); + dap_chain_ch_pkt_write_unsafe(DAP_STREAM_CH(l_ch_chain), DAP_CHAIN_CH_PKT_TYPE_FIRST_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, &g_node_addr, sizeof(dap_chain_node_addr_t)); if(l_ch_chain->callback_notify_packet_out) - l_ch_chain->callback_notify_packet_out(l_ch_chain, DAP_STREAM_CH_CHAIN_PKT_TYPE_FIRST_GLOBAL_DB, + l_ch_chain->callback_notify_packet_out(l_ch_chain, DAP_CHAIN_CH_PKT_TYPE_FIRST_GLOBAL_DB, NULL, 0, l_ch_chain->callback_notify_arg); if( a_worker){ // We send NULL to prevent delete @@ -404,7 +455,7 @@ static void s_sync_out_gdb_last_worker_callback(dap_worker_t *a_worker, void *a_ return; } - dap_chain_ch_t *l_ch_chain = DAP_STREAM_CH_CHAIN( l_ch ); + dap_chain_ch_t *l_ch_chain = DAP_CHAIN_CH( l_ch ); if (!l_ch_chain) { log_it(L_CRITICAL, "Channel without chain, dump it"); s_sync_request_delete(l_sync_request); @@ -413,13 +464,13 @@ static void s_sync_out_gdb_last_worker_callback(dap_worker_t *a_worker, void *a_ s_sync_out_gdb_first_worker_callback(NULL,a_arg); // NULL to say callback not to delete request if (s_debug_more ) - log_it(L_INFO,"Out: DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB"); - dap_chain_ch_pkt_write_unsafe(DAP_STREAM_CH(l_ch_chain), DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB, + log_it(L_INFO,"Out: DAP_CHAIN_CH_PKT_TYPE_SYNCED_GLOBAL_DB"); + dap_chain_ch_pkt_write_unsafe(DAP_STREAM_CH(l_ch_chain), DAP_CHAIN_CH_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, NULL, 0); s_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, + l_ch_chain->callback_notify_packet_out(l_ch_chain, DAP_CHAIN_CH_PKT_TYPE_SYNCED_GLOBAL_DB, NULL, 0, l_ch_chain->callback_notify_arg); s_sync_request_delete(l_sync_request); } @@ -441,7 +492,7 @@ static bool s_sync_out_gdb_proc_callback(void *a_arg) s_sync_request_delete(l_sync_request); return true; } - dap_chain_ch_t *l_ch_chain = DAP_STREAM_CH_CHAIN(l_ch); + dap_chain_ch_t *l_ch_chain = DAP_CHAIN_CH(l_ch); if (!l_ch_chain) { log_it(L_CRITICAL, "Channel without chain, dump it"); s_sync_request_delete(l_sync_request); @@ -478,11 +529,11 @@ static void s_sync_update_gdb_start_worker_callback(dap_worker_t *a_worker, void s_sync_request_delete(l_sync_request); return; } - dap_chain_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB_START, + dap_chain_ch_pkt_write_unsafe(l_ch, DAP_CHAIN_CH_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); if (s_debug_more) - log_it(L_INFO, "Out: DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB_START for net_id 0x%016"DAP_UINT64_FORMAT_x" " + log_it(L_INFO, "Out: DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_START for net_id 0x%016"DAP_UINT64_FORMAT_x" " "chain_id 0x%016"DAP_UINT64_FORMAT_x" cell_id 0x%016"DAP_UINT64_FORMAT_x"", l_sync_request->request_hdr.net_id.uint64, l_sync_request->request_hdr.chain_id.uint64, l_sync_request->request_hdr.cell_id.uint64); DAP_DELETE(l_sync_request); @@ -504,13 +555,13 @@ static bool s_sync_update_gdb_proc_callback(void *a_arg) log_it(L_INFO, "Client disconnected before we sent the reply"); DAP_DELETE(l_sync_request); return true; - } else if (!DAP_STREAM_CH_CHAIN(l_ch)) { + } else if (!DAP_CHAIN_CH(l_ch)) { log_it(L_CRITICAL, "Channel without chain, dump it"); DAP_DELETE(l_sync_request); return true; } - dap_chain_ch_t *l_ch_chain = DAP_STREAM_CH_CHAIN(l_ch); + dap_chain_ch_t *l_ch_chain = DAP_CHAIN_CH(l_ch); int l_flags = 0; if (dap_chain_net_get_extra_gdb_group(l_net, l_sync_request->request.node_addr)) l_flags |= F_DB_LOG_ADD_EXTRA_GROUPS; @@ -519,7 +570,7 @@ static bool s_sync_update_gdb_proc_callback(void *a_arg) if (l_ch_chain->request_db_log != NULL) dap_db_log_list_delete(l_ch_chain->request_db_log); l_ch_chain->request_db_log = dap_db_log_list_start(l_net->pub.name, l_sync_request->request.node_addr.uint64, l_flags); - l_ch_chain->state = CHAIN_STATE_UPDATE_GLOBAL_DB; + l_ch_chain->state = DAP_CHAIN_CH_STATE_UPDATE_GLOBAL_DB; l_sync_request->gdb.db_log = l_ch_chain->request_db_log; l_sync_request->request.node_addr.uint64 = dap_chain_net_get_cur_addr_int(l_net); dap_worker_exec_callback_on(dap_events_worker_get(l_sync_request->worker->id), s_sync_update_gdb_start_worker_callback, l_sync_request); @@ -532,6 +583,12 @@ static bool s_gdb_in_pkt_proc_callback(void *a_arg) return false; } +struct atom_processing_args { + dap_stream_node_addr_t addr; + bool ack_req; + byte_t data[]; +}; + /** * @brief s_sync_in_chains_callback * @param a_thread dap_proc_thread_t @@ -540,8 +597,10 @@ static bool s_gdb_in_pkt_proc_callback(void *a_arg) */ static bool s_sync_in_chains_callback(void *a_arg) { - dap_chain_ch_pkt_t *l_chain_pkt = a_arg; - if (!l_chain_pkt || !l_chain_pkt->hdr.data_size) { + assert(a_arg); + struct atom_processing_args *l_args = a_arg; + dap_chain_ch_pkt_t *l_chain_pkt = (dap_chain_ch_pkt_t *)l_args->data; + if (!l_chain_pkt->hdr.data_size) { log_it(L_CRITICAL, "Proc thread received corrupted chain packet!"); return false; } @@ -549,8 +608,8 @@ static bool s_sync_in_chains_callback(void *a_arg) uint64_t l_atom_size = l_chain_pkt->hdr.data_size; 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) { - debug_if(s_debug_more, L_WARNING, "No chain found for DAP_STREAM_CH_CHAIN_PKT_TYPE_CHAIN"); - DAP_DELETE(l_chain_pkt); + debug_if(s_debug_more, L_WARNING, "No chain found for DAP_CHAIN_CH_PKT_TYPE_CHAIN"); + DAP_DELETE(l_args); return false; } char *l_atom_hash_str = NULL; @@ -561,19 +620,25 @@ static bool s_sync_in_chains_callback(void *a_arg) case ATOM_PASS: debug_if(s_debug_more, L_WARNING, "Atom with hash %s for %s:%s not accepted (code ATOM_PASS, already present)", l_atom_hash_str, l_chain->net_name, l_chain->name); - //dap_chain_db_set_last_hash_remote(l_sync_request->request.node_addr.uint64, l_chain, &l_atom_hash); break; case ATOM_MOVE_TO_THRESHOLD: debug_if(s_debug_more, L_INFO, "Thresholded atom with hash %s for %s:%s", l_atom_hash_str, l_chain->net_name, l_chain->name); - //dap_chain_db_set_last_hash_remote(l_sync_request->request.node_addr.uint64, l_chain, &l_atom_hash); break; case ATOM_ACCEPT: debug_if(s_debug_more, L_INFO,"Accepted atom with hash %s for %s:%s", l_atom_hash_str, l_chain->net_name, l_chain->name); - int l_res = dap_chain_atom_save(l_chain->cells, l_atom, l_atom_size, NULL); - if(l_res < 0) { + if (dap_chain_atom_save(l_chain->cells, l_atom, l_atom_size, NULL) < 0) log_it(L_ERROR, "Can't save atom %s to the file", l_atom_hash_str); - } else { - //dap_chain_db_set_last_hash_remote(l_sync_request->request.node_addr.uint64, l_chain, &l_atom_hash); + if (l_args->ack_req) { + uint64_t l_ack_num = (l_chain_pkt->hdr.num_hi << 16) | l_chain_pkt->hdr.num_lo; + dap_chain_ch_pkt_t *l_pkt = dap_chain_ch_pkt_new(l_chain_pkt->hdr.net_id.uint64, l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64, + &l_ack_num, sizeof(uint64_t)); + dap_stream_ch_pkt_send_by_addr(&l_args->addr, DAP_CHAIN_CH_ID, DAP_CHAIN_CH_PKT_TYPE_CHAIN_ACK, l_pkt, dap_chain_ch_pkt_get_size(l_pkt)); + DAP_DELETE(l_pkt); + debug_if(s_debug_more, L_DEBUG, "Out: CHAIN_ACK %s for net %s to destination " NODE_ADDR_FP_STR " with num %" DAP_UINT64_FORMAT_U, + l_chain ? l_chain->name : "(null)", + l_chain ? l_chain->net_name : "(null)", + NODE_ADDR_FP_ARGS_S(l_args->addr), + l_ack_num); } break; case ATOM_REJECT: { @@ -584,11 +649,11 @@ static bool s_sync_in_chains_callback(void *a_arg) log_it(L_CRITICAL, "Wtf is this ret code? %d", l_atom_add_res); break; } - DAP_DELETE(l_chain_pkt); + DAP_DELETE(l_args); return false; } -static void s_gossip_payload_callback(void *a_payload, size_t a_payload_size, dap_stream_node_addr_t UNUSED_ARG a_sender_addr) +static void s_gossip_payload_callback(void *a_payload, size_t a_payload_size, dap_stream_node_addr_t a_sender_addr) { assert(a_payload && a_payload_size); dap_chain_ch_pkt_t *l_chain_pkt = a_payload; @@ -597,12 +662,15 @@ static void s_gossip_payload_callback(void *a_payload, size_t a_payload_size, da log_it(L_WARNING, "Incorrect chain GOSSIP packet size"); return; } - dap_chain_ch_pkt_t *l_chain_pkt_copy = DAP_DUP_SIZE(a_payload, a_payload_size); - if (!l_chain_pkt_copy) { - log_it(L_CRITICAL, "Not enough memory"); + struct atom_processing_args *l_args = DAP_NEW_SIZE(struct atom_processing_args, a_payload_size + sizeof(struct atom_processing_args)); + if (!l_args) { + log_it(L_CRITICAL, g_error_memory_alloc); return; } - dap_proc_thread_callback_add(NULL, s_sync_in_chains_callback, l_chain_pkt_copy); + l_args->addr = a_sender_addr; + l_args->ack_req = false; + memcpy(l_args->data, a_payload, a_payload_size); + dap_proc_thread_callback_add(NULL, s_sync_in_chains_callback, l_args); } /** @@ -615,14 +683,13 @@ static void s_gdb_in_pkt_error_worker_callback(dap_worker_t *a_worker, void *a_a 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 ) { + if (l_ch == NULL) log_it(L_INFO,"Client disconnected before we sent the reply"); - } else { - dap_chain_ch_pkt_write_error_unsafe(l_ch, l_sync_request->request_hdr.net_id.uint64, - l_sync_request->request_hdr.chain_id.uint64, - l_sync_request->request_hdr.cell_id.uint64, - "%s : err %d", "ERROR_GLOBAL_DB_INTERNAL_NOT_SAVED", l_sync_request->last_err); - } + else + s_stream_ch_write_error_unsafe(l_ch, l_sync_request->request_hdr.net_id.uint64, + l_sync_request->request_hdr.chain_id.uint64, + l_sync_request->request_hdr.cell_id.uint64, + DAP_CHAIN_CH_ERROR_GLOBAL_DB_INTERNAL_NOT_SAVED); DAP_DELETE(l_sync_request); } @@ -633,7 +700,7 @@ static void s_gdb_in_pkt_error_worker_callback(dap_worker_t *a_worker, void *a_a */ struct sync_request *dap_chain_ch_create_sync_request(dap_chain_ch_pkt_t *a_chain_pkt, dap_stream_ch_t* a_ch) { - dap_chain_ch_t * l_ch_chain = DAP_STREAM_CH_CHAIN(a_ch); + dap_chain_ch_t * l_ch_chain = DAP_CHAIN_CH(a_ch); if (!l_ch_chain) { log_it(L_CRITICAL, "Channel without chain, dump it"); return NULL; @@ -653,15 +720,15 @@ struct sync_request *dap_chain_ch_create_sync_request(dap_chain_ch_pkt_t *a_chai return l_sync_request; } -static void s_stream_ch_write_error_unsafe(dap_stream_ch_t *a_ch, uint64_t a_net_id, uint64_t a_chain_id, uint64_t a_cell_id, const char * a_err_string) +static void s_stream_ch_write_error_unsafe(dap_stream_ch_t *a_ch, uint64_t a_net_id, uint64_t a_chain_id, uint64_t a_cell_id, dap_chain_ch_error_type_t a_error) { - dap_chain_ch_t *l_ch_chain = DAP_STREAM_CH_CHAIN(a_ch); + dap_chain_ch_t *l_ch_chain = DAP_CHAIN_CH(a_ch); if (!l_ch_chain) { log_it(L_CRITICAL, "Channel without chain, dump it"); return; } s_ch_chain_go_idle(l_ch_chain); - dap_chain_ch_pkt_write_error_unsafe(a_ch, a_net_id, a_chain_id, a_cell_id, "%s", a_err_string); + dap_chain_ch_pkt_write_error_unsafe(a_ch, a_net_id, a_chain_id, a_cell_id, "%s", s_error_type_to_string(a_error)); } static bool s_chain_timer_callback(void *a_arg) @@ -672,32 +739,32 @@ static bool s_chain_timer_callback(void *a_arg) DAP_DELETE(a_arg); return false; } - dap_chain_ch_t *l_ch_chain = DAP_STREAM_CH_CHAIN(l_ch); + dap_chain_ch_t *l_ch_chain = DAP_CHAIN_CH(l_ch); if (!l_ch_chain) { log_it(L_CRITICAL, "Channel without chain, dump it"); DAP_DELETE(a_arg); return false; } - if (l_ch_chain->timer_shots++ >= DAP_SYNC_TICKS_PER_SECOND * DAP_CHAIN_NODE_SYNC_TIMEOUT) { + if (l_ch_chain->timer_shots++ >= DAP_SYNC_TICKS_PER_SECOND * s_sync_timeout) { if (!s_ch_chain_get_idle(l_ch_chain)) { s_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_TIMEOUT, NULL, 0, + l_ch_chain->callback_notify_packet_out(l_ch_chain, DAP_CHAIN_CH_PKT_TYPE_TIMEOUT, NULL, 0, l_ch_chain->callback_notify_arg); } DAP_DELETE(a_arg); l_ch_chain->activity_timer = NULL; return false; } - if (l_ch_chain->state != CHAIN_STATE_WAITING && l_ch_chain->sent_breaks) { + if (l_ch_chain->state != DAP_CHAIN_CH_STATE_WAITING && l_ch_chain->sent_breaks) { s_stream_ch_packet_out(l_ch, a_arg); if (l_ch_chain->activity_timer == NULL) return false; } // Sending dumb packet with nothing to inform remote thats we're just skiping atoms of GDB's, nothing freezed - if (l_ch_chain->state == CHAIN_STATE_SYNC_CHAINS && l_ch_chain->sent_breaks >= 3 * DAP_SYNC_TICKS_PER_SECOND) { + if (l_ch_chain->state == DAP_CHAIN_CH_STATE_SYNC_CHAINS && l_ch_chain->sent_breaks >= 3 * DAP_SYNC_TICKS_PER_SECOND) { debug_if(s_debug_more, L_INFO, "Send one chain TSD packet"); - dap_chain_ch_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_CHAINS_TSD, + dap_chain_ch_pkt_write_unsafe(l_ch, DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_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); l_ch_chain->sent_breaks = 0; @@ -729,46 +796,245 @@ void dap_chain_ch_timer_start(dap_chain_ch_t *a_ch_chain) */ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) { - dap_chain_ch_t * l_ch_chain = DAP_STREAM_CH_CHAIN(a_ch); + dap_chain_ch_t *l_ch_chain = DAP_CHAIN_CH(a_ch); if (!l_ch_chain || l_ch_chain->_inheritor != a_ch) { 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_chain_ch_pkt_t * l_chain_pkt = (dap_chain_ch_pkt_t *) l_ch_pkt->data; - if (!l_chain_pkt) { - log_it(L_ERROR, "No chain packet in channel packet, returning"); + if (l_ch_pkt->hdr.data_size < sizeof(dap_chain_ch_pkt_t)) { + log_it(L_ERROR, "Corrupted packet: too small size %u, smaller then header size %zu", + l_ch_pkt->hdr.data_size, sizeof(dap_chain_ch_pkt_t)); return; } - if (l_ch_pkt->hdr.data_size < sizeof (l_chain_pkt->hdr)){ - log_it(L_ERROR, "Corrupted packet: too small size %u, smaller then header size %zu", l_ch_pkt->hdr.data_size, - sizeof(l_chain_pkt->hdr)); + + dap_chain_ch_pkt_t *l_chain_pkt = (dap_chain_ch_pkt_t *)l_ch_pkt->data; + size_t l_chain_pkt_data_size = l_ch_pkt->hdr.data_size - sizeof(l_chain_pkt->hdr); + + if (l_chain_pkt->hdr.version > DAP_CHAIN_CH_PKT_VERSION) { + debug_if(s_debug_more, L_ATT, "Unsupported protocol version %d, current version %d", + l_chain_pkt->hdr.version, DAP_CHAIN_CH_PKT_VERSION); return; } - if (l_chain_pkt->hdr.version != DAP_STREAM_CH_CHAIN_PKT_VERSION) { - debug_if(s_debug_more, L_ATT, "Unsupported protocol version %d, current version %d", - l_chain_pkt->hdr.version, DAP_STREAM_CH_CHAIN_PKT_VERSION); + if (l_chain_pkt->hdr.version >= 2 && + l_chain_pkt_data_size != l_chain_pkt->hdr.data_size) { + log_it(L_WARNING, "Incorrect chain packet size %zu, expected %u", + l_chain_pkt_data_size, l_chain_pkt->hdr.data_size); return; } - size_t l_chain_pkt_data_size = l_ch_pkt->hdr.data_size - sizeof(l_chain_pkt->hdr); s_chain_timer_reset(l_ch_chain); + switch (l_ch_pkt->hdr.type) { + + /* *** New synchronization protocol *** */ + + case DAP_CHAIN_CH_PKT_TYPE_ERROR:{ + char * l_error_str = (char*)l_chain_pkt->data; + if(l_chain_pkt_data_size>1) + 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%016"DAP_UINT64_FORMAT_x" got error on his side: '%s'", + DAP_STREAM_CH(l_ch_chain)->stream->esocket->remote_addr_str, + l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt_data_size ? l_error_str : "<empty>"); + } break; + + case DAP_CHAIN_CH_PKT_TYPE_CHAIN: { + dap_cluster_t *l_cluster = dap_cluster_find(dap_cluster_guuid_compose(l_chain_pkt->hdr.net_id.uint64, 0)); + if (!l_cluster) { + log_it(L_WARNING, "Can't find cluster with ID 0x%" DAP_UINT64_FORMAT_X, l_chain_pkt->hdr.net_id.uint64); + 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, + DAP_CHAIN_CH_ERROR_CHAIN_NOT_FOUND); + break; + } + dap_cluster_member_t *l_check = dap_cluster_member_find_unsafe(l_cluster, &a_ch->stream->node); + if (!l_check) { + log_it(L_WARNING, "Node with addr "NODE_ADDR_FP_STR" isn't a member of cluster %s", + NODE_ADDR_FP_ARGS_S(a_ch->stream->node), l_cluster->mnemonim); + break; + } + struct atom_processing_args *l_args = DAP_NEW_SIZE(struct atom_processing_args, l_ch_pkt->hdr.data_size + sizeof(struct atom_processing_args)); + if (!l_args) { + log_it(L_CRITICAL, g_error_memory_alloc); + return; + } + l_args->addr = a_ch->stream->node; + l_args->ack_req = true; + if (l_chain_pkt->hdr.version < 2) + l_chain_pkt->hdr.data_size = l_chain_pkt_data_size; + memcpy(l_args->data, l_chain_pkt, l_ch_pkt->hdr.data_size); + if (s_debug_more) { + char *l_atom_hash_str; + dap_get_data_hash_str_static(l_chain_pkt->data, l_chain_pkt_data_size, l_atom_hash_str); + log_it(L_INFO, "In: CHAIN pkt: atom hash %s (size %zd)", l_atom_hash_str, l_chain_pkt_data_size); + } + dap_proc_thread_callback_add(a_ch->stream_worker->worker->proc_queue_input, s_sync_in_chains_callback, l_args); + } break; + + case DAP_CHAIN_CH_PKT_TYPE_CHAIN_REQ: { + if (l_chain_pkt_data_size != sizeof(dap_hash_fast_t)) { + log_it(L_WARNING, "DAP_CHAIN_CH_PKT_TYPE_CHAIN_REQ: Wrong chain packet size %zd when expected %zd", + l_chain_pkt_data_size, sizeof(dap_hash_fast_t)); + 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, + DAP_CHAIN_CH_ERROR_CHAIN_PKT_DATA_SIZE); + break; + } + if (s_debug_more) + log_it(L_INFO, "In: CHAIN_REQ pkt: net 0x%016" DAP_UINT64_FORMAT_x " chain 0x%016" DAP_UINT64_FORMAT_x " cell 0x%016" DAP_UINT64_FORMAT_x, + 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->sync_context) { + log_it(L_WARNING, "Can't process CHAIN_REQ request cause already busy with syncronization"); + dap_chain_ch_pkt_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, + DAP_CHAIN_CH_ERROR_SYNC_REQUEST_ALREADY_IN_PROCESS); + break; + } + 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) { + log_it(L_WARNING, "Not found chain id 0x%016" DAP_UINT64_FORMAT_x " with net id 0x%016" DAP_UINT64_FORMAT_x, + l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.net_id.uint64); + 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, + DAP_CHAIN_CH_ERROR_CHAIN_NOT_FOUND); + break; + } + dap_hash_fast_t *l_requested_hash = (dap_hash_fast_t *)l_chain_pkt->data; + if (dap_hash_fast_is_blank(l_requested_hash)) + l_requested_hash = NULL; + dap_chain_atom_iter_t *l_iter = l_chain->callback_atom_iter_create(l_chain, l_chain_pkt->hdr.cell_id, l_requested_hash); + if (!l_requested_hash) + l_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_FIRST, NULL); + if (l_iter->cur) { + dap_chain_ch_summary_t l_sum = { .num_cur = l_requested_hash ? l_iter->cur_num : 0, .num_last = l_chain->callback_count_atom(l_chain) }; + if (l_sum.num_last - l_sum.num_cur) { + dap_chain_ch_pkt_write_unsafe(a_ch, DAP_CHAIN_CH_PKT_TYPE_CHAIN_SUMMARY, + l_chain_pkt->hdr.net_id.uint64, l_chain_pkt->hdr.chain_id.uint64, + l_chain_pkt->hdr.cell_id.uint64, &l_sum, sizeof(l_sum)); + debug_if(s_debug_more, L_DEBUG, "Out: CHAIN_SUMMARY %s for net %s to destination " NODE_ADDR_FP_STR, + l_chain ? l_chain->name : "(null)", + l_chain ? l_chain->net_name : "(null)", + NODE_ADDR_FP_ARGS_S(a_ch->stream->node)); + struct sync_context *l_context = DAP_NEW_Z(struct sync_context); + l_context->addr = a_ch->stream->node; + l_context->iter = l_iter; + l_context->net_id = l_chain_pkt->hdr.net_id; + l_context->chain_id = l_chain_pkt->hdr.chain_id; + l_context->cell_id = l_chain_pkt->hdr.cell_id; + l_context->num_last = l_sum.num_last; + l_context->last_activity = dap_time_now(); + atomic_store_explicit(&l_context->state, SYNC_STATE_READY, memory_order_relaxed); + atomic_store(&l_context->allowed_num, l_sum.num_cur + s_sync_ack_window_size); + dap_proc_thread_callback_add(a_ch->stream_worker->worker->proc_queue_input, s_chain_iter_callback, l_context); + l_ch_chain->sync_context = l_context; + l_ch_chain->sync_timer = dap_timerfd_start_on_worker(a_ch->stream_worker->worker, 1000, s_sync_timer_callback, l_ch_chain); + break; + } + } else + debug_if(s_debug_more, L_DEBUG, "Requested atom with hash %s not found", dap_hash_fast_to_str_static(l_requested_hash)); + dap_chain_ch_pkt_write_unsafe(a_ch, DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAIN, + l_chain_pkt->hdr.net_id.uint64, l_chain_pkt->hdr.chain_id.uint64, + l_chain_pkt->hdr.cell_id.uint64, NULL, 0); + debug_if(s_debug_more, L_DEBUG, "Out: SYNCED_CHAIN %s for net %s to destination " NODE_ADDR_FP_STR, + l_chain ? l_chain->name : "(null)", + l_chain ? l_chain->net_name : "(null)", + NODE_ADDR_FP_ARGS_S(a_ch->stream->node)); + l_chain->callback_atom_iter_delete(l_iter); + } break; + + case DAP_CHAIN_CH_PKT_TYPE_CHAIN_SUMMARY: { + if (l_chain_pkt_data_size != sizeof(dap_chain_ch_summary_t)) { + log_it(L_WARNING, "DAP_CHAIN_CH_PKT_TYPE_CHAIN_SUMMARY: Wrong chain packet size %zd when expected %zd", + l_chain_pkt_data_size, sizeof(dap_chain_ch_summary_t)); + 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, + DAP_CHAIN_CH_ERROR_CHAIN_PKT_DATA_SIZE); + break; + } + dap_chain_t *l_chain = dap_chain_find_by_id(l_chain_pkt->hdr.net_id, l_chain_pkt->hdr.chain_id); + dap_chain_ch_summary_t *l_sum = (dap_chain_ch_summary_t *)l_chain_pkt->data; + debug_if(s_debug_more, L_DEBUG, "In: CHAIN_SUMMARY of %s for net %s from source " NODE_ADDR_FP_STR + " with %" DAP_UINT64_FORMAT_U " atoms to sync from %" DAP_UINT64_FORMAT_U " to %" DAP_UINT64_FORMAT_U, + l_chain ? l_chain->name : "(null)", + l_chain ? l_chain->net_name : "(null)", + NODE_ADDR_FP_ARGS_S(a_ch->stream->node), + l_sum->num_last - l_sum->num_cur, l_sum->num_cur, l_sum->num_last); + } break; + + case DAP_CHAIN_CH_PKT_TYPE_CHAIN_ACK: { + if (l_chain_pkt_data_size != sizeof(uint64_t)) { + log_it(L_WARNING, "DAP_CHAIN_CH_PKT_TYPE_CHAIN_ACK: Wrong chain packet size %zd when expected %zd", + l_chain_pkt_data_size, sizeof(uint64_t)); + 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, + DAP_CHAIN_CH_ERROR_CHAIN_PKT_DATA_SIZE); + break; + } + uint64_t l_ack_num = *(uint64_t *)l_chain_pkt->data; + dap_chain_t *l_chain = dap_chain_find_by_id(l_chain_pkt->hdr.net_id, l_chain_pkt->hdr.chain_id); + debug_if(s_debug_more, L_DEBUG, "In: CHAIN_ACK %s for net %s from source " NODE_ADDR_FP_STR " with num %" DAP_UINT64_FORMAT_U, + l_chain ? l_chain->name : "(null)", + l_chain ? l_chain->net_name : "(null)", + NODE_ADDR_FP_ARGS_S(a_ch->stream->node), + l_ack_num); + struct sync_context *l_context = l_ch_chain->sync_context; + if (!l_context) { + log_it(L_WARNING, "CHAIN_ACK: No active sync context"); + 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, + DAP_CHAIN_CH_ERROR_INCORRECT_SYNC_SEQUENCE); + break; + } + if (l_context->num_last == l_ack_num) { + dap_chain_ch_pkt_write_unsafe(a_ch, DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAIN, + l_chain_pkt->hdr.net_id.uint64, l_chain_pkt->hdr.chain_id.uint64, + l_chain_pkt->hdr.cell_id.uint64, NULL, 0); + s_ch_chain_go_idle(l_ch_chain); + break; + } + l_context->last_activity = dap_time_now(); + if (atomic_load_explicit(&l_context->state, memory_order_relaxed) == SYNC_STATE_OVER) + break; + atomic_store_explicit(&l_context->allowed_num, + dap_min(l_ack_num + s_sync_ack_window_size, l_context->num_last), + memory_order_release); + if (atomic_exchange(&l_context->state, SYNC_STATE_READY) == SYNC_STATE_IDLE) + dap_proc_thread_callback_add(a_ch->stream_worker->worker->proc_queue_input, s_chain_iter_callback, l_context); + } break; + + case DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAIN: { + dap_chain_t *l_chain = dap_chain_find_by_id(l_chain_pkt->hdr.net_id, l_chain_pkt->hdr.chain_id); + log_it(L_INFO, "In: SYNCED_CHAIN %s for net %s from source " NODE_ADDR_FP_STR, + l_chain ? l_chain->name : "(null)", + l_chain ? l_chain->net_name : "(null)", + NODE_ADDR_FP_ARGS_S(a_ch->stream->node)); + } break; + + default: + 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, + DAP_CHAIN_CH_ERROR_UNKNOWN_CHAIN_PKT_TYPE); + +// } +//} + + /* *** Legacy *** */ + /// --- GDB update --- // Request for gdbs list update - case DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB_REQ:{ - if(l_ch_chain->state != CHAIN_STATE_IDLE){ + case DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_REQ:{ + if(l_ch_chain->state != DAP_CHAIN_CH_STATE_IDLE){ log_it(L_WARNING, "Can't process UPDATE_GLOBAL_DB_REQ request because its already busy with syncronization"); dap_chain_ch_pkt_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, - "ERROR_SYNC_REQUEST_ALREADY_IN_PROCESS"); + DAP_CHAIN_CH_ERROR_SYNC_REQUEST_ALREADY_IN_PROCESS); break; } log_it(L_INFO, "In: UPDATE_GLOBAL_DB_REQ pkt: net 0x%016"DAP_UINT64_FORMAT_x" chain 0x%016"DAP_UINT64_FORMAT_x" cell 0x%016"DAP_UINT64_FORMAT_x, l_chain_pkt->hdr.net_id.uint64, l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64); if (l_chain_pkt_data_size == (size_t)sizeof(dap_chain_ch_sync_request_t)) l_ch_chain->request = *(dap_chain_ch_sync_request_t*)l_chain_pkt->data; - l_ch_chain->request.id_start = 0; struct sync_request *l_sync_request = dap_chain_ch_create_sync_request(l_chain_pkt, a_ch); l_ch_chain->stats_request_gdb_processed = 0; l_ch_chain->request_hdr = l_chain_pkt->hdr; @@ -776,37 +1042,37 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) } break; // Response with metadata organized in TSD - case DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB_TSD: { + case DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_TSD: { if (s_debug_more) log_it(L_DEBUG, "Global DB TSD packet detected"); } break; // If requested - begin to recieve record's hashes - case DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB_START:{ + case DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_START:{ if (s_debug_more) log_it(L_INFO, "In: UPDATE_GLOBAL_DB_START pkt net 0x%016"DAP_UINT64_FORMAT_x" chain 0x%016"DAP_UINT64_FORMAT_x" cell 0x%016"DAP_UINT64_FORMAT_x, 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 != DAP_CHAIN_CH_STATE_IDLE){ log_it(L_WARNING, "Can't process UPDATE_GLOBAL_DB_START request because its already busy with syncronization"); dap_chain_ch_pkt_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, - "ERROR_SYNC_REQUEST_ALREADY_IN_PROCESS"); + DAP_CHAIN_CH_ERROR_SYNC_REQUEST_ALREADY_IN_PROCESS); break; } l_ch_chain->request_hdr = l_chain_pkt->hdr; - l_ch_chain->state = CHAIN_STATE_UPDATE_GLOBAL_DB_REMOTE; + l_ch_chain->state = DAP_CHAIN_CH_STATE_UPDATE_GLOBAL_DB_REMOTE; } break; // Response with gdb element hashes and sizes - case DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB:{ + case DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB:{ if(s_debug_more) log_it(L_INFO, "In: UPDATE_GLOBAL_DB pkt data_size=%zu", l_chain_pkt_data_size); - if (l_ch_chain->state != CHAIN_STATE_UPDATE_GLOBAL_DB_REMOTE || + if (l_ch_chain->state != DAP_CHAIN_CH_STATE_UPDATE_GLOBAL_DB_REMOTE || memcmp(&l_ch_chain->request_hdr.net_id, &l_chain_pkt->hdr.net_id, sizeof(dap_chain_net_id_t) + sizeof(dap_chain_id_t) + sizeof(dap_chain_cell_id_t))) { log_it(L_WARNING, "Can't process UPDATE_GLOBAL_DB 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, - "ERROR_SYNC_REQUEST_ALREADY_IN_PROCESS"); + DAP_CHAIN_CH_ERROR_SYNC_REQUEST_ALREADY_IN_PROCESS); break; } for ( dap_chain_ch_update_element_t * l_element =(dap_chain_ch_update_element_t *) l_chain_pkt->data; @@ -836,15 +1102,15 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) } } break; // End of response with starting of DB sync - case DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB_END: { + case DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_END: { if(l_chain_pkt_data_size == sizeof(dap_chain_ch_sync_request_t)) { - if (l_ch_chain->state != CHAIN_STATE_UPDATE_GLOBAL_DB_REMOTE || + if (l_ch_chain->state != DAP_CHAIN_CH_STATE_UPDATE_GLOBAL_DB_REMOTE || memcmp(&l_ch_chain->request_hdr.net_id, &l_chain_pkt->hdr.net_id, sizeof(dap_chain_net_id_t) + sizeof(dap_chain_id_t) + sizeof(dap_chain_cell_id_t))) { log_it(L_WARNING, "Can't process UPDATE_GLOBAL_DB_END 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, - "ERROR_SYNC_REQUEST_ALREADY_IN_PROCESS"); + DAP_CHAIN_CH_ERROR_SYNC_REQUEST_ALREADY_IN_PROCESS); break; } debug_if(s_debug_more, L_INFO, "In: UPDATE_GLOBAL_DB_END pkt with total count %d hashes", @@ -854,14 +1120,14 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) struct sync_request *l_sync_request = dap_chain_ch_create_sync_request(l_chain_pkt, a_ch); dap_proc_thread_callback_add(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_UPDATE_GLOBAL_DB_END: Wrong chain packet size %zd when expected %zd", l_chain_pkt_data_size, sizeof(l_ch_chain->request)); + log_it(L_WARNING, "DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_END: Wrong chain packet size %zd when expected %zd", l_chain_pkt_data_size, sizeof(l_ch_chain->request)); 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, - "ERROR_CHAIN_PKT_DATA_SIZE" ); + DAP_CHAIN_CH_ERROR_CHAIN_PKT_DATA_SIZE); } } break; // first packet of data with source node address - case DAP_STREAM_CH_CHAIN_PKT_TYPE_FIRST_GLOBAL_DB: { + case DAP_CHAIN_CH_PKT_TYPE_FIRST_GLOBAL_DB: { if(l_chain_pkt_data_size == (size_t)sizeof(dap_chain_node_addr_t)){ l_ch_chain->request.node_addr = *(dap_chain_node_addr_t*)l_chain_pkt->data; l_ch_chain->stats_request_gdb_processed = 0; @@ -869,14 +1135,14 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) " from address "NODE_ADDR_FP_STR, l_chain_pkt_data_size, l_chain_pkt->hdr.net_id.uint64 , l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64, NODE_ADDR_FP_ARGS_S(l_ch_chain->request.node_addr) ); }else { - log_it(L_WARNING,"Incorrect data size %zu in packet DAP_STREAM_CH_CHAIN_PKT_TYPE_FIRST_GLOBAL_DB", l_chain_pkt_data_size); + log_it(L_WARNING,"Incorrect data size %zu in packet DAP_CHAIN_CH_PKT_TYPE_FIRST_GLOBAL_DB", l_chain_pkt_data_size); 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, - "ERROR_CHAIN_PACKET_TYPE_FIRST_GLOBAL_DB_INCORRET_DATA_SIZE"); + DAP_CHAIN_CH_ERROR_CHAIN_PKT_DATA_SIZE); } } break; - case DAP_STREAM_CH_CHAIN_PKT_TYPE_GLOBAL_DB: { + case DAP_CHAIN_CH_PKT_TYPE_GLOBAL_DB: { if(s_debug_more) log_it(L_INFO, "In: GLOBAL_DB data_size=%zu", l_chain_pkt_data_size); // get transaction and save it to global_db @@ -890,29 +1156,29 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) log_it(L_WARNING, "Packet with GLOBAL_DB atom has zero body size"); 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, - "ERROR_GLOBAL_DB_PACKET_EMPTY"); + DAP_CHAIN_CH_ERROR_CHAIN_PKT_DATA_SIZE); } } break; - case DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB: { + case DAP_CHAIN_CH_PKT_TYPE_SYNCED_GLOBAL_DB: { log_it(L_INFO, "In: SYNCED_GLOBAL_DB: net 0x%016"DAP_UINT64_FORMAT_x" chain 0x%016"DAP_UINT64_FORMAT_x" cell 0x%016"DAP_UINT64_FORMAT_x, 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->callback_notify_packet_in) { // we haven't node client waitng, so reply to other side dap_chain_ch_sync_request_t l_sync_gdb = {}; l_sync_gdb.node_addr.uint64 = g_node_addr.uint64; - dap_chain_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB_REQ, l_chain_pkt->hdr.net_id.uint64, + dap_chain_ch_pkt_write_unsafe(a_ch, DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_REQ, l_chain_pkt->hdr.net_id.uint64, l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64, &l_sync_gdb, sizeof(l_sync_gdb)); } } break; /// --- Chains update --- // Request for atoms list update - case DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_CHAINS_REQ:{ - if (l_ch_chain->state != CHAIN_STATE_IDLE) { + case DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_REQ:{ + if (l_ch_chain->state != DAP_CHAIN_CH_STATE_IDLE) { log_it(L_WARNING, "Can't process UPDATE_CHAINS_REQ request because its already busy with syncronization"); - dap_chain_ch_pkt_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id.uint64, + 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, - "ERROR_SYNC_REQUEST_ALREADY_IN_PROCESS"); + DAP_CHAIN_CH_ERROR_SYNC_REQUEST_ALREADY_IN_PROCESS); break; } if(s_debug_more) @@ -920,31 +1186,31 @@ 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); 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) { - l_ch_chain->state = CHAIN_STATE_UPDATE_CHAINS; + l_ch_chain->state = DAP_CHAIN_CH_STATE_UPDATE_CHAINS; if(s_debug_more) log_it(L_INFO, "Out: UPDATE_CHAINS_START pkt: net %s chain %s cell 0x%016"DAP_UINT64_FORMAT_X, l_chain->name, l_chain->net_name, l_chain_pkt->hdr.cell_id.uint64); - l_ch_chain->request_atom_iter = l_chain->callback_atom_iter_create(l_chain, l_chain_pkt->hdr.cell_id, 1); - l_chain->callback_atom_iter_get_first(l_ch_chain->request_atom_iter, NULL); + l_ch_chain->request_atom_iter = l_chain->callback_atom_iter_create(l_chain, l_chain_pkt->hdr.cell_id, NULL); + l_chain->callback_atom_iter_get(l_ch_chain->request_atom_iter, DAP_CHAIN_ITER_OP_FIRST, NULL); l_ch_chain->request_hdr = l_chain_pkt->hdr; - dap_chain_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_CHAINS_START, + dap_chain_ch_pkt_write_unsafe(a_ch, DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_START, l_chain_pkt->hdr.net_id.uint64,l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt->hdr.cell_id.uint64, NULL, 0); } } break; // Response with metadata organized in TSD - case DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_CHAINS_TSD :{ + case DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_TSD :{ 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:{ - if (l_ch_chain->state != CHAIN_STATE_IDLE) { + case DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_START:{ + if (l_ch_chain->state != DAP_CHAIN_CH_STATE_IDLE) { log_it(L_WARNING, "Can't process UPDATE_CHAINS_START request because its already busy with syncronization"); dap_chain_ch_pkt_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, - "ERROR_SYNC_REQUEST_ALREADY_IN_PROCESS"); + DAP_CHAIN_CH_ERROR_SYNC_REQUEST_ALREADY_IN_PROCESS); break; } dap_chain_t * l_chain = dap_chain_find_by_id(l_chain_pkt->hdr.net_id, l_chain_pkt->hdr.chain_id); @@ -955,18 +1221,18 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) l_chain_pkt->hdr.cell_id.uint64); 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, - "ERROR_NET_INVALID_ID"); + DAP_CHAIN_CH_ERROR_NET_INVALID_ID); // Who are you? I don't know you! go away! a_ch->stream->esocket->flags |= DAP_SOCK_SIGNAL_CLOSE; break; } - l_ch_chain->state = CHAIN_STATE_UPDATE_CHAINS_REMOTE; + l_ch_chain->state = DAP_CHAIN_CH_STATE_UPDATE_CHAINS_REMOTE; l_ch_chain->request_hdr = l_chain_pkt->hdr; debug_if(s_debug_more, L_INFO, "In: UPDATE_CHAINS_START pkt"); } break; // Response with atom hashes and sizes - case DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_CHAINS: { + case DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS: { unsigned int l_count_added=0; unsigned int l_count_total=0; @@ -979,7 +1245,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) l_chain_pkt->hdr.cell_id.uint64); 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, - "ERROR_NET_INVALID_ID"); + DAP_CHAIN_CH_ERROR_NET_INVALID_ID); // Who are you? I don't know you! go away! a_ch->stream->esocket->flags |= DAP_SOCK_SIGNAL_CLOSE; break; @@ -1016,15 +1282,15 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) log_it(L_INFO,"In: Added %u from %u remote atom hash in list",l_count_added,l_count_total); } break; - case DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_CHAINS_END: { + case DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_END: { if(l_chain_pkt_data_size == sizeof(dap_chain_ch_sync_request_t)) { - if (l_ch_chain->state != CHAIN_STATE_UPDATE_CHAINS_REMOTE || + if (l_ch_chain->state != DAP_CHAIN_CH_STATE_UPDATE_CHAINS_REMOTE || memcmp(&l_ch_chain->request_hdr.net_id, &l_chain_pkt->hdr.net_id, sizeof(dap_chain_net_id_t) + sizeof(dap_chain_id_t) + sizeof(dap_chain_cell_id_t))) { log_it(L_WARNING, "Can't process UPDATE_CHAINS_END 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, - "ERROR_SYNC_REQUEST_ALREADY_IN_PROCESS"); + DAP_CHAIN_CH_ERROR_SYNC_REQUEST_ALREADY_IN_PROCESS); break; } dap_chain_t * l_chain = dap_chain_find_by_id(l_chain_pkt->hdr.net_id, l_chain_pkt->hdr.chain_id); @@ -1035,7 +1301,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) l_chain_pkt->hdr.cell_id.uint64); 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, - "ERROR_NET_INVALID_ID"); + DAP_CHAIN_CH_ERROR_NET_INVALID_ID); break; } debug_if(s_debug_more, L_INFO, "In: UPDATE_CHAINS_END pkt with total count %d hashes", @@ -1045,15 +1311,15 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) l_ch_chain->request_hdr = l_chain_pkt->hdr; dap_proc_thread_callback_add(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_UPDATE_CHAINS_END: Wrong chain packet size %zd when expected %zd", + log_it(L_WARNING, "DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_END: Wrong chain packet size %zd when expected %zd", l_chain_pkt_data_size, sizeof(l_ch_chain->request)); 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, - "ERROR_CHAIN_PKT_DATA_SIZE" ); + DAP_CHAIN_CH_ERROR_CHAIN_PKT_DATA_SIZE); } } break; // first packet of data with source node address - case DAP_STREAM_CH_CHAIN_PKT_TYPE_FIRST_CHAIN: { + case DAP_CHAIN_CH_PKT_TYPE_FIRST_CHAIN: { if(l_chain_pkt_data_size == (size_t)sizeof(dap_chain_node_addr_t)){ l_ch_chain->request_hdr = l_chain_pkt->hdr; l_ch_chain->request.node_addr = *(dap_chain_node_addr_t*)l_chain_pkt->data; @@ -1062,53 +1328,19 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) 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); }else{ - log_it(L_WARNING,"Incorrect data size %zd in packet DAP_STREAM_CH_CHAIN_PKT_TYPE_FIRST_CHAIN", l_chain_pkt_data_size); + log_it(L_WARNING,"Incorrect data size %zd in packet DAP_CHAIN_CH_PKT_TYPE_FIRST_CHAIN", l_chain_pkt_data_size); 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, - "ERROR_CHAIN_PACKET_TYPE_FIRST_CHAIN_INCORRET_DATA_SIZE"); + DAP_CHAIN_CH_ERROR_CHAIN_PKT_DATA_SIZE); } } break; - case DAP_STREAM_CH_CHAIN_PKT_TYPE_CHAIN: { - dap_chain_ch_pkt_t *l_chain_pkt = (dap_chain_ch_pkt_t *)l_ch_pkt->data; - if (l_chain_pkt->hdr.version >= 2 && - l_chain_pkt_data_size != l_chain_pkt->hdr.data_size) { - log_it(L_WARNING, "Incorrect chain packet size"); - break; - } - dap_cluster_t *l_cluster = dap_cluster_find(dap_cluster_guuid_compose(l_chain_pkt->hdr.net_id.uint64, 0)); - if (!l_cluster) { - log_it(L_WARNING, "Can't find cluster with ID 0x%" DAP_UINT64_FORMAT_X, l_chain_pkt->hdr.net_id.uint64); - break; - } - dap_cluster_member_t *l_check = dap_cluster_member_find_unsafe(l_cluster, &a_ch->stream->node); - if (!l_check) { - log_it(L_WARNING, "Node with addr "NODE_ADDR_FP_STR" isn't a member of cluster %s", - NODE_ADDR_FP_ARGS_S(a_ch->stream->node), l_cluster->mnemonim); - break; - } - dap_chain_ch_pkt_t *l_chain_pkt_copy = DAP_DUP_SIZE(l_ch_pkt->data, l_ch_pkt->hdr.data_size); - if (!l_chain_pkt_copy) { - log_it(L_CRITICAL, "Not enough memory"); - break; - } - if (l_chain_pkt_copy->hdr.version < 2) - l_chain_pkt_copy->hdr.data_size = l_chain_pkt_data_size; - if (s_debug_more) { - char *l_atom_hash_str; - dap_get_data_hash_str_static(l_chain_pkt->data, l_chain_pkt_data_size, l_atom_hash_str); - log_it(L_INFO, "In: CHAIN pkt: atom hash %s (size %zd)", l_atom_hash_str, l_chain_pkt_data_size); - } - dap_proc_thread_callback_add(a_ch->stream_worker->worker->proc_queue_input, s_sync_in_chains_callback, l_chain_pkt_copy); - } break; - - case DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_CHAINS: { + case DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAINS: { if (dap_log_level_get() <= L_INFO) { - dap_chain_hash_fast_t l_hash_from = l_ch_chain->request.hash_from, - l_hash_to = l_ch_chain->request.hash_to; + dap_chain_hash_fast_t l_hash_from = l_ch_chain->request.hash_from; char l_hash_from_str[DAP_CHAIN_HASH_FAST_STR_SIZE] = { '\0' }, l_hash_to_str[DAP_CHAIN_HASH_FAST_STR_SIZE] = { '\0' }; dap_chain_hash_fast_to_str(&l_hash_from, l_hash_from_str, DAP_CHAIN_HASH_FAST_STR_SIZE); - dap_chain_hash_fast_to_str(&l_hash_to, l_hash_to_str, DAP_CHAIN_HASH_FAST_STR_SIZE); + dap_chain_hash_fast_to_str(&c_dap_chain_addr_blank.data.hash_fast, l_hash_to_str, DAP_CHAIN_HASH_FAST_STR_SIZE); log_it(L_INFO, "In: SYNCED_CHAINS: between %s and %s",l_hash_from_str[0] ? l_hash_from_str : "(null)", l_hash_to_str[0] ? l_hash_to_str: "(null)"); @@ -1127,47 +1359,92 @@ 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); 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, - "ERROR_NET_INVALID_ID"); + DAP_CHAIN_CH_ERROR_NET_INVALID_ID); break; } if (s_debug_more) { log_it(L_INFO, "Out: UPDATE_CHAINS_REQ pkt"); } dap_chain_ch_sync_request_t l_request= {}; - dap_chain_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_CHAINS_REQ, l_chain_pkt->hdr.net_id.uint64, + dap_chain_ch_pkt_write_unsafe(a_ch, DAP_CHAIN_CH_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)); } } break; - - case DAP_STREAM_CH_CHAIN_PKT_TYPE_ERROR:{ - char * l_error_str = (char*)l_chain_pkt->data; - if(l_chain_pkt_data_size>1) - 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%016"DAP_UINT64_FORMAT_x" got error on his side: '%s'", - DAP_STREAM_CH(l_ch_chain)->stream->esocket->remote_addr_str, - l_chain_pkt->hdr.chain_id.uint64, l_chain_pkt_data_size ? l_error_str : "<empty>"); - } break; - - default: { - 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, - "ERROR_UNKNOWN_CHAIN_PKT_TYPE"); - } } if(l_ch_chain->callback_notify_packet_in) l_ch_chain->callback_notify_packet_in(l_ch_chain, l_ch_pkt->hdr.type, l_chain_pkt, l_chain_pkt_data_size, l_ch_chain->callback_notify_arg); } +static bool s_sync_timer_callback(void *a_arg) +{ + dap_chain_ch_t *l_ch_chain = a_arg; + struct sync_context *l_context = l_ch_chain->sync_context; + if (l_context->last_activity + s_sync_timeout <= dap_time_now()) { + l_ch_chain->sync_timer = NULL; + s_ch_chain_go_idle(l_ch_chain); + return false; + } + return true; +} -/** - * @brief s_ch_chain_go_idle_and_free_log_list - * @param a_ch_chain - */ -static void s_free_log_list_gdb ( dap_chain_ch_t * a_ch_chain) +static bool s_chain_iter_callback(void *a_arg) { + assert(a_arg); + struct sync_context *l_context = a_arg; + dap_chain_atom_iter_t *l_iter = l_context->iter; + assert(l_iter); + dap_chain_t *l_chain = l_iter->chain; + if (atomic_exchange(&l_context->state, SYNC_STATE_BUSY) == SYNC_STATE_OVER) { + atomic_store(&l_context->state, SYNC_STATE_OVER); + return false; + } + size_t l_atom_size = l_iter->cur_size; + dap_chain_atom_ptr_t l_atom = l_iter->cur; + uint32_t l_cycles_count = 0; + while (l_atom && l_atom_size) { + if (l_iter->cur_num > atomic_load_explicit(&l_context->allowed_num, memory_order_acquire)) + break; + dap_chain_ch_pkt_t *l_pkt = dap_chain_ch_pkt_new(l_context->net_id.uint64, l_context->chain_id.uint64, l_context->cell_id.uint64, + l_atom, l_atom_size); + // For master format binary complience + l_pkt->hdr.num_lo = l_iter->cur_num & 0xFFFF; + l_pkt->hdr.num_hi = (l_iter->cur_num >> 16) & 0xFF; + dap_stream_ch_pkt_send_by_addr(&l_context->addr, DAP_CHAIN_CH_ID, DAP_CHAIN_CH_PKT_TYPE_CHAIN, l_pkt, dap_chain_ch_pkt_get_size(l_pkt)); + DAP_DELETE(l_pkt); + debug_if(s_debug_more, L_DEBUG, "Out: CHAIN %s for net %s to destination " NODE_ADDR_FP_STR " with num %" DAP_UINT64_FORMAT_U + " hash %s and size %zu", + l_chain ? l_chain->name : "(null)", + l_chain ? l_chain->net_name : "(null)", + NODE_ADDR_FP_ARGS_S(l_context->addr), + l_iter->cur_num, dap_hash_fast_to_str_static(l_iter->cur_hash), l_iter->cur_size); + l_atom = l_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_NEXT, &l_atom_size); + if (!l_atom || !l_atom_size || l_iter->cur_num > l_context->num_last) + break; + if (atomic_exchange(&l_context->state, SYNC_STATE_BUSY) == SYNC_STATE_OVER) { + atomic_store(&l_context->state, SYNC_STATE_OVER); + return false; + } + if (++l_cycles_count >= s_sync_packets_per_thread_call) + return true; + } + uint16_t l_state = l_atom && l_atom_size && l_iter->cur_num <= l_context->num_last + ? SYNC_STATE_IDLE : SYNC_STATE_OVER; + uint16_t l_prev_state = atomic_exchange(&l_context->state, l_state); + if (l_prev_state == SYNC_STATE_OVER && l_state != SYNC_STATE_OVER) + atomic_store(&l_context->state, SYNC_STATE_OVER); + if (l_prev_state == SYNC_STATE_READY) // Allowed num was changed since last state updating + return true; + return false; +} +static bool s_chain_iter_delete_callback(void *a_arg) +{ + struct sync_context *l_context = a_arg; + assert(l_context->iter); + l_context->iter->chain->callback_atom_iter_delete(l_context->iter); + DAP_DELETE(l_context); + return false; } /** @@ -1176,13 +1453,26 @@ static void s_free_log_list_gdb ( dap_chain_ch_t * a_ch_chain) */ static void s_ch_chain_go_idle(dap_chain_ch_t *a_ch_chain) { - if (a_ch_chain->state == CHAIN_STATE_IDLE) { + // New protocol + if (a_ch_chain->sync_context) { + atomic_store(&((struct sync_context *)a_ch_chain->sync_context)->state, SYNC_STATE_OVER); + dap_proc_thread_callback_add(DAP_STREAM_CH(a_ch_chain)->stream_worker->worker->proc_queue_input, + s_chain_iter_delete_callback, a_ch_chain->sync_context); + a_ch_chain->sync_context = NULL; + } + if (a_ch_chain->sync_timer) { + dap_timerfd_delete_unsafe(a_ch_chain->sync_timer); + a_ch_chain->sync_timer = NULL; + } +//} + // Legacy + if (a_ch_chain->state == DAP_CHAIN_CH_STATE_IDLE) { return; } - a_ch_chain->state = CHAIN_STATE_IDLE; + a_ch_chain->state = DAP_CHAIN_CH_STATE_IDLE; if(s_debug_more) - log_it(L_INFO, "Go in CHAIN_STATE_IDLE"); + log_it(L_INFO, "Go in DAP_CHAIN_CH_STATE_IDLE"); // Cleanup after request memset(&a_ch_chain->request, 0, sizeof(a_ch_chain->request)); @@ -1202,7 +1492,6 @@ static void s_ch_chain_go_idle(dap_chain_ch_t *a_ch_chain) } a_ch_chain->remote_atoms = NULL; a_ch_chain->sent_breaks = 0; - s_free_log_list_gdb(a_ch_chain); } struct chain_io_complete { @@ -1233,14 +1522,14 @@ static void s_stream_ch_io_complete(dap_events_socket_t *a_es, void *a_arg) return; dap_stream_ch_t *l_ch = NULL; for (size_t i = 0; i < l_stream->channel_count; i++) - if (l_stream->channel[i]->proc->id == DAP_STREAM_CH_CHAIN_ID) + if (l_stream->channel[i]->proc->id == DAP_CHAIN_CH_ID) l_ch = l_stream->channel[i]; - if (!l_ch || !DAP_STREAM_CH_CHAIN(l_ch)) + if (!l_ch || !DAP_CHAIN_CH(l_ch)) return; if (a_arg) { struct chain_io_complete *l_arg = (struct chain_io_complete *)a_arg; - if (DAP_STREAM_CH_CHAIN(l_ch)->state == CHAIN_STATE_WAITING) - DAP_STREAM_CH_CHAIN(l_ch)->state = l_arg->state; + if (DAP_CHAIN_CH(l_ch)->state == DAP_CHAIN_CH_STATE_WAITING) + DAP_CHAIN_CH(l_ch)->state = l_arg->state; dap_chain_ch_pkt_write_unsafe(l_ch, l_arg->type, l_arg->net_id, l_arg->chain_id, l_arg->cell_id, l_arg->data, l_arg->data_size); a_es->callbacks.arg = NULL; @@ -1260,8 +1549,8 @@ static void s_stream_ch_chain_pkt_write(dap_stream_ch_t *a_ch, uint8_t a_type, u if (l_free_buf_size < a_data_size) { struct chain_io_complete *l_arg = DAP_NEW_Z_SIZE(struct chain_io_complete, sizeof(struct chain_io_complete) + a_data_size); l_arg->ch_uuid = a_ch->uuid; - l_arg->state = DAP_STREAM_CH_CHAIN(a_ch)->state; - DAP_STREAM_CH_CHAIN(a_ch)->state = CHAIN_STATE_WAITING; + l_arg->state = DAP_CHAIN_CH(a_ch)->state; + DAP_CHAIN_CH(a_ch)->state = DAP_CHAIN_CH_STATE_WAITING; l_arg->type = a_type; l_arg->net_id = a_net_id; l_arg->chain_id = a_chain_id; @@ -1281,7 +1570,7 @@ static void s_stream_ch_chain_pkt_write(dap_stream_ch_t *a_ch, uint8_t a_type, u */ static bool s_stream_ch_packet_out(dap_stream_ch_t *a_ch, void *a_arg) { - dap_chain_ch_t *l_ch_chain = DAP_STREAM_CH_CHAIN(a_ch); + dap_chain_ch_t *l_ch_chain = DAP_CHAIN_CH(a_ch); if (!l_ch_chain) { log_it(L_CRITICAL, "Channel without chain, dump it"); s_ch_chain_go_idle(l_ch_chain); @@ -1290,7 +1579,7 @@ static bool s_stream_ch_packet_out(dap_stream_ch_t *a_ch, void *a_arg) bool l_go_idle = false, l_was_sent_smth = false; switch (l_ch_chain->state) { // Update list of global DB records to remote - case CHAIN_STATE_UPDATE_GLOBAL_DB: { + case DAP_CHAIN_CH_STATE_UPDATE_GLOBAL_DB: { #if 0 size_t i, q = // s_update_pack_size; @@ -1305,24 +1594,24 @@ static bool s_stream_ch_packet_out(dap_stream_ch_t *a_ch, void *a_arg) } if (i) { l_was_sent_smth = true; - s_stream_ch_chain_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB, + s_stream_ch_chain_pkt_write(a_ch, DAP_CHAIN_CH_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_data, i * sizeof(dap_chain_ch_update_element_t)); l_ch_chain->stats_request_gdb_processed += i; DAP_DELETE(l_data); DAP_DELETE(l_objs); - debug_if(s_debug_more, L_INFO, "Out: DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB, %zu records", i); + debug_if(s_debug_more, L_INFO, "Out: DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB, %zu records", i); } else if (!l_objs) { l_was_sent_smth = true; 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)); - s_stream_ch_chain_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB_END, + s_stream_ch_chain_pkt_write(a_ch, DAP_CHAIN_CH_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_chain_ch_sync_request_t)); - debug_if(s_debug_more, L_INFO, "Out: DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB_END"); + debug_if(s_debug_more, L_INFO, "Out: DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_END"); l_go_idle = true; } dap_chain_ch_update_element_t l_data[s_update_pack_size]; @@ -1339,31 +1628,31 @@ static bool s_stream_ch_packet_out(dap_stream_ch_t *a_ch, void *a_arg) } if (i) { l_was_sent_smth = true; - s_stream_ch_chain_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB, + s_stream_ch_chain_pkt_write(a_ch, DAP_CHAIN_CH_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_data, i * sizeof(dap_chain_ch_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"); + log_it(L_INFO, "Out: DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB"); } else if (!l_obj) { l_was_sent_smth = true; 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)); - s_stream_ch_chain_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB_END, + s_stream_ch_chain_pkt_write(a_ch, DAP_CHAIN_CH_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_chain_ch_sync_request_t)); if (s_debug_more ) - log_it(L_INFO, "Out: DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB_END"); + log_it(L_INFO, "Out: DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_END"); l_go_idle = true; } #endif } break; // Synchronize GDB - case CHAIN_STATE_SYNC_GLOBAL_DB: { + case DAP_CHAIN_CH_STATE_SYNC_GLOBAL_DB: { #if 0 dap_global_db_pkt_t *l_pkt = NULL; size_t l_pkt_size = 0, i, q = 0; @@ -1393,7 +1682,7 @@ static bool s_stream_ch_packet_out(dap_stream_ch_t *a_ch, void *a_arg) if (l_pkt_size) { l_was_sent_smth = true; // If request was from defined node_addr we update its state - s_stream_ch_chain_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_GLOBAL_DB, + s_stream_ch_chain_pkt_write(a_ch, DAP_CHAIN_CH_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); debug_if(s_debug_more, L_INFO, "Send one global_db packet, size %zu, rest %zu/%zu items", l_pkt_size, @@ -1405,12 +1694,12 @@ static bool s_stream_ch_packet_out(dap_stream_ch_t *a_ch, void *a_arg) l_was_sent_smth = true; // last message dap_chain_ch_sync_request_t l_request = { }; - s_stream_ch_chain_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB, + s_stream_ch_chain_pkt_write(a_ch, DAP_CHAIN_CH_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_go_idle = true; 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, + l_ch_chain->callback_notify_packet_out(l_ch_chain, DAP_CHAIN_CH_PKT_TYPE_SYNCED_GLOBAL_DB, NULL, 0, l_ch_chain->callback_notify_arg); log_it(L_INFO,"Syncronized database: items syncronyzed %"DAP_UINT64_FORMAT_U" of %zu", l_ch_chain->stats_request_gdb_processed, l_ch_chain->request_db_log->items_number); @@ -1464,7 +1753,7 @@ static bool s_stream_ch_packet_out(dap_stream_ch_t *a_ch, void *a_arg) log_it(L_INFO, "Send one global_db packet len=%zu (rest=%zu/%zu 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)); - s_stream_ch_chain_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_GLOBAL_DB, + s_stream_ch_chain_pkt_write(a_ch, DAP_CHAIN_CH_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); @@ -1474,19 +1763,19 @@ static bool s_stream_ch_packet_out(dap_stream_ch_t *a_ch, void *a_arg) l_ch_chain->stats_request_gdb_processed, dap_db_log_list_get_count(l_ch_chain->request_db_log)); // last message dap_chain_ch_sync_request_t l_request = {}; - s_stream_ch_chain_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB, + s_stream_ch_chain_pkt_write(a_ch, DAP_CHAIN_CH_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_go_idle = true; 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, + l_ch_chain->callback_notify_packet_out(l_ch_chain, DAP_CHAIN_CH_PKT_TYPE_SYNCED_GLOBAL_DB, NULL, 0, l_ch_chain->callback_notify_arg); } #endif } break; // Update list of atoms to remote - case CHAIN_STATE_UPDATE_CHAINS:{ + case DAP_CHAIN_CH_STATE_UPDATE_CHAINS:{ dap_chain_ch_update_element_t *l_data = DAP_NEW_Z_SIZE(dap_chain_ch_update_element_t, sizeof(dap_chain_ch_update_element_t) * s_update_pack_size); size_t l_data_size=0; @@ -1495,13 +1784,13 @@ static bool s_stream_ch_packet_out(dap_stream_ch_t *a_ch, void *a_arg) // Shift offset counter l_data_size += sizeof(dap_chain_ch_update_element_t); // Then get next atom - l_ch_chain->request_atom_iter->chain->callback_atom_iter_get_next(l_ch_chain->request_atom_iter, NULL); + l_ch_chain->request_atom_iter->chain->callback_atom_iter_get(l_ch_chain->request_atom_iter, DAP_CHAIN_ITER_OP_NEXT, NULL); } if (l_data_size){ l_was_sent_smth = true; if(s_debug_more) log_it(L_DEBUG,"Out: UPDATE_CHAINS with %zu hashes sent", l_data_size / sizeof(dap_chain_ch_update_element_t)); - s_stream_ch_chain_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_CHAINS, + s_stream_ch_chain_pkt_write(a_ch, DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS, l_ch_chain->request_hdr.net_id.uint64, l_ch_chain->request_hdr.chain_id.uint64, l_ch_chain->request_hdr.cell_id.uint64, @@ -1512,7 +1801,7 @@ static bool s_stream_ch_packet_out(dap_stream_ch_t *a_ch, void *a_arg) if(s_debug_more) log_it(L_INFO,"Out: UPDATE_CHAINS_END sent "); dap_chain_ch_sync_request_t l_request = {}; - s_stream_ch_chain_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_CHAINS_END, + s_stream_ch_chain_pkt_write(a_ch, DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_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, @@ -1524,7 +1813,7 @@ static bool s_stream_ch_packet_out(dap_stream_ch_t *a_ch, void *a_arg) }break; // Synchronize chains - case CHAIN_STATE_SYNC_CHAINS: { + case DAP_CHAIN_CH_STATE_SYNC_CHAINS: { // Process one chain from l_ch_chain->request_atom_iter // Pack loop to skip quicker for(uint_fast16_t k=0; k<s_skip_in_reactor_count && @@ -1555,7 +1844,7 @@ static bool s_stream_ch_packet_out(dap_stream_ch_t *a_ch, void *a_arg) dap_chain_hash_fast_to_str(&l_hash_item->hash, l_atom_hash_str, sizeof(l_atom_hash_str)); log_it(L_INFO, "Out CHAIN pkt: atom hash %s (size %zd) ", l_atom_hash_str, l_ch_chain->request_atom_iter->cur_size); } - s_stream_ch_chain_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_CHAIN, l_ch_chain->request_hdr.net_id.uint64, + s_stream_ch_chain_pkt_write(a_ch, DAP_CHAIN_CH_PKT_TYPE_CHAIN, 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_atom_iter->cur, l_ch_chain->request_atom_iter->cur_size); l_was_sent_smth = true; @@ -1567,7 +1856,7 @@ static bool s_stream_ch_packet_out(dap_stream_ch_t *a_ch, void *a_arg) l_hash_item); } // 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); + l_ch_chain->request_atom_iter->chain->callback_atom_iter_get(l_ch_chain->request_atom_iter, DAP_CHAIN_ITER_OP_NEXT, NULL); if (l_was_sent_smth) break; } @@ -1575,13 +1864,13 @@ static bool s_stream_ch_packet_out(dap_stream_ch_t *a_ch, void *a_arg) dap_chain_ch_sync_request_t l_request = {}; // last message l_was_sent_smth = true; - s_stream_ch_chain_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_CHAINS, + s_stream_ch_chain_pkt_write(a_ch, DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAINS, 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)); log_it( L_INFO,"Synced: %"DAP_UINT64_FORMAT_U" atoms processed", l_ch_chain->stats_request_atoms_processed); l_go_idle = true; 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_CHAINS, NULL, + l_ch_chain->callback_notify_packet_out(l_ch_chain, DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAINS, NULL, 0, l_ch_chain->callback_notify_arg); } } break; diff --git a/modules/chain/dap_chain_ch_pkt.c b/modules/chain/dap_chain_ch_pkt.c index a42b35d439..9149522a97 100644 --- a/modules/chain/dap_chain_ch_pkt.c +++ b/modules/chain/dap_chain_ch_pkt.c @@ -35,7 +35,7 @@ size_t dap_chain_ch_pkt_write_unsafe(dap_stream_ch_t *a_ch, uint8_t a_type, uint const void * a_data, size_t a_data_size) { dap_chain_ch_pkt_t *l_chain_pkt = dap_chain_ch_pkt_new(a_net_id, a_chain_id, a_cell_id, a_data, a_data_size); - size_t l_ret = dap_stream_ch_pkt_write_unsafe(a_ch, a_type, l_chain_pkt, sizeof(dap_chain_ch_pkt_hdr_t) + a_data_size); + size_t l_ret = dap_stream_ch_pkt_write_unsafe(a_ch, a_type, l_chain_pkt, dap_chain_ch_pkt_get_size(l_chain_pkt)); DAP_DELETE(l_chain_pkt); return l_ret; } @@ -47,10 +47,11 @@ dap_chain_ch_pkt_t *dap_chain_ch_pkt_new(uint64_t a_net_id, uint64_t a_chain_id, dap_chain_ch_pkt_t *l_chain_pkt = DAP_NEW_Z_SIZE(dap_chain_ch_pkt_t, l_chain_pkt_size); if (l_chain_pkt) { *l_chain_pkt = (dap_chain_ch_pkt_t) { - .hdr = { .version = DAP_STREAM_CH_CHAIN_PKT_VERSION, + .hdr = { .version = DAP_CHAIN_CH_PKT_VERSION, .data_size = a_data_size, .net_id.uint64 = a_net_id, - .cell_id.uint64 = a_cell_id, .chain_id.uint64 = a_chain_id } + .cell_id.uint64 = a_cell_id, + .chain_id.uint64 = a_chain_id } }; if (a_data_size && a_data) memcpy(l_chain_pkt->data, a_data, a_data_size); @@ -79,7 +80,7 @@ size_t dap_chain_ch_pkt_write_mt(dap_stream_worker_t *a_worker, dap_stream_ch_uu ? DAP_NEW_Z_SIZE(dap_chain_ch_pkt_t, l_chain_pkt_size) : DAP_NEW_STACK_SIZE(dap_chain_ch_pkt_t, l_chain_pkt_size); *l_chain_pkt = (dap_chain_ch_pkt_t){ - .hdr = { .version = DAP_STREAM_CH_CHAIN_PKT_VERSION, .net_id.uint64 = a_net_id, .cell_id.uint64 = a_cell_id, .chain_id.uint64 = a_chain_id } + .hdr = { .version = DAP_CHAIN_CH_PKT_VERSION, .net_id.uint64 = a_net_id, .cell_id.uint64 = a_cell_id, .chain_id.uint64 = a_chain_id } }; if (a_data_size && a_data) @@ -100,7 +101,7 @@ size_t dap_chain_ch_pkt_write_multi_mt(dap_stream_ch_cachet_t *a_links, size_t a ? DAP_NEW_Z_SIZE(dap_chain_ch_pkt_t, l_chain_pkt_size) : DAP_NEW_STACK_SIZE(dap_chain_ch_pkt_t, l_chain_pkt_size); *l_chain_pkt = (dap_chain_ch_pkt_t){ - .hdr = { .version = DAP_STREAM_CH_CHAIN_PKT_VERSION, .net_id.uint64 = a_net_id, .cell_id.uint64 = a_cell_id, .chain_id.uint64 = a_chain_id } + .hdr = { .version = DAP_CHAIN_CH_PKT_VERSION, .net_id.uint64 = a_net_id, .cell_id.uint64 = a_cell_id, .chain_id.uint64 = a_chain_id } }; if (a_data_size && a_data) @@ -141,7 +142,7 @@ size_t dap_chain_ch_pkt_write_inter(dap_events_socket_t * a_es_input, dap_stream size_t l_chain_pkt_size = sizeof(dap_chain_ch_pkt_hdr_t) + a_data_size; dap_chain_ch_pkt_t *l_chain_pkt = DAP_NEW_Z_SIZE(dap_chain_ch_pkt_t, l_chain_pkt_size ); *l_chain_pkt = (dap_chain_ch_pkt_t){ - .hdr = { .version = DAP_STREAM_CH_CHAIN_PKT_VERSION, .net_id.uint64 = a_net_id, .cell_id.uint64 = a_cell_id, .chain_id.uint64 = a_chain_id } + .hdr = { .version = DAP_CHAIN_CH_PKT_VERSION, .net_id.uint64 = a_net_id, .cell_id.uint64 = a_cell_id, .chain_id.uint64 = a_chain_id } }; if (a_data_size && a_data) diff --git a/modules/chain/include/dap_chain.h b/modules/chain/include/dap_chain.h index 5b0ad6af2c..59237d9605 100644 --- a/modules/chain/include/dap_chain.h +++ b/modules/chain/include/dap_chain.h @@ -45,13 +45,12 @@ typedef const void * dap_chain_atom_ptr_t; // Atomic element iterator typedef struct dap_chain_atom_iter { dap_chain_t *chain; + dap_chain_cell_id_t cell_id; + void *cur_item; dap_chain_atom_ptr_t cur; size_t cur_size; dap_chain_hash_fast_t *cur_hash; - dap_chain_cell_id_t cell_id; - bool with_treshold; - bool found_in_treshold; - void *cur_item; + uint64_t cur_num; } dap_chain_atom_iter_t; typedef struct dap_chain_datum_iter { @@ -75,6 +74,13 @@ static const char* const dap_chain_atom_verify_res_str[] = { [ATOM_MOVE_TO_THRESHOLD] = "thresholded" }; +typedef enum dap_chain_iter_op { + DAP_CHAIN_ITER_OP_FIRST, + DAP_CHAIN_ITER_OP_LAST, + DAP_CHAIN_ITER_OP_NEXT, + DAP_CHAIN_ITER_OP_PREV +} dap_chain_iter_op_t; + typedef dap_chain_t* (*dap_chain_callback_new_t)(void); typedef void (*dap_chain_callback_t)(dap_chain_t *); @@ -86,9 +92,10 @@ typedef dap_chain_atom_ptr_t (*dap_chain_callback_atom_form_treshold_t)(dap_chai typedef dap_chain_atom_verify_res_t (*dap_chain_callback_atom_verify_t)(dap_chain_t *, dap_chain_atom_ptr_t , size_t); typedef size_t (*dap_chain_callback_atom_get_hdr_size_t)(void); -typedef dap_chain_atom_iter_t* (*dap_chain_callback_atom_iter_create_t)(dap_chain_t *, dap_chain_cell_id_t, bool); -typedef dap_chain_atom_iter_t* (*dap_chain_callback_atom_iter_create_from_t)(dap_chain_t * ,dap_chain_atom_ptr_t, size_t); -typedef dap_chain_atom_ptr_t (*dap_chain_callback_atom_iter_get_first_t)(dap_chain_atom_iter_t * , size_t*); +typedef dap_chain_atom_iter_t * (*dap_chain_callback_atom_iter_create_t)(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, dap_hash_fast_t *a_hash_from); +typedef dap_chain_atom_ptr_t (*dap_chain_callback_atom_iter_get_t)(dap_chain_atom_iter_t *a_iter, dap_chain_iter_op_t a_operation, size_t *a_atom_size); +typedef dap_chain_atom_ptr_t (*dap_chain_callback_atom_iter_find_by_hash_t)(dap_chain_atom_iter_t *a_iter, dap_hash_fast_t *a_atom_hash, size_t *a_atom_size); +typedef void (*dap_chain_callback_atom_iter_delete_t)(dap_chain_atom_iter_t *); typedef dap_chain_datum_iter_t * (*dap_chain_datum_callback_iter_create_t)(dap_chain_t *); typedef dap_chain_datum_t * (*dap_chain_datum_callback_iter_get_first_t)(dap_chain_datum_iter_t *); @@ -98,7 +105,6 @@ typedef void (*dap_chain_datum_callback_iter_delete_t)(dap_chain_datum_iter_t *) typedef dap_chain_datum_t** (*dap_chain_callback_atom_get_datum_t)(dap_chain_atom_ptr_t, size_t, size_t * ); typedef dap_time_t (*dap_chain_callback_atom_get_timestamp_t)(dap_chain_atom_ptr_t); -typedef dap_chain_atom_ptr_t (*dap_chain_callback_atom_iter_find_by_hash_t)(dap_chain_atom_iter_t * ,dap_chain_hash_fast_t *,size_t*); typedef dap_chain_datum_t * (*dap_chain_callback_datum_find_by_hash_t)(dap_chain_t *, dap_chain_hash_fast_t *, dap_chain_hash_fast_t *, int *); typedef dap_chain_atom_ptr_t (*dap_chain_callback_block_find_by_hash_t)(dap_chain_t * ,dap_chain_hash_fast_t *, size_t *); @@ -106,9 +112,6 @@ typedef dap_chain_atom_ptr_t (*dap_chain_callback_block_find_by_hash_t)(dap_chai typedef dap_chain_atom_ptr_t * (*dap_chain_callback_atom_iter_get_atoms_t)(dap_chain_atom_iter_t * ,size_t* ,size_t**); typedef size_t (*dap_chain_callback_add_datums_t)(dap_chain_t * , dap_chain_datum_t **, size_t ); -typedef dap_chain_atom_ptr_t (*dap_chain_callback_atom_iter_get_next_t)(dap_chain_atom_iter_t * ,size_t*); -typedef void (*dap_chain_callback_atom_iter_delete_t)(dap_chain_atom_iter_t *); - typedef void (*dap_chain_callback_notify_t)(void *a_arg, dap_chain_t *a_chain, dap_chain_cell_id_t a_id, void *a_atom, size_t a_atom_size); //change in chain happened typedef uint64_t (*dap_chain_callback_get_count)(dap_chain_t *a_chain); @@ -171,10 +174,6 @@ typedef struct dap_chain { dap_chain_callback_add_datums_t callback_add_datums; dap_chain_callback_atom_get_hdr_size_t callback_atom_get_hdr_static_size; // Get atom header's size - dap_chain_callback_atom_iter_create_t callback_atom_iter_create; - dap_chain_callback_atom_iter_create_from_t callback_atom_iter_create_from; - dap_chain_callback_atom_iter_get_first_t callback_atom_iter_get_first; - dap_chain_callback_atom_get_datum_t callback_atom_get_datums; dap_chain_callback_atom_get_timestamp_t callback_atom_get_timestamp; @@ -183,10 +182,11 @@ typedef struct dap_chain { dap_chain_callback_block_find_by_hash_t callback_block_find_by_tx_hash; - dap_chain_callback_atom_iter_get_next_t callback_atom_iter_get_next; - dap_chain_callback_atom_iter_get_atoms_t callback_atom_iter_get_links; - dap_chain_callback_atom_iter_get_atoms_t callback_atom_iter_get_lasts; + dap_chain_callback_atom_iter_create_t callback_atom_iter_create; + dap_chain_callback_atom_iter_get_t callback_atom_iter_get; dap_chain_callback_atom_iter_delete_t callback_atom_iter_delete; + // WRN: No iterator used or changed with it + dap_chain_callback_atom_iter_get_atoms_t callback_atom_iter_get_links; dap_chain_callback_get_count callback_count_tx; dap_chain_callback_get_list callback_get_txs; diff --git a/modules/chain/include/dap_chain_ch.h b/modules/chain/include/dap_chain_ch.h index 225689bb72..010d112b36 100644 --- a/modules/chain/include/dap_chain_ch.h +++ b/modules/chain/include/dap_chain_ch.h @@ -33,20 +33,35 @@ #include "uthash.h" #include "dap_global_db_cluster.h" -#define DAP_CHAIN_NODE_SYNC_TIMEOUT 60 // sec -#define DAP_SYNC_TICKS_PER_SECOND 10 +#define DAP_SYNC_TICKS_PER_SECOND 10 + +typedef enum dap_chain_ch_state { + DAP_CHAIN_CH_STATE_IDLE = 0, + DAP_CHAIN_CH_STATE_WAITING, + DAP_CHAIN_CH_STATE_UPDATE_GLOBAL_DB_REMOTE, // Downloadn GDB hashtable from remote + DAP_CHAIN_CH_STATE_UPDATE_GLOBAL_DB, // Update GDB hashtable to remote + DAP_CHAIN_CH_STATE_SYNC_GLOBAL_DB, + DAP_CHAIN_CH_STATE_UPDATE_CHAINS_REMOTE, // Update chains hashtable from remote + DAP_CHAIN_CH_STATE_UPDATE_CHAINS, // Update chains hashtable to remote + DAP_CHAIN_CH_STATE_SYNC_CHAINS, + DAP_CHAIN_CH_STATE_ERROR +} dap_chain_ch_state_t; + +typedef enum dap_chain_ch_error_type { + DAP_CHAIN_CH_ERROR_SYNC_REQUEST_ALREADY_IN_PROCESS, + DAP_CHAIN_CH_ERROR_INCORRECT_SYNC_SEQUENCE, + DAP_CHAIN_CH_ERROR_CHAIN_PKT_DATA_SIZE, + DAP_CHAIN_CH_ERROR_NET_INVALID_ID, + DAP_CHAIN_CH_ERROR_CHAIN_NOT_FOUND, + DAP_CHAIN_CH_ERROR_ATOM_NOT_FOUND, + DAP_CHAIN_CH_ERROR_UNKNOWN_CHAIN_PKT_TYPE, + DAP_CHAIN_CH_ERROR_GLOBAL_DB_INTERNAL_NOT_SAVED +} dap_chain_ch_error_type_t; typedef struct dap_chain_ch dap_chain_ch_t; typedef void (*dap_chain_ch_callback_packet_t)(dap_chain_ch_t*, uint8_t a_pkt_type, dap_chain_ch_pkt_t *a_pkt, size_t a_pkt_data_size, void * a_arg); -typedef struct dap_chain_atom_item{ - dap_chain_hash_fast_t atom_hash; - dap_chain_atom_ptr_t atom; - size_t atom_size; - UT_hash_handle hh; -} dap_chain_atom_item_t; - typedef struct dap_chain_pkt_item { uint64_t pkt_data_size; byte_t *pkt_data; @@ -61,8 +76,12 @@ typedef struct dap_chain_ch_hash_item{ typedef struct dap_chain_ch { void *_inheritor; + dap_timerfd_t *sync_timer; + void *sync_context; + + // Legacy section // + int state; - dap_chain_ch_state_t state; uint64_t stats_request_atoms_processed; uint64_t stats_request_gdb_processed; @@ -76,7 +95,7 @@ typedef struct dap_chain_ch { dap_chain_ch_pkt_hdr_t request_hdr; dap_list_t *request_db_iter; - int timer_shots; + uint32_t timer_shots; dap_timerfd_t *activity_timer; int sent_breaks; @@ -85,10 +104,10 @@ typedef struct dap_chain_ch { void *callback_notify_arg; } dap_chain_ch_t; -#define DAP_STREAM_CH_CHAIN(a) ((dap_chain_ch_t *) ((a)->internal) ) +#define DAP_CHAIN_CH(a) ((dap_chain_ch_t *) ((a)->internal) ) #define DAP_STREAM_CH(a) ((dap_stream_ch_t *)((a)->_inheritor)) #define DAP_CHAIN_PKT_EXPECT_SIZE 7168 -#define DAP_STREAM_CH_CHAIN_ID 'C' +#define DAP_CHAIN_CH_ID 'C' int dap_chain_ch_init(void); void dap_chain_ch_deinit(void); diff --git a/modules/chain/include/dap_chain_ch_pkt.h b/modules/chain/include/dap_chain_ch_pkt.h index cd200f6fa1..68046ededd 100644 --- a/modules/chain/include/dap_chain_ch_pkt.h +++ b/modules/chain/include/dap_chain_ch_pkt.h @@ -36,50 +36,44 @@ #include "dap_stream_ch.h" -#define DAP_STREAM_CH_CHAIN_PKT_VERSION 0x02 - -#define DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_CHAINS_REQ 0x05 -#define DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_CHAINS_START 0x25 -#define DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_CHAINS 0x35 -#define DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_CHAINS_END 0x45 -#define DAP_STREAM_CH_CHAIN_PKT_TYPE_FIRST_CHAIN 0x20 -#define DAP_STREAM_CH_CHAIN_PKT_TYPE_CHAIN 0x01 -#define DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_CHAINS 0x03 - -#define DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB_REQ 0x06 -#define DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB_START 0x26 -#define DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB 0x36 -#define DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB_END 0x46 -#define DAP_STREAM_CH_CHAIN_PKT_TYPE_FIRST_GLOBAL_DB 0x21 -#define DAP_STREAM_CH_CHAIN_PKT_TYPE_GLOBAL_DB 0x11 -#define DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB 0x13 - -#define DAP_STREAM_CH_CHAIN_PKT_TYPE_DELETE 0xda -#define DAP_STREAM_CH_CHAIN_PKT_TYPE_TIMEOUT 0xfe -#define DAP_STREAM_CH_CHAIN_PKT_TYPE_ERROR 0xff +#define DAP_CHAIN_CH_PKT_VERSION 0x02 + +//Legacy +#define DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_REQ 0x05 +#define DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_START 0x25 +#define DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS 0x35 +#define DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_END 0x45 +#define DAP_CHAIN_CH_PKT_TYPE_FIRST_CHAIN 0x20 +#define DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAINS 0x03 + +#define DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_REQ 0x06 +#define DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_START 0x26 +#define DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB 0x36 +#define DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_END 0x46 +#define DAP_CHAIN_CH_PKT_TYPE_FIRST_GLOBAL_DB 0x21 +#define DAP_CHAIN_CH_PKT_TYPE_GLOBAL_DB 0x11 +#define DAP_CHAIN_CH_PKT_TYPE_SYNCED_GLOBAL_DB 0x13 + +#define DAP_CHAIN_CH_PKT_TYPE_DELETE 0xda +#define DAP_CHAIN_CH_PKT_TYPE_TIMEOUT 0xfe +#define DAP_CHAIN_CH_PKT_TYPE_ERROR 0xff + +// Stable +#define DAP_CHAIN_CH_PKT_TYPE_CHAIN_REQ 0x80 +#define DAP_CHAIN_CH_PKT_TYPE_CHAIN 0x01 +#define DAP_CHAIN_CH_PKT_TYPE_CHAIN_SUMMARY 0x81 +#define DAP_CHAIN_CH_PKT_TYPE_CHAIN_ACK 0x82 +#define DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAIN 0x88 // TSD sections -#define DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_CHAINS_TSD 0x15 -#define DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB_TSD 0x16 - -#define DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_TSD_PROTO 0x0001 // Protocol version -#define DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_TSD_COUNT 0x0002 // Items count -#define DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_TSD_HASH_LAST 0x0003 // Hash of last(s) item -#define DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_TSD_HASH_FIRST 0x0004 // Hash of first(s) item -#define DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_TSD_LAST_ID 0x0100 // Last ID of GDB synced group - -typedef enum dap_chain_ch_state{ - CHAIN_STATE_IDLE=0, - CHAIN_STATE_WAITING, - CHAIN_STATE_UPDATE_GLOBAL_DB_REMOTE, // Downloadn GDB hashtable from remote - CHAIN_STATE_UPDATE_GLOBAL_DB, // Update GDB hashtable to remote - CHAIN_STATE_SYNC_GLOBAL_DB, - CHAIN_STATE_UPDATE_CHAINS_REMOTE, // Update chains hashtable from remote - CHAIN_STATE_UPDATE_CHAINS, // Update chains hashtable to remote - CHAIN_STATE_SYNC_CHAINS, - CHAIN_STATE_SYNC_ALL -} dap_chain_ch_state_t; +#define DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_TSD 0x15 +#define DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_TSD 0x16 +#define DAP_CHAIN_CH_PKT_TYPE_UPDATE_TSD_PROTO 0x0001 // Protocol version +#define DAP_CHAIN_CH_PKT_TYPE_UPDATE_TSD_COUNT 0x0002 // Items count +#define DAP_CHAIN_CH_PKT_TYPE_UPDATE_TSD_HASH_LAST 0x0003 // Hash of last(s) item +#define DAP_CHAIN_CH_PKT_TYPE_UPDATE_TSD_HASH_FIRST 0x0004 // Hash of first(s) item +#define DAP_CHAIN_CH_PKT_TYPE_UPDATE_TSD_LAST_ID 0x0100 // Last ID of GDB synced group typedef struct dap_chain_ch_update_element{ dap_hash_fast_t hash; @@ -89,15 +83,19 @@ typedef struct dap_chain_ch_update_element{ typedef struct dap_chain_ch_sync_request{ dap_chain_node_addr_t node_addr; // Requesting node's address dap_chain_hash_fast_t hash_from; - dap_chain_hash_fast_t hash_to; // unused - uint64_t id_start; - uint64_t id_end; // unused + byte_t unused[96]; } DAP_ALIGN_PACKED dap_chain_ch_sync_request_t; +typedef struct dap_chain_ch_summary { + uint64_t num_cur; + uint64_t num_last; + byte_t reserved[128]; +} DAP_ALIGN_PACKED dap_chain_ch_summary_t; typedef struct dap_chain_ch_pkt_hdr { uint8_t version; - uint8_t padding[3]; + uint8_t num_hi; + uint16_t num_lo; uint32_t data_size; dap_chain_net_id_t net_id; dap_chain_id_t chain_id; @@ -110,14 +108,16 @@ typedef struct dap_chain_ch_pkt { } DAP_ALIGN_PACKED dap_chain_ch_pkt_t; static const char* c_dap_chain_ch_pkt_type_str[]={ - [DAP_STREAM_CH_CHAIN_PKT_TYPE_CHAIN] = "DAP_STREAM_CH_CHAIN_PKT_TYPE_CHAIN", - [DAP_STREAM_CH_CHAIN_PKT_TYPE_GLOBAL_DB] = "DAP_STREAM_CH_CHAIN_PKT_TYPE_GLOBAL_DB", - [DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_CHAINS] = "DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_CHAINS", - [DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB] = "DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB", - [DAP_STREAM_CH_CHAIN_PKT_TYPE_ERROR] = "DAP_STREAM_CH_CHAIN_PKT_TYPE_ERROR" + [DAP_CHAIN_CH_PKT_TYPE_CHAIN] = "DAP_CHAIN_CH_PKT_TYPE_CHAIN", + [DAP_CHAIN_CH_PKT_TYPE_GLOBAL_DB] = "DAP_CHAIN_CH_PKT_TYPE_GLOBAL_DB", + [DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAINS] = "DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAINS", + [DAP_CHAIN_CH_PKT_TYPE_SYNCED_GLOBAL_DB] = "DAP_CHAIN_CH_PKT_TYPE_SYNCED_GLOBAL_DB", + [DAP_CHAIN_CH_PKT_TYPE_ERROR] = "DAP_CHAIN_CH_PKT_TYPE_ERROR" }; +DAP_STATIC_INLINE size_t dap_chain_ch_pkt_get_size(dap_chain_ch_pkt_t *a_pkt) { return sizeof(dap_chain_ch_pkt_hdr_t) + a_pkt->hdr.data_size; } + dap_chain_ch_pkt_t *dap_chain_ch_pkt_new(uint64_t a_net_id, uint64_t a_chain_id, uint64_t a_cell_id, const void *a_data, size_t a_data_size); @@ -160,7 +160,7 @@ inline static DAP_PRINTF_ATTR(5, 6) size_t dap_chain_ch_pkt_write_error_unsafe(d va_start(l_va, a_err_string_format); vsnprintf(l_str, l_size,a_err_string_format, l_va); va_end(l_va); - return dap_chain_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_ERROR, + return dap_chain_ch_pkt_write_unsafe(a_ch, DAP_CHAIN_CH_PKT_TYPE_ERROR, a_net_id, a_chain_id, a_cell_id, l_str, l_size); } return 0; @@ -190,7 +190,7 @@ static inline size_t dap_chain_ch_pkt_write_error_inter(dap_events_socket_t *a_e va_start(l_va, a_err_string_format); vsnprintf(l_str, l_size, a_err_string_format, l_va); va_end(l_va); - return dap_chain_ch_pkt_write_inter(a_es_input, a_ch_uuid, DAP_STREAM_CH_CHAIN_PKT_TYPE_ERROR, + return dap_chain_ch_pkt_write_inter(a_es_input, a_ch_uuid, DAP_CHAIN_CH_PKT_TYPE_ERROR, a_net_id, a_chain_id, a_cell_id, l_str, l_size); } return 0; diff --git a/modules/channel/chain-net/dap_stream_ch_chain_net.c b/modules/channel/chain-net/dap_stream_ch_chain_net.c index 831f04a10e..056a573ce2 100644 --- a/modules/channel/chain-net/dap_stream_ch_chain_net.c +++ b/modules/channel/chain-net/dap_stream_ch_chain_net.c @@ -169,14 +169,14 @@ void s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void* a_arg) break; // received ping request - > send pong request case DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_PING: - //log_it(L_INFO, "Get STREAM_CH_CHAIN_NET_PKT_TYPE_PING"); + //log_it(L_INFO, "Get CHAIN_CH_NET_PKT_TYPE_PING"); dap_stream_ch_chain_net_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_PONG, l_ch_chain_net_pkt->hdr.net_id,NULL, 0); dap_stream_ch_set_ready_to_write_unsafe(a_ch, true); break; // receive pong request -> send nothing case DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_PONG: - //log_it(L_INFO, "Get STREAM_CH_CHAIN_NET_PKT_TYPE_PONG"); + //log_it(L_INFO, "Get CHAIN_CH_NET_PKT_TYPE_PONG"); dap_stream_ch_set_ready_to_write_unsafe(a_ch, false); break; diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c index 05e8dc7b92..1ff166f62e 100644 --- a/modules/net/dap_chain_net.c +++ b/modules/net/dap_chain_net.c @@ -144,6 +144,23 @@ struct block_reward { struct block_reward *prev, *next; }; +enum sync_state { + SYNC_STATE_IDLE, + SYNC_STATE_WAITING, + SYNC_STATE_SYNCED, + SYNC_STATE_ERROR +}; + +struct chain_sync_context { + enum sync_state state, + last_state; + dap_time_t stage_last_activity, + sync_idle_time; + dap_stream_node_addr_t current_link; + dap_chain_t *cur_chain; + dap_chain_cell_t *cur_cell; +}; + /** * @struct dap_chain_net_pvt * @details Private part of chain_net dap object @@ -170,6 +187,8 @@ typedef struct dap_chain_net_pvt{ uint16_t seed_nodes_count; dap_chain_node_info_t **seed_nodes_info; + struct chain_sync_context sync_context; + _Atomic(dap_chain_net_state_t) state, state_target; uint16_t acl_idx; @@ -228,21 +247,17 @@ static const dap_link_manager_callbacks_t s_link_manager_callbacks = { // State machine switchs here static bool s_net_states_proc(void *a_arg); - struct json_object *s_net_states_json_collect(dap_chain_net_t * l_net); - static void s_net_states_notify(dap_chain_net_t * l_net); static void s_nodelist_change_notify(dap_store_obj_t *a_obj, void *a_arg); //static void s_net_proc_kill( dap_chain_net_t * a_net ); static int s_net_init(const char * a_net_name, uint16_t a_acl_idx); - static int s_net_load(dap_chain_net_t *a_net); static int s_net_try_online(dap_chain_net_t *a_net); - static int s_cli_net(int argc, char ** argv, void **a_str_reply); static uint8_t *s_net_set_acl(dap_chain_hash_fast_t *a_pkey_hash); static bool s_new_balancer_link_request(dap_chain_net_t *a_net); - +static void s_sync_timer_callback(void *a_arg); /** * @brief @@ -1976,7 +1991,6 @@ void dap_chain_net_delete(dap_chain_net_t *a_net) HASH_DELETE(hh2, s_net_ids, l_net_item); DAP_DELETE(l_net_item); } - DAP_DEL_Z(PVT(a_net)->poa_nodes_addrs); DAP_DEL_Z(PVT(a_net)->node_info); if (a_net->pub.ledger) { @@ -2120,6 +2134,7 @@ int s_net_init(const char *a_net_name, uint16_t a_acl_idx) = dap_strncpy(l_net_pvt->seed_nodes_info[i]->ext_host, l_host, l_hostlen) - l_net_pvt->seed_nodes_info[i]->ext_host; if (g_node_addr.uint64 == l_addr.uint64) { // We're in PoA seed list, predefine node info regardless of host set in [server] config section + l_net_pvt->node_info = DAP_NEW_Z_SIZE(dap_chain_node_info_t, sizeof(dap_chain_node_info_t) + DAP_HOSTADDR_STRLEN + 1); dap_mempcpy(l_net_pvt->node_info, l_net_pvt->seed_nodes_info[i], dap_chain_node_info_get_size(l_net_pvt->seed_nodes_info[i])); } } @@ -2486,6 +2501,9 @@ int s_net_load(dap_chain_net_t *a_net) } else if (dap_strcmp(l_node_addr_type, "auto")) log_it(L_WARNING, "Unknown node address type will be defalted to 'auto'"); + l_net_pvt->sync_context.sync_idle_time = dap_config_get_item_uint32_default(g_config, "chain", "sync_idle_time", 60); + dap_proc_thread_timer_add(NULL, s_sync_timer_callback, l_net, 1000); + if(dap_link_manager_add_net(l_net->pub.id.uint64, l_net_pvt->nodes_cluster->links_cluster)) { log_it(L_WARNING, "Can't add net %s to link manager", l_net->pub.name); } @@ -2495,6 +2513,107 @@ int s_net_load(dap_chain_net_t *a_net) return 0; } +static void s_ch_in_pkt_callback(dap_stream_ch_t *a_ch, uint8_t a_type, const void *a_data, size_t a_data_size, void *a_arg) +{ + debug_if(s_debug_more, L_DEBUG, "Got IN sync packet type %hhu size %zu from addr " NODE_ADDR_FP_STR, + a_type, a_data_size, NODE_ADDR_FP_ARGS_S(a_ch->stream->node)); + dap_chain_net_t *l_net = a_arg; + dap_chain_net_pvt_t *l_net_pvt = PVT(l_net); + switch (a_type) { + case DAP_CHAIN_CH_PKT_TYPE_ERROR: + l_net_pvt->sync_context.state = SYNC_STATE_ERROR; + break; + case DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAIN: + l_net_pvt->sync_context.state = SYNC_STATE_SYNCED; + break; + default: + break; + } + l_net_pvt->sync_context.stage_last_activity = dap_time_now(); +} + +static void s_ch_out_pkt_callback(dap_stream_ch_t *a_ch, uint8_t a_type, const void *a_data, size_t a_data_size, void *a_arg) +{ + debug_if(s_debug_more, L_DEBUG, "Sent OUT sync packet type %hhu size %zu to addr " NODE_ADDR_FP_STR, + a_type, a_data_size, NODE_ADDR_FP_ARGS_S(a_ch->stream->node)); + dap_chain_net_t *l_net = a_arg; + dap_chain_net_pvt_t *l_net_pvt = PVT(l_net); + switch (a_type) { + case DAP_CHAIN_CH_PKT_TYPE_ERROR: + l_net_pvt->sync_context.state = SYNC_STATE_ERROR; + break; + default: + break; + } + l_net_pvt->sync_context.stage_last_activity = dap_time_now(); +} + +static void s_sync_timer_callback(void *a_arg) +{ + dap_chain_net_t *l_net = a_arg; + dap_chain_net_pvt_t *l_net_pvt = PVT(l_net); + if (l_net_pvt->state_target == NET_STATE_OFFLINE) + return; + if (l_net_pvt->sync_context.last_state == SYNC_STATE_SYNCED || l_net_pvt->sync_context.last_state == SYNC_STATE_ERROR || + (l_net_pvt->sync_context.last_state == SYNC_STATE_IDLE && l_net_pvt->state != NET_STATE_ONLINE) || + dap_time_now() - l_net_pvt->sync_context.stage_last_activity > l_net_pvt->sync_context.sync_idle_time) { + if (!l_net_pvt->sync_context.cur_chain || l_net_pvt->sync_context.last_state == SYNC_STATE_ERROR) { + // Go no next link + dap_cluster_t *l_cluster = dap_cluster_by_mnemonim(l_net->pub.name); + if (!dap_stream_node_addr_is_blank(&l_net_pvt->sync_context.current_link)) { + dap_stream_ch_del_notifier(&l_net_pvt->sync_context.current_link, DAP_CHAIN_CH_ID, + DAP_STREAM_PKT_DIR_IN, s_ch_in_pkt_callback, l_net); + dap_stream_ch_del_notifier(&l_net_pvt->sync_context.current_link, DAP_CHAIN_CH_ID, + DAP_STREAM_PKT_DIR_OUT, s_ch_out_pkt_callback, l_net); + } + l_net_pvt->sync_context.current_link = dap_cluster_get_random_link(l_cluster); + if (dap_stream_node_addr_is_blank(&l_net_pvt->sync_context.current_link)) + return; // No links in cluster + l_net_pvt->sync_context.cur_chain = l_net->pub.chains; + if (!l_net_pvt->sync_context.cur_chain) { + log_it(L_ERROR, "No chains in net %s", l_net->pub.name); + return; + } + dap_stream_ch_add_notifier(&l_net_pvt->sync_context.current_link, DAP_CHAIN_CH_ID, + DAP_STREAM_PKT_DIR_IN, s_ch_in_pkt_callback, l_net); + dap_stream_ch_add_notifier(&l_net_pvt->sync_context.current_link, DAP_CHAIN_CH_ID, + DAP_STREAM_PKT_DIR_OUT, s_ch_out_pkt_callback, l_net); + l_net_pvt->sync_context.state = l_net_pvt->sync_context.last_state = SYNC_STATE_WAITING; + } else { + l_net_pvt->sync_context.cur_chain = l_net_pvt->sync_context.cur_chain->next; + if (!l_net_pvt->sync_context.cur_chain) { + if (l_net_pvt->sync_context.last_state == SYNC_STATE_SYNCED) { + l_net_pvt->state = NET_STATE_ONLINE; + l_net_pvt->sync_context.state = l_net_pvt->sync_context.last_state = SYNC_STATE_IDLE; + s_net_states_proc(l_net); + } else + l_net_pvt->sync_context.state = l_net_pvt->sync_context.last_state = SYNC_STATE_WAITING; + return; + } + } + // TODO make correct working with cells + assert(l_net_pvt->sync_context.cur_chain); + l_net_pvt->sync_context.cur_cell = l_net_pvt->sync_context.cur_chain->cells; + log_it(L_INFO, "Start synchronization process with " NODE_ADDR_FP_STR " for net %s and chain %s", + NODE_ADDR_FP_ARGS_S(l_net_pvt->sync_context.current_link), + l_net->pub.name, l_net_pvt->sync_context.cur_chain->name); + l_net_pvt->sync_context.state = l_net_pvt->sync_context.last_state = SYNC_STATE_WAITING; + dap_hash_fast_t l_last_hash; + dap_chain_get_atom_last_hash(l_net_pvt->sync_context.cur_chain, &l_last_hash, l_net_pvt->sync_context.cur_cell + ? l_net_pvt->sync_context.cur_cell->id : c_dap_chain_cell_id_null); + dap_chain_ch_pkt_t *l_chain_pkt = dap_chain_ch_pkt_new(l_net->pub.id.uint64, l_net_pvt->sync_context.cur_chain->id.uint64, + l_net_pvt->sync_context.cur_cell ? l_net_pvt->sync_context.cur_cell->id.uint64 : 0, + &l_last_hash, sizeof(l_last_hash)); + dap_stream_ch_pkt_send_by_addr(&l_net_pvt->sync_context.current_link, DAP_CHAIN_CH_ID, + DAP_CHAIN_CH_PKT_TYPE_CHAIN_REQ, l_chain_pkt, + dap_chain_ch_pkt_get_size(l_chain_pkt)); + DAP_DELETE(l_chain_pkt); + } + if (l_net_pvt->sync_context.last_state != SYNC_STATE_IDLE && + l_net_pvt->sync_context.last_state != l_net_pvt->sync_context.state) + l_net_pvt->sync_context.last_state = l_net_pvt->sync_context.state; +} + /** * @brief try net to go online * @@ -3059,8 +3178,8 @@ dap_list_t* dap_chain_datum_list(dap_chain_net_t *a_net, dap_chain_t *a_chain, d { dap_chain_cell_t *l_cell = l_chain_cur->cells; size_t l_atom_size = 0; - dap_chain_atom_iter_t *l_atom_iter = l_chain_cur->callback_atom_iter_create(l_chain_cur, l_cell->id, 0); - dap_chain_atom_ptr_t l_atom = l_chain_cur->callback_atom_iter_get_first(l_atom_iter, &l_atom_size); + dap_chain_atom_iter_t *l_atom_iter = l_chain_cur->callback_atom_iter_create(l_chain_cur, l_cell->id, NULL); + dap_chain_atom_ptr_t l_atom = l_chain_cur->callback_atom_iter_get(l_atom_iter, DAP_CHAIN_ITER_OP_FIRST, &l_atom_size); while(l_atom && l_atom_size) { size_t l_datums_count = 0; @@ -3092,7 +3211,7 @@ dap_list_t* dap_chain_datum_list(dap_chain_net_t *a_net, dap_chain_t *a_chain, d } DAP_DEL_Z(l_datums); // go to next transaction - l_atom = l_chain_cur->callback_atom_iter_get_next(l_atom_iter, &l_atom_size); + l_atom = l_chain_cur->callback_atom_iter_get(l_atom_iter, DAP_CHAIN_ITER_OP_NEXT, &l_atom_size); } l_chain_cur->callback_atom_iter_delete(l_atom_iter); } diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c index 785eb810a5..a85fe65d9a 100644 --- a/modules/net/dap_chain_node_cli_cmd.c +++ b/modules/net/dap_chain_node_cli_cmd.c @@ -1159,7 +1159,7 @@ int com_node(int a_argc, char ** a_argv, void **a_str_reply) log_it(L_NOTICE, "Stream connection established"); dap_chain_ch_sync_request_t l_sync_request = {}; - dap_stream_ch_t *l_ch_chain = dap_client_get_stream_ch_unsafe(l_node_client->client, DAP_STREAM_CH_CHAIN_ID); + dap_stream_ch_t *l_ch_chain = dap_client_get_stream_ch_unsafe(l_node_client->client, DAP_CHAIN_CH_ID); // fill begin id l_sync_request.id_start = 1; // fill current node address @@ -1167,7 +1167,7 @@ int com_node(int a_argc, char ** a_argv, void **a_str_reply) log_it(L_INFO, "Requested GLOBAL_DB syncronizatoin, %"DAP_UINT64_FORMAT_U":%"DAP_UINT64_FORMAT_U" period", l_sync_request.id_start, l_sync_request.id_end); - if(0 == dap_chain_ch_pkt_write_unsafe(l_ch_chain, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_GLOBAL_DB, + if(0 == dap_chain_ch_pkt_write_unsafe(l_ch_chain, DAP_CHAIN_CH_PKT_TYPE_SYNC_GLOBAL_DB, l_net->pub.id.uint64, 0, 0, &l_sync_request, sizeof(l_sync_request))) { dap_cli_server_cmd_set_reply_text(a_str_reply, "Error: Can't send sync chains request"); @@ -1202,7 +1202,7 @@ int com_node(int a_argc, char ** a_argv, void **a_str_reply) dap_chain_node_client_reset(l_node_client); // send request dap_chain_ch_sync_request_t l_sync_request = {}; - if(0 == dap_chain_ch_pkt_write_unsafe(l_ch_chain, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNC_CHAINS, + if(0 == dap_chain_ch_pkt_write_unsafe(l_ch_chain, DAP_CHAIN_CH_PKT_TYPE_SYNC_CHAINS, l_net->pub.id.uint64, l_chain->id.uint64, l_remote_node_info->hdr.cell_id.uint64, &l_sync_request, sizeof(l_sync_request))) { dap_cli_server_cmd_set_reply_text(a_str_reply, "Error: Can't send sync chains request"); @@ -7702,7 +7702,7 @@ static int s_check_cmd(int a_arg_index, int a_argc, char **a_argv, void **a_str_ size_t l_atom_size = 0, l_datums_count = 0; HASH_ITER(hh, l_chain->cells, l_cell, l_cell_tmp) { - l_iter = l_cell->chain->callback_atom_iter_create(l_cell->chain, l_cell->id, 0); + l_iter = l_cell->chain->callback_atom_iter_create(l_cell->chain, l_cell->id, NULL); dap_chain_atom_ptr_t l_atom = l_cell->chain->callback_atom_find_by_hash(l_iter, &l_hash_tmp, &l_atom_size); dap_chain_datum_t **l_datums = l_cell->chain->callback_atom_get_datums(l_atom, l_atom_size, &l_datums_count); for (size_t i = 0; i < l_datums_count; i++) { diff --git a/modules/net/dap_chain_node_cli_cmd_tx.c b/modules/net/dap_chain_node_cli_cmd_tx.c index 5c00beb02b..db41574ba2 100644 --- a/modules/net/dap_chain_node_cli_cmd_tx.c +++ b/modules/net/dap_chain_node_cli_cmd_tx.c @@ -631,9 +631,9 @@ json_object *dap_db_history_tx_all(dap_chain_t *l_chain, dap_chain_net_t *l_net, } size_t i_tmp = 1; HASH_ITER(hh, l_chain->cells, l_cell, l_cell_tmp) { - l_iter = l_chain->callback_atom_iter_create(l_chain, l_cell->id, 0); + l_iter = l_chain->callback_atom_iter_create(l_chain, l_cell->id, NULL); size_t l_atom_size = 0; - dap_chain_atom_ptr_t l_ptr = l_chain->callback_atom_iter_get_first(l_iter, &l_atom_size); + dap_chain_atom_ptr_t l_ptr = l_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_FIRST, &l_atom_size); while (l_ptr && l_atom_size) { size_t l_datums_count = 0; dap_chain_datum_t **l_datums = l_cell->chain->callback_atom_get_datums(l_ptr, l_atom_size, &l_datums_count); @@ -663,7 +663,7 @@ json_object *dap_db_history_tx_all(dap_chain_t *l_chain, dap_chain_net_t *l_net, } } DAP_DEL_Z(l_datums); - l_ptr = l_chain->callback_atom_iter_get_next(l_iter, &l_atom_size); + l_ptr = l_chain->callback_atom_iter_get(l_iter, DAP_CHAIN_ITER_OP_NEXT, &l_atom_size); } l_cell->chain->callback_atom_iter_delete(l_iter); } @@ -700,13 +700,13 @@ static char* dap_db_chain_history_token_list(dap_chain_t * a_chain, const char * size_t l_atom_size = 0; dap_chain_cell_t *l_cell = a_chain->cells; do { - dap_chain_atom_iter_t *l_atom_iter = a_chain->callback_atom_iter_create(a_chain, l_cell->id, 0); + dap_chain_atom_iter_t *l_atom_iter = a_chain->callback_atom_iter_create(a_chain, l_cell->id, NULL); if(!a_chain->callback_atom_get_datums) { log_it(L_DEBUG, "Not defined callback_atom_get_datums for chain \"%s\"", a_chain->name); return NULL ; } - for (dap_chain_atom_ptr_t l_atom = a_chain->callback_atom_iter_get_first(l_atom_iter, &l_atom_size); - l_atom && l_atom_size; l_atom = a_chain->callback_atom_iter_get_next(l_atom_iter, &l_atom_size)) { + for (dap_chain_atom_ptr_t l_atom = a_chain->callback_atom_iter_get(l_atom_iter, DAP_CHAIN_ITER_OP_FIRST, &l_atom_size); + l_atom && l_atom_size; l_atom = a_chain->callback_atom_iter_get(l_atom_iter, DAP_CHAIN_ITER_OP_NEXT, &l_atom_size)) { size_t l_datums_count = 0; dap_chain_datum_t **l_datums = a_chain->callback_atom_get_datums(l_atom, l_atom_size, &l_datums_count); for(size_t l_datum_n = 0; l_datum_n < l_datums_count; l_datum_n++) { @@ -790,11 +790,11 @@ static char* dap_db_history_filter(dap_chain_t * a_chain, dap_ledger_t *a_ledger do { // load transactions size_t l_atom_size = 0; - dap_chain_atom_iter_t *l_atom_iter = a_chain->callback_atom_iter_create(a_chain, l_cell->id, 0); + dap_chain_atom_iter_t *l_atom_iter = a_chain->callback_atom_iter_create(a_chain, l_cell->id, NULL); size_t l_datum_num = 0, l_token_num = 0, l_emission_num = 0, l_tx_num = 0; size_t l_datum_num_global = a_total_datums ? *a_total_datums : 0; - for (dap_chain_atom_ptr_t l_atom = a_chain->callback_atom_iter_get_first(l_atom_iter, &l_atom_size); - l_atom && l_atom_size; l_atom = a_chain->callback_atom_iter_get_next(l_atom_iter, &l_atom_size)) { + for (dap_chain_atom_ptr_t l_atom = a_chain->callback_atom_iter_get(l_atom_iter, DAP_CHAIN_ITER_OP_FIRST, &l_atom_size); + l_atom && l_atom_size; l_atom = a_chain->callback_atom_iter_get(l_atom_iter, DAP_CHAIN_ITER_OP_NEXT, &l_atom_size)) { size_t l_datums_count = 0; dap_chain_datum_t **l_datums = a_chain->callback_atom_get_datums(l_atom, l_atom_size, &l_datums_count); if (!l_datums || !l_datums_count) diff --git a/modules/net/dap_chain_node_client.c b/modules/net/dap_chain_node_client.c index 14f7bdeddb..9caed1f5bc 100644 --- a/modules/net/dap_chain_node_client.c +++ b/modules/net/dap_chain_node_client.c @@ -181,13 +181,13 @@ dap_chain_node_sync_status_t dap_chain_node_client_start_sync(dap_chain_node_cli // check if esocket still in worker dap_stream_ch_t *l_ch = dap_stream_ch_find_by_uuid_unsafe(a_node_client->stream_worker, a_node_client->ch_chain_uuid); if (l_ch) { - dap_chain_ch_t *l_ch_chain = DAP_STREAM_CH_CHAIN(l_ch); + dap_chain_ch_t *l_ch_chain = DAP_CHAIN_CH(l_ch); assert(l_ch_chain); dap_chain_net_t * l_net = a_node_client->net; assert(l_net); // If we do nothing - init sync process - if (l_ch_chain->state == CHAIN_STATE_IDLE) { + if (l_ch_chain->state == DAP_CHAIN_CH_STATE_IDLE) { // bool l_trylocked = dap_chain_net_sync_trylock(l_net, a_node_client); bool l_trylocked = true; if (l_trylocked) { @@ -197,7 +197,7 @@ dap_chain_node_sync_status_t dap_chain_node_client_start_sync(dap_chain_node_cli dap_chain_ch_sync_request_t l_sync_chain = {}; l_sync_chain.node_addr.uint64 = dap_chain_net_get_cur_addr_int(l_net); dap_chain_ch_pkt_write_unsafe(a_node_client->ch_chain, - DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_CHAINS_REQ, + DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_REQ, l_net->pub.id.uint64, l_net->pub.chains->id.uint64, 0, &l_sync_chain, sizeof(l_sync_chain)); if (!l_ch_chain->activity_timer) @@ -362,35 +362,35 @@ static void s_ch_chain_callback_notify_packet_in(dap_chain_ch_t* a_ch_chain, uin l_finished = true; } break; - case DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB_REQ:{ + case DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_REQ:{ l_node_client->state = NODE_CLIENT_STATE_SYNC_GDB_UPDATES; }break; - case DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB_START:{ + case DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB_START:{ l_node_client->state = NODE_CLIENT_STATE_SYNC_GDB_RVRS; dap_chain_net_t * l_net = l_node_client->net; assert(l_net); dap_chain_net_set_state(l_net, NET_STATE_SYNC_GDB); }break; - case DAP_STREAM_CH_CHAIN_PKT_TYPE_FIRST_GLOBAL_DB:{ + case DAP_CHAIN_CH_PKT_TYPE_FIRST_GLOBAL_DB:{ l_node_client->state = NODE_CLIENT_STATE_SYNC_GDB; }break; - case DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_CHAINS_REQ:{ + case DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_REQ:{ l_node_client->state = NODE_CLIENT_STATE_SYNC_CHAINS_UPDATES; }break; - case DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_CHAINS_START:{ + case DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_START:{ l_node_client->state = NODE_CLIENT_STATE_SYNC_CHAINS_RVRS; dap_chain_net_t * l_net = l_node_client->net; assert(l_net); dap_chain_net_set_state(l_net, NET_STATE_SYNC_CHAINS); }break; - case DAP_STREAM_CH_CHAIN_PKT_TYPE_FIRST_CHAIN:{ + case DAP_CHAIN_CH_PKT_TYPE_FIRST_CHAIN:{ l_node_client->state = NODE_CLIENT_STATE_SYNC_CHAINS; }break; - case DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB: - case DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_CHAINS: { + case DAP_CHAIN_CH_PKT_TYPE_SYNCED_GLOBAL_DB: + case DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAINS: { dap_chain_id_t l_chain_id = {}; dap_chain_cell_id_t l_cell_id = {}; - if (a_pkt_type == DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB) { + if (a_pkt_type == DAP_CHAIN_CH_PKT_TYPE_SYNCED_GLOBAL_DB) { if (dap_chain_net_get_target_state(l_net) != NET_STATE_SYNC_GDB) { if(s_stream_ch_chain_debug_more) log_it(L_INFO,"In: Link %s."NODE_ADDR_FP_STR" synced GDB. Going to update chains", l_net->pub.name, NODE_ADDR_FP_ARGS_S(l_node_client->remote_node_addr )); @@ -434,7 +434,7 @@ static void s_ch_chain_callback_notify_packet_in(dap_chain_ch_t* a_ch_chain, uin log_it(L_INFO,"In: Link %s."NODE_ADDR_FP_STR" started to sync %s chain",l_net->pub.name, NODE_ADDR_FP_ARGS_S(l_node_addr), l_node_client->cur_chain->name ); } - dap_chain_ch_pkt_write_unsafe(l_node_client->ch_chain, DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_CHAINS_REQ, + dap_chain_ch_pkt_write_unsafe(l_node_client->ch_chain, DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS_REQ, l_net->pub.id.uint64 , l_chain_id.uint64,l_cell_id.uint64,NULL,0); } else { // If no - over with sync process @@ -483,20 +483,20 @@ static void s_ch_chain_callback_notify_packet_out(dap_chain_ch_t* a_ch_chain, ui dap_chain_node_client_t * l_node_client = (dap_chain_node_client_t *) a_arg; assert(a_arg); switch (a_pkt_type) { - case DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_GLOBAL_DB: { + case DAP_CHAIN_CH_PKT_TYPE_SYNCED_GLOBAL_DB: { if(s_stream_ch_chain_debug_more) log_it(L_INFO,"Out: global database sent to uplink "NODE_ADDR_FP_STR, NODE_ADDR_FP_ARGS_S(l_node_client->remote_node_addr)); } break; - case DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_CHAINS: { + case DAP_CHAIN_CH_PKT_TYPE_SYNCED_CHAINS: { if(s_stream_ch_chain_debug_more) log_it(L_INFO,"Out: chain %"DAP_UINT64_FORMAT_x" sent to uplink "NODE_ADDR_FP_STR,l_node_client->cur_chain ? l_node_client->cur_chain->id.uint64 : 0, NODE_ADDR_FP_ARGS_S(l_node_client->remote_node_addr)); } break; - case DAP_STREAM_CH_CHAIN_PKT_TYPE_TIMEOUT: - case DAP_STREAM_CH_CHAIN_PKT_TYPE_DELETE: { + case DAP_CHAIN_CH_PKT_TYPE_TIMEOUT: + case DAP_CHAIN_CH_PKT_TYPE_DELETE: { dap_chain_net_t *l_net = l_node_client->net; assert(l_net); log_it(L_DEBUG, "In: State node %s."NODE_ADDR_FP_STR" %s", l_net->pub.name, NODE_ADDR_FP_ARGS_S(g_node_addr), - a_pkt_type == DAP_STREAM_CH_CHAIN_PKT_TYPE_TIMEOUT ? "is timeout for sync" : "stream closed"); + a_pkt_type == DAP_CHAIN_CH_PKT_TYPE_TIMEOUT ? "is timeout for sync" : "stream closed"); l_node_client->state = NODE_CLIENT_STATE_ERROR; if (l_node_client->sync_timer) dap_timerfd_reset_unsafe(l_node_client->sync_timer); @@ -771,7 +771,7 @@ void dap_chain_node_client_close_unsafe(dap_chain_node_client_t *a_node_client) if (a_node_client->stream_worker) { dap_stream_ch_t *l_ch = dap_stream_ch_find_by_uuid_unsafe(a_node_client->stream_worker, a_node_client->ch_chain_uuid); if (l_ch) { - dap_chain_ch_t *l_ch_chain = DAP_STREAM_CH_CHAIN(l_ch); + dap_chain_ch_t *l_ch_chain = DAP_CHAIN_CH(l_ch); l_ch_chain->callback_notify_packet_in = NULL; l_ch_chain->callback_notify_packet_out = NULL; } @@ -930,8 +930,8 @@ static int s_node_client_set_notify_callbacks(dap_client_t *a_client, uint8_t a_ l_ret = 0; switch (a_ch_id) { // 'C' - case DAP_STREAM_CH_CHAIN_ID: { - dap_chain_ch_t *l_ch_chain = DAP_STREAM_CH_CHAIN(l_ch); + case DAP_CHAIN_CH_ID: { + dap_chain_ch_t *l_ch_chain = DAP_CHAIN_CH(l_ch); 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; diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c index 96ec6b4786..4ddb1393bf 100644 --- a/modules/type/blocks/dap_chain_cs_blocks.c +++ b/modules/type/blocks/dap_chain_cs_blocks.c @@ -99,8 +99,7 @@ static dap_chain_atom_verify_res_t s_callback_atom_verify(dap_chain_t * a_chain, // Get block header size static size_t s_callback_atom_get_static_hdr_size(void); -static dap_chain_atom_iter_t *s_callback_atom_iter_create(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, bool a_with_treshold); -static dap_chain_atom_iter_t* s_callback_atom_iter_create_from(dap_chain_t *a_chain, dap_chain_atom_ptr_t a_atom, size_t a_atom_size); +static dap_chain_atom_iter_t *s_callback_atom_iter_create(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, dap_hash_fast_t *a_hash_from); static dap_chain_atom_ptr_t s_callback_atom_iter_find_by_hash(dap_chain_atom_iter_t * a_atom_iter , dap_chain_hash_fast_t * a_atom_hash, size_t * a_atom_size); static dap_chain_datum_t *s_callback_datum_find_by_hash(dap_chain_t *a_chain, dap_chain_hash_fast_t *a_datum_hash, @@ -112,12 +111,9 @@ static dap_chain_datum_t** s_callback_atom_get_datums(dap_chain_atom_ptr_t a_ato static dap_time_t s_chain_callback_atom_get_timestamp(dap_chain_atom_ptr_t a_atom) { return ((dap_chain_block_t *)a_atom)->hdr.ts_created; } static uint256_t s_callback_calc_reward(dap_chain_t *a_chain, dap_hash_fast_t *a_block_hash, dap_pkey_t *a_block_sign_pkey); // Get blocks -static dap_chain_atom_ptr_t s_callback_atom_iter_get_first( dap_chain_atom_iter_t * a_atom_iter, size_t *a_atom_size ); // Get the fisrt block -static dap_chain_atom_ptr_t s_callback_atom_iter_get_next( dap_chain_atom_iter_t * a_atom_iter,size_t *a_atom_size ); // Get the next block +static dap_chain_atom_ptr_t s_callback_atom_iter_get(dap_chain_atom_iter_t *a_atom_iter, dap_chain_iter_op_t a_operation, size_t *a_atom_size); static dap_chain_atom_ptr_t *s_callback_atom_iter_get_links( dap_chain_atom_iter_t * a_atom_iter , size_t *a_links_size, size_t ** a_links_size_ptr ); // Get list of linked blocks -static dap_chain_atom_ptr_t *s_callback_atom_iter_get_lasts( dap_chain_atom_iter_t * a_atom_iter ,size_t *a_links_size, - size_t ** a_lasts_size_ptr ); // Get list of linked blocks //Get list of hashes static dap_list_t *s_block_parse_str_list(char *a_hash_str, size_t * a_hash_size, dap_chain_t * a_chain); @@ -242,13 +238,10 @@ static int s_chain_cs_blocks_new(dap_chain_t * a_chain, dap_config_t * a_chain_c a_chain->callback_atom_get_hdr_static_size = s_callback_atom_get_static_hdr_size; // Get block hdr size a_chain->callback_atom_iter_create = s_callback_atom_iter_create; - a_chain->callback_atom_iter_create_from = s_callback_atom_iter_create_from; a_chain->callback_atom_iter_delete = s_callback_atom_iter_delete; - // Linear pass through - a_chain->callback_atom_iter_get_first = s_callback_atom_iter_get_first; // Get the fisrt element from chain - a_chain->callback_atom_iter_get_next = s_callback_atom_iter_get_next; // Get the next element from chain from the current one - a_chain->callback_atom_iter_get_links = s_callback_atom_iter_get_links; // Get the next element from chain from the current one - a_chain->callback_atom_iter_get_lasts = s_callback_atom_iter_get_lasts; + a_chain->callback_atom_iter_get = s_callback_atom_iter_get; // Linear pass through + + a_chain->callback_atom_iter_get_links = s_callback_atom_iter_get_links; // Datum operations callbacks a_chain->callback_datum_iter_create = s_chain_callback_datum_iter_create; // Datum iterator create @@ -1446,52 +1439,6 @@ static size_t s_callback_atom_get_static_hdr_size(void) return sizeof (dap_chain_block_hdr_t); } -/** - * @brief s_callback_atom_iter_create - * @param a_chain - * @return - */ -static dap_chain_atom_iter_t *s_callback_atom_iter_create(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, bool a_with_treshold) -{ - dap_chain_atom_iter_t * l_atom_iter = DAP_NEW_Z(dap_chain_atom_iter_t); - if (!l_atom_iter) { - log_it(L_CRITICAL, "Memory allocation error"); - return NULL; - } - l_atom_iter->chain = a_chain; - l_atom_iter->cell_id = a_cell_id; - l_atom_iter->with_treshold = a_with_treshold; -#ifdef WIN32 - log_it(L_DEBUG, "! %p create caller id %lu", l_atom_iter, GetThreadId(GetCurrentThread())); -#endif - return l_atom_iter; -} - -/** - * @brief s_callback_atom_iter_create_from - * @param a_chain - * @param a_atom - * @param a_atom_size - * @return - */ -static dap_chain_atom_iter_t* s_callback_atom_iter_create_from(dap_chain_t * a_chain, dap_chain_atom_ptr_t a_atom, size_t a_atom_size) -{ - if (a_atom && a_atom_size){ - dap_chain_hash_fast_t l_atom_hash; - dap_hash_fast(a_atom, a_atom_size, &l_atom_hash); - dap_chain_atom_iter_t * l_atom_iter = s_callback_atom_iter_create(a_chain, a_chain->cells->id, 0); - if (l_atom_iter){ - dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_chain); - l_atom_iter->cur_item = dap_chain_block_cache_get_by_hash(l_blocks, &l_atom_hash); - l_atom_iter->cur = a_atom; - l_atom_iter->cur_size = a_atom_size; - return l_atom_iter; - }else - return NULL; - }else - return NULL; -} - /** * @brief s_callback_atom_iter_find_by_hash * @param a_atom_iter @@ -1499,23 +1446,21 @@ static dap_chain_atom_iter_t* s_callback_atom_iter_create_from(dap_chain_t * a_c * @param a_atom_size * @return */ -static dap_chain_atom_ptr_t s_callback_atom_iter_find_by_hash(dap_chain_atom_iter_t * a_atom_iter, dap_chain_hash_fast_t * a_atom_hash, +static dap_chain_atom_ptr_t s_callback_atom_iter_find_by_hash(dap_chain_atom_iter_t * a_atom_iter, dap_chain_hash_fast_t *a_atom_hash, size_t * a_atom_size) { assert(a_atom_iter); - dap_chain_cs_blocks_pvt_t *l_blocks_pvt = PVT(DAP_CHAIN_CS_BLOCKS(a_atom_iter->chain)); - dap_chain_block_cache_t * l_block_cache = NULL; - pthread_rwlock_rdlock(&l_blocks_pvt->rwlock); - HASH_FIND(hh, l_blocks_pvt->blocks, a_atom_hash, sizeof(*a_atom_hash), l_block_cache); - pthread_rwlock_unlock(&l_blocks_pvt->rwlock); + dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_atom_iter->chain); + dap_chain_block_cache_t *l_block_cache = dap_chain_block_cache_get_by_hash(l_blocks, a_atom_hash); a_atom_iter->cur_item = l_block_cache; if (l_block_cache) { - a_atom_iter->cur = l_block_cache->block; - a_atom_iter->cur_size = l_block_cache->block_size; - } else { - a_atom_iter->cur = NULL; - a_atom_iter->cur_size = 0; - } + a_atom_iter->cur = l_block_cache->block; + a_atom_iter->cur_size = l_block_cache->block_size; + a_atom_iter->cur_hash = &l_block_cache->block_hash; + a_atom_iter->cur_num = l_block_cache->block_number; + } else + *a_atom_iter = (dap_chain_atom_iter_t) { .chain = a_atom_iter->chain, + .cell_id = a_atom_iter->cell_id }; if (a_atom_size) *a_atom_size = a_atom_iter->cur_size; return a_atom_iter->cur; @@ -1578,32 +1523,64 @@ static dap_chain_datum_t** s_callback_atom_get_datums(dap_chain_atom_ptr_t a_ato } /** - * @brief s_callback_atom_iter_get_first - * @param a_atom_iter - * @param a_atom_size + * @brief s_callback_atom_iter_create + * @param a_chain * @return */ -static dap_chain_atom_ptr_t s_callback_atom_iter_get_first( dap_chain_atom_iter_t * a_atom_iter, size_t *a_atom_size ) +static dap_chain_atom_iter_t *s_callback_atom_iter_create(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, dap_hash_fast_t *a_hash_from) { - if(!a_atom_iter) { - log_it(L_CRITICAL, "Invalid argument"); + dap_chain_atom_iter_t * l_atom_iter = DAP_NEW_Z(dap_chain_atom_iter_t); + if (!l_atom_iter) { + log_it(L_CRITICAL, "Memory allocation error"); return NULL; } + l_atom_iter->chain = a_chain; + l_atom_iter->cell_id = a_cell_id; + if (a_hash_from) + s_callback_atom_iter_find_by_hash(l_atom_iter, a_hash_from, NULL); + return l_atom_iter; +} + +/** + * @brief s_callback_atom_iter_get + * @param a_atom_iter + * @param a_operation + * @param a_atom_size + * @return + */ +static dap_chain_atom_ptr_t s_callback_atom_iter_get(dap_chain_atom_iter_t *a_atom_iter, dap_chain_iter_op_t a_operation, size_t *a_atom_size) +{ + dap_return_val_if_fail(a_atom_iter, NULL); dap_chain_cs_blocks_t * l_blocks = DAP_CHAIN_CS_BLOCKS(a_atom_iter->chain); dap_chain_cs_blocks_pvt_t *l_blocks_pvt = l_blocks ? PVT(l_blocks) : NULL; assert(l_blocks_pvt); - //pthread_rwlock_rdlock(&l_blocks_pvt->rwlock); - a_atom_iter->cur_item = l_blocks_pvt->blocks; - if (a_atom_iter->cur_item) { - a_atom_iter->cur = l_blocks_pvt->blocks->block; - a_atom_iter->cur_size = l_blocks_pvt->blocks->block_size; - a_atom_iter->cur_hash = &l_blocks_pvt->blocks->block_hash; - } else { - a_atom_iter->cur = NULL; - a_atom_iter->cur_size = 0; - a_atom_iter->cur_hash = NULL; + pthread_rwlock_rdlock(&l_blocks_pvt->rwlock); + switch (a_operation) { + case DAP_CHAIN_ITER_OP_FIRST: + a_atom_iter->cur_item = l_blocks_pvt->blocks; + break; + case DAP_CHAIN_ITER_OP_LAST: + HASH_LAST(l_blocks_pvt->blocks, a_atom_iter->cur_item); + break; + case DAP_CHAIN_ITER_OP_NEXT: + if (a_atom_iter->cur_item) + a_atom_iter->cur_item = ((dap_chain_block_cache_t *)a_atom_iter->cur_item)->hh.next; + break; + case DAP_CHAIN_ITER_OP_PREV: + if (a_atom_iter->cur_item) + a_atom_iter->cur_item = ((dap_chain_block_cache_t *)a_atom_iter->cur_item)->hh.prev; + break; } - //pthread_rwlock_unlock(&l_blocks_pvt->rwlock); + if (a_atom_iter->cur_item) { + dap_chain_block_cache_t *l_item = a_atom_iter->cur_item; + a_atom_iter->cur = l_item->block; + a_atom_iter->cur_size = l_item->block_size; + a_atom_iter->cur_hash = &l_item->block_hash; + a_atom_iter->cur_num = l_item->block_number; + } else + *a_atom_iter = (dap_chain_atom_iter_t) { .chain = a_atom_iter->chain, + .cell_id = a_atom_iter->cell_id }; + pthread_rwlock_unlock(&l_blocks_pvt->rwlock); if (a_atom_size) *a_atom_size = a_atom_iter->cur_size; @@ -1611,31 +1588,12 @@ static dap_chain_atom_ptr_t s_callback_atom_iter_get_first( dap_chain_atom_iter_ } /** - * @brief s_callback_atom_iter_get_next + * @brief s_callback_atom_iter_delete * @param a_atom_iter - * @param a_atom_size - * @return */ -static dap_chain_atom_ptr_t s_callback_atom_iter_get_next(dap_chain_atom_iter_t * a_atom_iter,size_t *a_atom_size ) +static void s_callback_atom_iter_delete(dap_chain_atom_iter_t * a_atom_iter) { - assert(a_atom_iter); - assert(a_atom_iter->cur_item); - - dap_chain_block_cache_t *l_next_item = ((dap_chain_block_cache_t*)a_atom_iter->cur_item)->hh.next; - a_atom_iter->cur_item = l_next_item; - if (a_atom_iter->cur_item) { - a_atom_iter->cur = l_next_item->block; - a_atom_iter->cur_size = l_next_item->block_size; - a_atom_iter->cur_hash = &l_next_item->block_hash; - } else { - a_atom_iter->cur = NULL; - a_atom_iter->cur_size = 0; - a_atom_iter->cur_hash = NULL; - } - if(a_atom_size) - *a_atom_size = a_atom_iter->cur_size; - - return a_atom_iter->cur; + DAP_DELETE(a_atom_iter); } /** @@ -1670,70 +1628,6 @@ static dap_chain_atom_ptr_t *s_callback_atom_iter_get_links(dap_chain_atom_iter_ return l_ret; } -/** - * @brief s_callback_atom_iter_get_lasts - * @param a_atom_iter - * @param a_links_size - * @param a_lasts_size_ptr - * @return - */ -static dap_chain_atom_ptr_t *s_callback_atom_iter_get_lasts( dap_chain_atom_iter_t *a_atom_iter, size_t *a_links_size, size_t **a_lasts_size_ptr) -{ - if(!a_atom_iter) { - log_it(L_CRITICAL, "Invalid argument"); - return NULL; - } - dap_chain_block_cache_t *l_blocks = PVT(DAP_CHAIN_CS_BLOCKS(a_atom_iter->chain))->blocks; - dap_chain_block_cache_t *l_block_cache_last = l_blocks ? l_blocks->hh.tbl->tail->prev : NULL; - l_block_cache_last = l_block_cache_last ? l_block_cache_last->hh.next : l_blocks; - - if (l_block_cache_last) { - a_atom_iter->cur = l_block_cache_last->block; - a_atom_iter->cur_size = l_block_cache_last->block_size; - a_atom_iter->cur_hash = &l_block_cache_last->block_hash; - if (a_lasts_size_ptr) { - *a_lasts_size_ptr = DAP_NEW_Z(size_t); - if (!a_lasts_size_ptr) { - log_it(L_CRITICAL, "Memory allocation error"); - return NULL; - } - (*a_lasts_size_ptr)[0] = l_block_cache_last->block_size; - } - if (a_links_size) - *a_links_size = 1; - dap_chain_atom_ptr_t *l_ret = DAP_NEW_Z(dap_chain_atom_ptr_t); - if (!l_ret) { - log_it(L_CRITICAL, "Memory allocation error"); - if (a_lasts_size_ptr) - DAP_DEL_Z(*a_lasts_size_ptr); - return NULL; - } - l_ret[0] = l_block_cache_last->block; - return l_ret; - } else { - a_atom_iter->cur = NULL; - a_atom_iter->cur_size = 0; - a_atom_iter->cur_hash = NULL; - if (a_links_size) - *a_links_size = 0; - if (a_lasts_size_ptr) - *a_lasts_size_ptr = NULL; - return NULL; - } -} - -/** - * @brief s_callback_atom_iter_delete - * @param a_atom_iter - */ -static void s_callback_atom_iter_delete(dap_chain_atom_iter_t * a_atom_iter) -{ -#ifdef WIN32 - log_it(L_DEBUG, "! %p delete caller id %lu", a_atom_iter, GetThreadId(GetCurrentThread())); -#endif - DAP_DELETE(a_atom_iter); -} - static dap_chain_datum_iter_t *s_chain_callback_datum_iter_create(dap_chain_t *a_chain) { dap_chain_datum_iter_t *l_ret = DAP_NEW_Z(dap_chain_datum_iter_t); diff --git a/modules/type/dag/dap_chain_cs_dag.c b/modules/type/dag/dap_chain_cs_dag.c index 4bbd15ab3f..e7cbf18eb3 100644 --- a/modules/type/dag/dap_chain_cs_dag.c +++ b/modules/type/dag/dap_chain_cs_dag.c @@ -63,6 +63,7 @@ typedef struct dap_chain_cs_dag_event_item { dap_nanotime_t ts_added; dap_chain_cs_dag_event_t *event; size_t event_size; + uint64_t event_number; int ret_code; UT_hash_handle hh, hh_select, hh_datums; } dap_chain_cs_dag_event_item_t; @@ -100,10 +101,7 @@ static dap_chain_atom_ptr_t s_chain_callback_atom_add_from_treshold(dap_chain_t static dap_chain_atom_verify_res_t s_chain_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_ptr_t , size_t); // Verify new event in dag static size_t s_chain_callback_atom_get_static_hdr_size(void); // Get dag event header size -static dap_chain_atom_iter_t* s_chain_callback_atom_iter_create(dap_chain_t * a_chain, dap_chain_cell_id_t a_cell_id, bool a_with_treshold); -static dap_chain_atom_iter_t* s_chain_callback_atom_iter_create_from(dap_chain_t * , - dap_chain_atom_ptr_t , size_t); - +static dap_chain_atom_iter_t* s_chain_callback_atom_iter_create(dap_chain_t * a_chain, dap_chain_cell_id_t a_cell_id, dap_hash_fast_t *a_hash_from); static dap_chain_atom_ptr_t s_chain_callback_atom_iter_find_by_hash(dap_chain_atom_iter_t * a_atom_iter , dap_chain_hash_fast_t * a_atom_hash, size_t * a_atom_size); @@ -112,12 +110,9 @@ static dap_chain_datum_t *s_chain_callback_atom_find_by_datum_hash(dap_chain_t * static dap_chain_datum_t** s_chain_callback_atom_get_datum(dap_chain_atom_ptr_t a_event, size_t a_atom_size, size_t *a_datums_count); static dap_time_t s_chain_callback_atom_get_timestamp(dap_chain_atom_ptr_t a_atom) { return ((dap_chain_cs_dag_event_t *)a_atom)->header.ts_created; } // Get event(s) from dag -static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get_first( dap_chain_atom_iter_t * a_atom_iter, size_t *a_atom_size ); // Get the fisrt event from dag -static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get_next( dap_chain_atom_iter_t * a_atom_iter,size_t *a_atom_size ); // Get the next event from dag +static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get(dap_chain_atom_iter_t *a_atom_iter, dap_chain_iter_op_t a_operation, size_t *a_atom_size); static dap_chain_atom_ptr_t *s_chain_callback_atom_iter_get_links( dap_chain_atom_iter_t * a_atom_iter , size_t *a_links_size, size_t ** a_links_size_ptr ); // Get list of linked events -static dap_chain_atom_ptr_t *s_chain_callback_atom_iter_get_lasts( dap_chain_atom_iter_t * a_atom_iter ,size_t *a_links_size, - size_t ** a_lasts_size_ptr ); // Get list of linked events // Delete iterator static void s_chain_callback_atom_iter_delete(dap_chain_atom_iter_t * a_atom_iter ); // Get the fisrt event from dag @@ -256,18 +251,14 @@ static int s_chain_cs_dag_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg) a_chain->callback_atom_get_hdr_static_size = s_chain_callback_atom_get_static_hdr_size; // Get dag event hdr size a_chain->callback_atom_iter_create = s_chain_callback_atom_iter_create; - a_chain->callback_atom_iter_create_from = s_chain_callback_atom_iter_create_from; a_chain->callback_atom_iter_delete = s_chain_callback_atom_iter_delete; - // Linear pass through - a_chain->callback_atom_iter_get_first = s_chain_callback_atom_iter_get_first; // Get the fisrt element from chain - a_chain->callback_atom_iter_get_next = s_chain_callback_atom_iter_get_next; // Get the next element from chain from the current one - a_chain->callback_atom_iter_get_links = s_chain_callback_atom_iter_get_links; // Get the next element from chain from the current one - a_chain->callback_atom_iter_get_lasts = s_chain_callback_atom_iter_get_lasts; + a_chain->callback_atom_iter_get = s_chain_callback_atom_iter_get; // Linear pass through + a_chain->callback_atom_find_by_hash = s_chain_callback_atom_iter_find_by_hash; // Get element by hash + a_chain->callback_atom_iter_get_links = s_chain_callback_atom_iter_get_links; a_chain->callback_atom_get_datums = s_chain_callback_atom_get_datum; a_chain->callback_atom_get_timestamp = s_chain_callback_atom_get_timestamp; - a_chain->callback_atom_find_by_hash = s_chain_callback_atom_iter_find_by_hash; a_chain->callback_datum_find_by_hash = s_chain_callback_atom_find_by_datum_hash; a_chain->callback_add_datums = s_callback_add_datums; @@ -453,6 +444,7 @@ static int s_dap_chain_add_atom_to_events_table(dap_chain_cs_dag_t *a_dag, dap_c PVT(a_dag)->tx_count++; a_event_item->datum_hash = l_datum_hash; a_event_item->ret_code = l_ret; + a_event_item->event_number = HASH_COUNT(PVT(a_dag)->events) + 1; unsigned l_hash_item_hashv; HASH_VALUE(&l_datum_hash, sizeof(l_datum_hash), l_hash_item_hashv); pthread_mutex_lock(&PVT(a_dag)->events_mutex); @@ -1040,59 +1032,6 @@ static size_t s_chain_callback_atom_get_static_hdr_size() return sizeof (dap_chain_class_dag_event_hdr_t); } -/** - * @brief s_chain_callback_atom_iter_create_from - * @param a_chain - * @param a_atom - * @return - */ -static dap_chain_atom_iter_t* s_chain_callback_atom_iter_create_from(dap_chain_t * a_chain , - dap_chain_atom_ptr_t a_atom, size_t a_atom_size) -{ - dap_chain_atom_iter_t * l_atom_iter = DAP_NEW_Z(dap_chain_atom_iter_t); - if (!l_atom_iter) { - log_it(L_CRITICAL, "Memory allocation error"); - return NULL; - } - l_atom_iter->chain = a_chain; - l_atom_iter->cur = a_atom; - l_atom_iter->cur_size = a_atom_size; - - if ( a_atom ){ - dap_chain_hash_fast_t l_atom_hash; - dap_hash_fast(a_atom, a_atom_size, &l_atom_hash ); - - dap_chain_cs_dag_event_item_t * l_atom_item; - HASH_FIND(hh, PVT(DAP_CHAIN_CS_DAG(a_chain))->events, &l_atom_hash, sizeof(l_atom_hash),l_atom_item ); - l_atom_iter->cur_item = l_atom_item; - l_atom_iter->cur_hash = &l_atom_item->hash; - } - return l_atom_iter; - -} - -/** - * @brief s_chain_callback_atom_iter_create Create atomic element iterator - * @param a_chain - * @return - */ -static dap_chain_atom_iter_t *s_chain_callback_atom_iter_create(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, bool a_with_treshold) -{ - dap_chain_atom_iter_t * l_atom_iter = DAP_NEW_Z(dap_chain_atom_iter_t); - if (!l_atom_iter) { - log_it(L_CRITICAL, "Memory allocation error"); - return NULL; - } - l_atom_iter->chain = a_chain; - l_atom_iter->cell_id = a_cell_id; - l_atom_iter->with_treshold = a_with_treshold; -#ifdef WIN32 - log_it(L_DEBUG, "! %p create caller id %lu", l_atom_iter, GetThreadId(GetCurrentThread())); -#endif - return l_atom_iter; -} - - /** * @brief s_chain_callback_atom_get_datum Get the datum from event * @param a_atom_iter @@ -1119,102 +1058,6 @@ static dap_chain_datum_t **s_chain_callback_atom_get_datum(dap_chain_atom_ptr_t return l_datums; } -/** - * @brief s_chain_callback_atom_iter_get_first Get the first dag event - * @param a_atom_iter - * @return - */ -static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get_first(dap_chain_atom_iter_t * a_atom_iter, size_t * a_ret_size ) -{ - if(! a_atom_iter){ - log_it(L_ERROR, "NULL iterator on input for atom_iter_get_first function"); - return NULL; - } - dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG(a_atom_iter->chain); - assert(l_dag); - dap_chain_cs_dag_pvt_t *l_dag_pvt = PVT(l_dag); - assert(l_dag_pvt); - a_atom_iter->cur_item = NULL; - dap_chain_cs_dag_event_item_t *l_item_tmp, *l_item_cur; - int found = 0; - - pthread_mutex_lock(&PVT(l_dag)->events_mutex); - HASH_ITER(hh, l_dag_pvt->events, l_item_cur, l_item_tmp) { - if (l_item_cur->event->header.cell_id.uint64 == a_atom_iter->cell_id.uint64) { - a_atom_iter->cur_item = l_item_cur; - found = 1; - a_atom_iter->found_in_treshold = 0; - break; - } - } - if (!found && a_atom_iter->with_treshold) { - HASH_ITER(hh, l_dag_pvt->events_treshold, l_item_cur, l_item_tmp) { - if (l_item_cur->event->header.cell_id.uint64 == a_atom_iter->cell_id.uint64) { - a_atom_iter->cur_item = l_item_cur; - a_atom_iter->found_in_treshold = 1; - break; - } - } - } - pthread_mutex_unlock(&PVT(l_dag)->events_mutex); - - if ( a_atom_iter->cur_item ){ - a_atom_iter->cur = ((dap_chain_cs_dag_event_item_t*) a_atom_iter->cur_item)->event; - a_atom_iter->cur_size = ((dap_chain_cs_dag_event_item_t*) a_atom_iter->cur_item)->event_size; - a_atom_iter->cur_hash = &((dap_chain_cs_dag_event_item_t*) a_atom_iter->cur_item)->hash; - }else{ - a_atom_iter->cur = NULL; - a_atom_iter->cur_size = 0; - a_atom_iter->cur_hash = NULL; - } - - if (a_ret_size) - *a_ret_size = a_atom_iter->cur_size; - return a_atom_iter->cur; -} - - -/** - * @brief s_chain_callback_atom_iter_get_lasts - * @param a_atom_iter - * @param a_lasts_size_ptr - * @return - */ -static dap_chain_atom_ptr_t* s_chain_callback_atom_iter_get_lasts( dap_chain_atom_iter_t * a_atom_iter ,size_t * a_lasts_size, - size_t ** a_lasts_size_array ) -{ - dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG( a_atom_iter->chain ); - dap_chain_atom_ptr_t * l_ret = NULL; - pthread_mutex_lock(&PVT(l_dag)->events_mutex); - size_t l_lasts_size = HASH_COUNT( PVT(l_dag)->events_lasts_unlinked ); - if ( l_lasts_size > 0 ) { - if( a_lasts_size) - *a_lasts_size = l_lasts_size; - l_ret = DAP_NEW_Z_SIZE(dap_chain_atom_ptr_t, sizeof(dap_chain_atom_ptr_t) * l_lasts_size); - if (!l_ret) { - log_it(L_CRITICAL, "Memory allocation error"); - pthread_mutex_unlock(&PVT(l_dag)->events_mutex); - return NULL; - } - dap_chain_cs_dag_event_item_t * l_event_item = NULL, *l_event_item_tmp = NULL; - size_t i = 0; - *a_lasts_size_array = DAP_NEW_Z_SIZE(size_t, sizeof(size_t) * l_lasts_size); - if (!*a_lasts_size_array) { - log_it(L_CRITICAL, "Memory allocation error"); - pthread_mutex_unlock(&PVT(l_dag)->events_mutex); - DAP_DEL_Z(l_ret); - return NULL; - } - HASH_ITER(hh,PVT(l_dag)->events_lasts_unlinked, l_event_item,l_event_item_tmp){ - l_ret[i] = l_event_item->event; - (*a_lasts_size_array)[i] = l_event_item->event_size; - i++; - } - } - pthread_mutex_unlock(&PVT(l_dag)->events_mutex); - return l_ret; -} - /** * @brief s_chain_callback_atom_iter_get_links * @param a_atom_iter @@ -1278,111 +1121,102 @@ static dap_chain_atom_ptr_t* s_chain_callback_atom_iter_get_links( dap_chain_ato } /** - * @brief s_chain_callback_atom_iter_find_by_hash - * @param a_atom_iter - * @param a_atom_hash + * @brief s_chain_callback_atom_iter_create Create atomic element iterator + * @param a_chain * @return */ -static dap_chain_atom_ptr_t s_chain_callback_atom_iter_find_by_hash(dap_chain_atom_iter_t * a_atom_iter , - dap_chain_hash_fast_t * a_atom_hash,size_t *a_atom_size) +static dap_chain_atom_iter_t *s_chain_callback_atom_iter_create(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, dap_hash_fast_t *a_hash_from) { - dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG( a_atom_iter->chain ); - dap_chain_cs_dag_event_item_t * l_event_item = NULL; - pthread_mutex_lock(&PVT(l_dag)->events_mutex); - HASH_FIND(hh, PVT(l_dag)->events,a_atom_hash,sizeof(*a_atom_hash),l_event_item); - pthread_mutex_unlock(&PVT(l_dag)->events_mutex); - if ( l_event_item ){ - a_atom_iter->cur_item = l_event_item; - a_atom_iter->cur = l_event_item->event; - a_atom_iter->cur_size= l_event_item->event_size; - a_atom_iter->cur_hash = &l_event_item->hash; - if(a_atom_size) - *a_atom_size = l_event_item->event_size; - return l_event_item->event; - }else + dap_chain_atom_iter_t * l_atom_iter = DAP_NEW_Z(dap_chain_atom_iter_t); + if (!l_atom_iter) { + log_it(L_CRITICAL, "Memory allocation error"); return NULL; + } + l_atom_iter->chain = a_chain; + l_atom_iter->cell_id = a_cell_id; + if (a_hash_from) + s_chain_callback_atom_iter_find_by_hash(l_atom_iter, a_hash_from, NULL); + return l_atom_iter; } /** - * @brief s_chain_callback_atom_find_by_datum_hash - * @param IN a_chain - * @param IN a_datum_hash - * @param OUT a_event_hash - * @param OUT a_ret_code + * @brief s_chain_callback_atom_iter_get Get pointed dag event + * @param a_atom_iter + * @param a_opertaion + * @param a_atom_size * @return */ -static dap_chain_datum_t *s_chain_callback_atom_find_by_datum_hash(dap_chain_t *a_chain, dap_chain_hash_fast_t *a_datum_hash, - dap_chain_hash_fast_t *a_event_hash, int *a_ret_code) +static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get(dap_chain_atom_iter_t *a_atom_iter, dap_chain_iter_op_t a_operation, size_t *a_atom_size) { - dap_chain_cs_dag_t *l_dag = DAP_CHAIN_CS_DAG( a_chain ); - dap_chain_cs_dag_event_item_t *l_event_item = NULL; + dap_return_val_if_fail(a_atom_iter, NULL); + dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG(a_atom_iter->chain); + assert(l_dag); + dap_chain_cs_dag_pvt_t *l_dag_pvt = PVT(l_dag); + assert(l_dag_pvt); pthread_mutex_lock(&PVT(l_dag)->events_mutex); - HASH_FIND(hh_datums, PVT(l_dag)->datums, a_datum_hash, sizeof(*a_datum_hash), l_event_item); - pthread_mutex_unlock(&PVT(l_dag)->events_mutex); - if ( l_event_item ){ - dap_chain_datum_t *l_datum = dap_chain_cs_dag_event_get_datum(l_event_item->event, l_event_item->event_size); - if (l_datum && l_datum->header.data_size) { - if (a_event_hash) - *a_event_hash = l_event_item->hash; - if (a_ret_code) - *a_ret_code = l_event_item->ret_code; - return l_datum; - } + switch (a_operation) { + case DAP_CHAIN_ITER_OP_FIRST: + a_atom_iter->cur_item = l_dag_pvt->events; + break; + case DAP_CHAIN_ITER_OP_LAST: + HASH_LAST(l_dag_pvt->events, a_atom_iter->cur_item); + break; + case DAP_CHAIN_ITER_OP_NEXT: + if (a_atom_iter->cur_item) + a_atom_iter->cur_item = ((dap_chain_cs_dag_event_item_t *)a_atom_iter->cur_item)->hh.next; + break; + case DAP_CHAIN_ITER_OP_PREV: + if (a_atom_iter->cur_item) + a_atom_iter->cur_item = ((dap_chain_cs_dag_event_item_t *)a_atom_iter->cur_item)->hh.prev; + break; } - return NULL; + if (a_atom_iter->cur_item) { + dap_chain_cs_dag_event_item_t *l_item = a_atom_iter->cur_item; + a_atom_iter->cur = l_item->event; + a_atom_iter->cur_size = l_item->event_size; + a_atom_iter->cur_hash = &l_item->hash; + a_atom_iter->cur_num = l_item->event_number; + } else + *a_atom_iter = (dap_chain_atom_iter_t) { .chain = a_atom_iter->chain, + .cell_id = a_atom_iter->cell_id }; + pthread_mutex_unlock(&PVT(l_dag)->events_mutex); + if (a_atom_size) + *a_atom_size = a_atom_iter->cur_size; + return a_atom_iter->cur; } /** - * @brief s_chain_callback_atom_iter_get_next Get the next dag event + * @brief s_chain_callback_atom_iter_find_by_hash * @param a_atom_iter + * @param a_atom_hash * @return */ -static dap_chain_atom_ptr_t s_chain_callback_atom_iter_get_next( dap_chain_atom_iter_t * a_atom_iter,size_t * a_atom_size ) +static dap_chain_atom_ptr_t s_chain_callback_atom_iter_find_by_hash(dap_chain_atom_iter_t *a_atom_iter , + dap_chain_hash_fast_t * a_atom_hash, size_t *a_atom_size) { - dap_chain_cs_dag_event_item_t * l_event_item = (dap_chain_cs_dag_event_item_t*) a_atom_iter->cur_item; - - while (l_event_item) { - l_event_item = (dap_chain_cs_dag_event_item_t *)l_event_item->hh.next; - if (l_event_item && l_event_item->event->header.cell_id.uint64 == a_atom_iter->cell_id.uint64) - break; - } - - if(!l_event_item && !a_atom_iter->found_in_treshold && a_atom_iter->with_treshold) { - dap_chain_cs_dag_t *l_dag = DAP_CHAIN_CS_DAG(a_atom_iter->chain); - assert(l_dag); - dap_chain_cs_dag_pvt_t *l_dag_pvt = PVT(l_dag); - assert(l_dag_pvt); - l_event_item = l_dag_pvt->events_treshold; - pthread_mutex_lock(&PVT(l_dag)->events_mutex); - while (l_event_item) { - if (l_event_item && l_event_item->event->header.cell_id.uint64 == a_atom_iter->cell_id.uint64) { - a_atom_iter->found_in_treshold = 1; - break; - } - l_event_item = (dap_chain_cs_dag_event_item_t *)l_event_item->hh.next; - } - pthread_mutex_unlock(&PVT(l_dag)->events_mutex); - } - // if l_event_item=NULL then items are over + dap_chain_cs_dag_t *l_dag = DAP_CHAIN_CS_DAG(a_atom_iter->chain); + dap_chain_cs_dag_event_item_t *l_event_item = NULL; + pthread_mutex_lock(&PVT(l_dag)->events_mutex); + HASH_FIND(hh, PVT(l_dag)->events, a_atom_hash, sizeof(*a_atom_hash), l_event_item); + pthread_mutex_unlock(&PVT(l_dag)->events_mutex); + if (!l_event_item) + return NULL; a_atom_iter->cur_item = l_event_item; - a_atom_iter->cur = l_event_item ? l_event_item->event : NULL; - a_atom_iter->cur_size = a_atom_iter->cur ? l_event_item->event_size : 0; - a_atom_iter->cur_hash = l_event_item ? &l_event_item->hash : NULL; - if(a_atom_size) - *a_atom_size = a_atom_iter->cur_size; - return a_atom_iter->cur; + a_atom_iter->cur = l_event_item->event; + a_atom_iter->cur_size= l_event_item->event_size; + a_atom_iter->cur_hash = &l_event_item->hash; + a_atom_iter->cur_num = l_event_item->event_number; + if (a_atom_size) + *a_atom_size = l_event_item->event_size; + return l_event_item->event; } - /** * @brief s_chain_callback_atom_iter_delete Delete dag event iterator * @param a_atom_iter */ -static void s_chain_callback_atom_iter_delete(dap_chain_atom_iter_t * a_atom_iter ) +static void s_chain_callback_atom_iter_delete(dap_chain_atom_iter_t *a_atom_iter) { -#ifdef WIN32 - log_it(L_DEBUG, "! Delete caller id %lu", GetThreadId(GetCurrentThread())); -#endif DAP_DELETE(a_atom_iter); } @@ -1419,6 +1253,36 @@ static void s_datum_iter_fill(dap_chain_datum_iter_t *a_datum_iter, dap_chain_cs } } +/** + * @brief s_chain_callback_atom_find_by_datum_hash + * @param IN a_chain + * @param IN a_datum_hash + * @param OUT a_event_hash + * @param OUT a_ret_code + * @return + */ +static dap_chain_datum_t *s_chain_callback_atom_find_by_datum_hash(dap_chain_t *a_chain, dap_chain_hash_fast_t *a_datum_hash, + dap_chain_hash_fast_t *a_event_hash, int *a_ret_code) +{ + dap_chain_cs_dag_t *l_dag = DAP_CHAIN_CS_DAG( a_chain ); + dap_chain_cs_dag_event_item_t *l_event_item = NULL; + pthread_mutex_lock(&PVT(l_dag)->events_mutex); + HASH_FIND(hh_datums, PVT(l_dag)->datums, a_datum_hash, sizeof(*a_datum_hash), l_event_item); + pthread_mutex_unlock(&PVT(l_dag)->events_mutex); + if ( l_event_item ){ + dap_chain_datum_t *l_datum = dap_chain_cs_dag_event_get_datum(l_event_item->event, l_event_item->event_size); + if (l_datum && l_datum->header.data_size) { + if (a_event_hash) + *a_event_hash = l_event_item->hash; + if (a_ret_code) + *a_ret_code = l_event_item->ret_code; + return l_datum; + } + } + return NULL; +} + + static dap_chain_datum_t *s_chain_callback_datum_iter_get_first(dap_chain_datum_iter_t *a_datum_iter) { dap_chain_cs_dag_t *l_dag = DAP_CHAIN_CS_DAG(a_datum_iter->chain); @@ -2193,11 +2057,8 @@ static dap_list_t *s_callback_get_atoms(dap_chain_t *a_chain, size_t a_count, si size_t l_counter = 0; size_t l_end = l_offset + a_count; - dap_chain_cs_dag_event_item_t *l_ptr = l_dag_pvt->events->hh.tbl->tail->prev; - if (!l_ptr) - l_ptr = l_dag_pvt->events; - else - l_ptr = l_ptr->hh.next; + dap_chain_cs_dag_event_item_t *l_ptr; + HASH_LAST(l_dag_pvt->events, l_ptr); for (dap_chain_cs_dag_event_item_t *ptr = l_ptr; ptr != NULL && l_counter < l_end; ptr = ptr->hh.prev){ if (l_counter >= l_offset){ dap_chain_cs_dag_event_t *l_event = ptr->event; diff --git a/modules/type/none/dap_chain_cs_none.c b/modules/type/none/dap_chain_cs_none.c index f04e5104b6..67484a00d4 100644 --- a/modules/type/none/dap_chain_cs_none.c +++ b/modules/type/none/dap_chain_cs_none.c @@ -66,9 +66,7 @@ static dap_chain_atom_verify_res_t s_nonconsensus_callback_atom_add(dap_chain_t static dap_chain_atom_verify_res_t s_nonconsensus_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_ptr_t, size_t); // Verify new event in gdb static size_t s_nonconsensus_callback_atom_get_static_hdr_size(void); // Get gdb event header size -static dap_chain_atom_iter_t* s_nonconsensus_callback_atom_iter_create(dap_chain_t * a_chain, dap_chain_cell_id_t a_cell_id, bool a_with_treshold); -static dap_chain_atom_iter_t* s_nonconsensus_callback_atom_iter_create_from(dap_chain_t * a_chain, - dap_chain_atom_ptr_t a, size_t a_atom_size); +static dap_chain_atom_iter_t* s_nonconsensus_callback_atom_iter_create(dap_chain_t * a_chain, dap_chain_cell_id_t a_cell_id, dap_hash_fast_t *a_hash_from); // Delete iterator static void s_nonconsensus_callback_atom_iter_delete(dap_chain_atom_iter_t * a_atom_iter); // Get the fisrt event from gdb @@ -77,12 +75,8 @@ static dap_chain_atom_ptr_t s_nonconsensus_callback_atom_iter_find_by_hash(dap_c dap_chain_hash_fast_t * a_atom_hash, size_t * a_atom_size); // Get event(s) from gdb -static dap_chain_atom_ptr_t s_nonconsensus_callback_atom_iter_get_first(dap_chain_atom_iter_t * a_atom_iter, size_t * a_atom_size); // Get the fisrt event from gdb -static dap_chain_atom_ptr_t s_nonconsensus_callback_atom_iter_get_next(dap_chain_atom_iter_t * a_atom_iter, size_t * a_atom_size); // Get the next event from gdb -static dap_chain_atom_ptr_t *s_nonconsensus_callback_atom_iter_get_links(dap_chain_atom_iter_t * a_atom_iter, - size_t * a_links_size_ptr, size_t ** a_lasts_sizes_ptr); // Get list of linked events -static dap_chain_atom_ptr_t *s_nonconsensus_callback_atom_iter_get_lasts(dap_chain_atom_iter_t * a_atom_iter, - size_t * a_lasts_size_ptr, size_t ** a_lasts_sizes_ptr); // Get list of linked events +static dap_chain_atom_ptr_t s_nonconsensus_callback_atom_iter_get(dap_chain_atom_iter_t *a_atom_iter, dap_chain_iter_op_t a_operation, size_t *a_atom_size); +static dap_chain_atom_ptr_t *s_nonconsensus_callback_atom_iter_get_links(dap_chain_atom_iter_t *a_atom_iter, size_t *a_links_size_ptr, size_t **a_lasts_sizes_ptr); // Get list of linked events static dap_chain_datum_t **s_nonconsensus_callback_atom_get_datum(dap_chain_atom_ptr_t a_atom, size_t a_atom_size, size_t *a_datums_count); static dap_time_t s_nonconsensus_callback_atom_get_timestamp(dap_chain_atom_ptr_t a_atom) { return ((dap_chain_datum_t *)a_atom)->header.ts_create; } static size_t s_nonconsensus_callback_datums_pool_proc(dap_chain_t * a_chain, dap_chain_datum_t ** a_datums, @@ -191,15 +185,12 @@ static int s_cs_callback_new(dap_chain_t *a_chain, dap_config_t UNUSED_ARG *a_ch a_chain->callback_atom_get_hdr_static_size = s_nonconsensus_callback_atom_get_static_hdr_size; // Get dag event hdr size a_chain->callback_atom_iter_create = s_nonconsensus_callback_atom_iter_create; - a_chain->callback_atom_iter_create_from = s_nonconsensus_callback_atom_iter_create_from; a_chain->callback_atom_iter_delete = s_nonconsensus_callback_atom_iter_delete; - // Linear pass through - a_chain->callback_atom_iter_get_first = s_nonconsensus_callback_atom_iter_get_first; // Get the fisrt element from chain - a_chain->callback_atom_iter_get_next = s_nonconsensus_callback_atom_iter_get_next; // Get the next element from chain from the current one + a_chain->callback_atom_iter_get = s_nonconsensus_callback_atom_iter_get; // Linear pass through a_chain->callback_atom_find_by_hash = s_nonconsensus_callback_atom_iter_find_by_hash; a_chain->callback_atom_iter_get_links = s_nonconsensus_callback_atom_iter_get_links; // Get the next element from chain from the current one - a_chain->callback_atom_iter_get_lasts = s_nonconsensus_callback_atom_iter_get_lasts; + a_chain->callback_atom_get_datums = s_nonconsensus_callback_atom_get_datum; a_chain->callback_atom_get_timestamp = s_nonconsensus_callback_atom_get_timestamp; @@ -251,24 +242,6 @@ const char* dap_nonconsensus_get_group(dap_chain_t * a_chain) } -/** - * @brief compare_datum_items - * @param l_a - * @param l_b - * @return - */ - -/*static int compare_datum_items(const void * l_a, const void * l_b) -{ - const dap_chain_datum_t *l_item_a = (const dap_chain_datum_t*) l_a; - const dap_chain_datum_t *l_item_b = (const dap_chain_datum_t*) l_b; - if(l_item_a->header.ts_create == l_item_b->header.ts_create) - return 0; - if(l_item_a->header.ts_create < l_item_b->header.ts_create) - return -1; - return 1; -}*/ - /** * @brief s_ledger_load_callback * @param a_global_db_context @@ -432,7 +405,7 @@ static size_t s_nonconsensus_callback_atom_get_static_hdr_size() * @param a_chain dap_chain_t a_chain * @return dap_chain_atom_iter_t* */ -static dap_chain_atom_iter_t* s_nonconsensus_callback_atom_iter_create(dap_chain_t * a_chain, dap_chain_cell_id_t a_cell_id, bool a_with_treshold) +static dap_chain_atom_iter_t* s_nonconsensus_callback_atom_iter_create(dap_chain_t * a_chain, dap_chain_cell_id_t a_cell_id, dap_hash_fast_t *a_hash_from) { dap_chain_atom_iter_t * l_iter = DAP_NEW_Z(dap_chain_atom_iter_t); if (!l_iter) { @@ -441,34 +414,11 @@ static dap_chain_atom_iter_t* s_nonconsensus_callback_atom_iter_create(dap_chain } l_iter->chain = a_chain; l_iter->cell_id = a_cell_id; - l_iter->with_treshold = a_with_treshold; - return l_iter; -} - -/** - * @brief create atom object (dap_chain_atom_iter_t) - * - * @param a_chain chain object - * @param a_atom pointer to atom - * @param a_atom_size size of atom - * @return dap_chain_atom_iter_t* - */ -static dap_chain_atom_iter_t* s_nonconsensus_callback_atom_iter_create_from(dap_chain_t * a_chain, - dap_chain_atom_ptr_t a_atom, size_t a_atom_size) -{ - dap_chain_atom_iter_t * l_iter = DAP_NEW_Z(dap_chain_atom_iter_t); - if (!l_iter) { - log_it(L_CRITICAL, "Memory allocation error"); - return NULL; - } - l_iter->chain = a_chain; - l_iter->cur = a_atom; - l_iter->cur_size = a_atom_size; - dap_hash_fast(a_atom, a_atom_size, l_iter->cur_hash); + if (a_hash_from) + s_nonconsensus_callback_atom_iter_find_by_hash(l_iter, a_hash_from, NULL); return l_iter; } - /** * @brief Delete dag event iterator * execute DAP_DELETE(a_atom_iter) @@ -502,6 +452,7 @@ static dap_chain_atom_ptr_t s_nonconsensus_callback_atom_iter_find_by_hash(dap_c l_ret = dap_global_db_get_sync(PVT(l_nochain)->group_datums, l_key, &l_ret_size, NULL, NULL); *a_atom_size = l_ret_size; } + //TODO set a_atom_iter item field return l_ret; } @@ -512,68 +463,45 @@ static dap_chain_atom_ptr_t s_nonconsensus_callback_atom_iter_find_by_hash(dap_c * @param a_atom_size a_atom_size atom size * @return dap_chain_atom_ptr_t */ -static dap_chain_atom_ptr_t s_nonconsensus_callback_atom_iter_get_first(dap_chain_atom_iter_t * a_atom_iter, size_t *a_atom_size) +static dap_chain_atom_ptr_t s_nonconsensus_callback_atom_iter_get(dap_chain_atom_iter_t *a_atom_iter, dap_chain_iter_op_t a_operation, size_t *a_atom_size) { - if (!a_atom_iter) - return NULL; + dap_return_val_if_fail(a_atom_iter, NULL); if (a_atom_iter->cur_item) { /* Iterator creates copies, free them at delete routine! */ DAP_DEL_Z(a_atom_iter->cur); DAP_DEL_Z(a_atom_iter->cur_hash); } - dap_chain_datum_t * l_datum = NULL; - dap_nonconsensus_datum_hash_item_t *l_item = PVT(DAP_NONCONSENSUS(a_atom_iter->chain))->hash_items; - a_atom_iter->cur_item = l_item; - if (a_atom_iter->cur_item) { - size_t l_datum_size = 0; - l_datum = (dap_chain_datum_t*)dap_global_db_get_sync(PVT(DAP_NONCONSENSUS(a_atom_iter->chain))->group_datums, - l_item->key, &l_datum_size, NULL, NULL); - a_atom_iter->cur = l_datum; - a_atom_iter->cur_size = l_datum_size; - a_atom_iter->cur_hash = DAP_NEW_Z(dap_hash_fast_t); - dap_chain_hash_fast_from_str(l_item->key, a_atom_iter->cur_hash); - if (a_atom_size) - *a_atom_size = l_datum_size; - } else { - a_atom_iter->cur_size = 0; - if (a_atom_size) - *a_atom_size = 0; + dap_nonconsensus_datum_hash_item_t *l_head = PVT(DAP_NONCONSENSUS(a_atom_iter->chain))->hash_items; + switch (a_operation) { + case DAP_CHAIN_ITER_OP_FIRST: + a_atom_iter->cur_item = l_head; + break; + case DAP_CHAIN_ITER_OP_LAST: + a_atom_iter->cur_item = l_head ? l_head->prev : NULL; + break; + case DAP_CHAIN_ITER_OP_NEXT: + if (a_atom_iter->cur_item) + a_atom_iter->cur_item = ((dap_nonconsensus_datum_hash_item_t *)a_atom_iter->cur_item)->next; + break; + case DAP_CHAIN_ITER_OP_PREV: + if (a_atom_iter->cur_item) + a_atom_iter->cur_item = ((dap_nonconsensus_datum_hash_item_t *)a_atom_iter->cur_item)->prev->next + ? ((dap_nonconsensus_datum_hash_item_t *)a_atom_iter->cur_item)->prev + : NULL; + break; } - return l_datum; -} - + if (a_atom_iter->cur_item) { + dap_nonconsensus_datum_hash_item_t *l_item = a_atom_iter->cur_item; -/** - * @brief Get the next dag event from database - * - * @param a_atom_iter dap_chain_atom_iter_t - * @param a_atom_size size_t a_atom_size - * @return dap_chain_atom_ptr_t - */ -static dap_chain_atom_ptr_t s_nonconsensus_callback_atom_iter_get_next(dap_chain_atom_iter_t *a_atom_iter, size_t *a_atom_size) -{ - dap_chain_datum_t * l_datum = NULL; - dap_nonconsensus_datum_hash_item_t *l_item = (dap_nonconsensus_datum_hash_item_t*)a_atom_iter->cur_item; - if (l_item) - l_item = l_item->next; - a_atom_iter->cur_item = l_item; - if (a_atom_iter->cur_item ){ - size_t l_datum_size =0; - l_datum = (dap_chain_datum_t *)dap_global_db_get_sync(PVT(DAP_NONCONSENSUS(a_atom_iter->chain))->group_datums, l_item->key, &l_datum_size, NULL, NULL); - if (a_atom_iter->cur) // This iterator should clean up data for it because its allocate it - DAP_DELETE(a_atom_iter->cur); - a_atom_iter->cur = l_datum; - a_atom_iter->cur_size = l_datum_size; + a_atom_iter->cur = dap_global_db_get_sync(PVT(DAP_NONCONSENSUS(a_atom_iter->chain))->group_datums, + l_item->key, &a_atom_iter->cur_size, NULL, NULL); + a_atom_iter->cur_hash = DAP_NEW_Z(dap_hash_fast_t); dap_chain_hash_fast_from_str(l_item->key, a_atom_iter->cur_hash); - if (a_atom_size) - *a_atom_size = l_datum_size; - } else { - DAP_DEL_Z(a_atom_iter->cur_hash); - DAP_DEL_Z(a_atom_iter->cur); - a_atom_iter->cur_size = 0; - if (a_atom_size) - *a_atom_size = 0; - } - return l_datum; + } else + *a_atom_iter = (dap_chain_atom_iter_t) { .chain = a_atom_iter->chain, + .cell_id = a_atom_iter->cell_id }; + if (a_atom_size) + *a_atom_size = a_atom_iter->cur_size; + return a_atom_iter->cur; } /** @@ -593,23 +521,6 @@ static dap_chain_atom_ptr_t* s_nonconsensus_callback_atom_iter_get_links(dap_cha return NULL; } -/** - * @brief return null in current implementation - * - * @param a_atom_iter - * @param a_lasts_size_ptr - * @param a_links_sizes_ptr - * @return dap_chain_atom_ptr_t* - */ -static dap_chain_atom_ptr_t* s_nonconsensus_callback_atom_iter_get_lasts(dap_chain_atom_iter_t * a_atom_iter, - size_t * a_lasts_size_ptr, size_t **a_links_sizes_ptr) -{ - (void) a_atom_iter; - (void) a_lasts_size_ptr; - (void) a_links_sizes_ptr; - return NULL; -} - /** * @brief get new datum object from atom * -- GitLab