diff --git a/modules/global-db/dap_chain_global_db_driver.c b/modules/global-db/dap_chain_global_db_driver.c index a74969e1a74cc075d802debfb4afd30612a5e0df..a7dc81923ba4964f67159b9f2896359c2fbd2087 100644 --- a/modules/global-db/dap_chain_global_db_driver.c +++ b/modules/global-db/dap_chain_global_db_driver.c @@ -185,7 +185,7 @@ dap_store_obj_t *l_store_obj, *l_store_obj_dst, *l_store_obj_src; l_store_obj_dst->key = dap_strdup(l_store_obj_src->key); l_store_obj_dst->value = DAP_DUP_SIZE(l_store_obj_src->value, l_store_obj_src->value_len); l_store_obj_dst->cb = l_store_obj_src->cb; - l_store_obj_dst->cb = l_store_obj_src->cb_arg; + l_store_obj_dst->cb_arg = l_store_obj_src->cb_arg; } return l_store_obj; @@ -311,7 +311,7 @@ size_t l_store_obj_cnt; /* Is there a callback ? */ - if ( l_store_obj_cur->cb ) + if ( s_db_drvmode_async && l_store_obj_cur->cb ) { /* Enqueue "Exec Complete" callback routine */ l_dap_worker = dap_events_worker_get_auto (); diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt new file mode 100755 index 0000000000000000000000000000000000000000..9f06a2e3b17505170ebb0c4787aa5112dd2c6928 --- /dev/null +++ b/test/CMakeLists.txt @@ -0,0 +1,56 @@ +cmake_minimum_required(VERSION 3.4.1) + +project(dap_global_db_test) + +IF (NOT DEFINED DAP_SDK_ROOT) + SET(DAP_SDK_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../cellframe-sdk") + SET(DAP_LIBSDK_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/../../build/cellframe-sdk") +ENDIF() + +ADD_DEFINITIONS(-DDAP_SDK_ROOT=${DAP_SDK_ROOT}) +ADD_DEFINITIONS(-DDAP_LIBSDK_ROOT=${DAP_LIBSDK_ROOT}) + +message(STATUS "Current DAP SDK path is '${DAP_SDK_ROOT}'. + Add '-DDAP_SDK_ROOT=<path_to_sdk>' to cmake if want to change path") +message(STATUS "Current DAP SDK Library path is '${DAP_LIBSDK_ROOT}'. + Add '-DDAP_LIBSDK_ROOT=<path_to_sdk_library>' to cmake if want to change path") + +include_directories( + ${DAP_SDK_ROOT}/dap-sdk/net/core/include/ + ${DAP_SDK_ROOT}/dap-sdk/crypto/src/sha3/ + ${DAP_SDK_ROOT}/dap-sdk/crypto/include/ + ${DAP_SDK_ROOT}/modules/common/include/ + ${DAP_SDK_ROOT}/modules/global-db/include/ + ${DAP_SDK_ROOT}/dap-sdk/net/core/include/ + ${DAP_SDK_ROOT}/dap-sdk/core/include/ + ${DAP_SDK_ROOT}/dap-sdk/core/src/unix/ + ) + +link_directories( + ${DAP_LIBSDK_ROOT}/dap-sdk/core/ + ${DAP_LIBSDK_ROOT}/dap-sdk/net/core/ + ) + +add_executable(dap_global_db_test dap_global_db_test.c) + +target_compile_definitions(dap_global_db_test PRIVATE + -DCELLFRAME_SDK_VERSION="3.0-15" + -DDAP_MODULES_DYNAMIC=1 + -DDAP_OS_LINUX=1 + -DDAP_OS_UNIX=1 + -DDAP_SRV_STAKE_USED=1 + -DDAP_VERSION="5-0.26" + -D_GNU_SOURCE=1 + ) + + +target_link_libraries(dap_global_db_test -pthread -lrt) + +target_link_libraries(dap_global_db_test ${DAP_LIBSDK_ROOT}/modules/global-db/libdap_chain_global_db.a) +target_link_libraries(dap_global_db_test ${DAP_LIBSDK_ROOT}/dap-sdk/crypto/libdap_crypto.a) +target_link_libraries(dap_global_db_test ${DAP_LIBSDK_ROOT}/dap-sdk/net/core/libdap_server_core.a) +target_link_libraries(dap_global_db_test ${DAP_LIBSDK_ROOT}/dap-sdk/core/libdap_core.a) +target_link_libraries(dap_global_db_test ${DAP_LIBSDK_ROOT}/3rdparty/cuttdb/libdap_cuttdb.a) +target_link_libraries(dap_global_db_test -lsqlite3) + +target_link_libraries(dap_global_db_test -pthread -lrt -lm -latomic) diff --git a/test/dap_global_db_test.c b/test/dap_global_db_test.c new file mode 100755 index 0000000000000000000000000000000000000000..1c11007c8f458e1ea6245aedaa7ac415a1e0cbbc --- /dev/null +++ b/test/dap_global_db_test.c @@ -0,0 +1,232 @@ +#include <time.h> +#include <unistd.h> +#include <stdatomic.h> + +#include "dap_common.h" +#include "dap_strfuncs.h" +#include "dap_file_utils.h" +#include "dap_events.h" +#include "dap_proc_thread.h" +#include "dap_proc_queue.h" +#include "dap_hash.h" + +#include "dap_chain_global_db.h" +#include "dap_chain_global_db_driver.h" + +#define LOG_TAG "dap_globaldb_test" + +#define DB_FILE "./base.tmp" + + + +static int s_test_create_db(const char *db_type, int mode) +{ +int rc; +char l_cmd[MAX_PATH]; + + if( dap_dir_test(DB_FILE) ) { + rmdir(DB_FILE); + dap_snprintf(l_cmd, sizeof(l_cmd), "rm -rf %s", DB_FILE); + if ( (rc = system(l_cmd)) ) + log_it(L_ERROR, "system(%s)->%d", l_cmd, rc); + } + else + unlink(DB_FILE); + + if ( rc = dap_db_driver_init(db_type, DB_FILE, mode) ) + return log_it(L_ERROR, "DB driver initialization, dap_db_driver_init(%s, %s)->%d", db_type, DB_FILE, rc), rc; + + + return log_it(L_NOTICE, "%s DB driver has been initialized in %s mode on the %s", db_type, mode ? "Async" : "Sync", DB_FILE), + rc; +} + +typedef struct __dap_test_record__ { + dap_chain_hash_fast_t csum; /* CRC32 , cover <len> and <data> fields */ + unsigned len; /* Length of the <data> field */ + char data[]; /* Place holder for data area */ +} dap_db_test_record_t; + +#define DAP_DB$SZ_DATA 8192 +#define DAP_DB$SZ_KEY 64 +#define DAP_DB$T_GROUP "Group.Zero" + + +static void s_test_cb_end (void *__unused_arg__, const void *arg) +{ +int *l_is_completed = (int *) arg; + + log_it(L_NOTICE, "Callback is called with arg: %p", arg); + atomic_fetch_add(l_is_completed, 1); +} + +static int s_test_write(int a_count, int a_mode) +{ +dap_store_obj_t l_store_obj = {0}; +int l_value_len = 0, *l_pvalue, i, ret, l_key_nr; +atomic_int l_is_completed = 0; +char l_key[64] = {0}, l_value[sizeof(dap_db_test_record_t) + DAP_DB$SZ_DATA] = {0}; +dap_db_test_record_t *prec; +struct timespec now; + + log_it(L_NOTICE, "Start writing %d records ...", a_count); + + /* Fill static part of the <store_object> descriptor */ + l_store_obj.type = DAP_DB$K_OPTYPE_ADD; /* Do INSERT */ + + + l_store_obj.group = DAP_DB$T_GROUP; /* "Table" name */ + l_store_obj.key = l_key; /* Point <.key> to the buffer with the key of record */ + l_store_obj.value = (int8_t *) l_value; /* Point <.value> to static buffer area */ + prec = (dap_db_test_record_t *) l_value; + + for (l_key_nr = 0; l_key_nr < a_count; l_key_nr++ ) + { + + if ( a_mode && (l_key_nr == (a_count - 1)) ) /* Async mode ? Last request ?*/ + { + l_store_obj.cb = s_test_cb_end; /* Callback on request complete should be called */ + l_store_obj.cb_arg = &l_is_completed; + } + + + snprintf(l_key, sizeof(l_key) - 1, "KEY$%08x", l_key_nr); /* Generate a key of record */ + + clock_gettime(CLOCK_REALTIME, &now); /* Get and save record's timestamp */ + l_store_obj.timestamp = (now.tv_sec << 32) | ((uint32_t) (now.tv_nsec)); + + + prec->len = rand() % DAP_DB$SZ_DATA; /* Variable payload length */ + l_pvalue = (int *) prec->data; + + for (int i = prec->len / sizeof(int); i--; l_pvalue++) /* Fill record's payload with random data */ + *l_pvalue = rand(); + + sprintf(prec->data, "DATA$%08x", l_key_nr); /* Just for fun ... */ + l_value_len = prec->len + sizeof(dap_db_test_record_t); + + l_store_obj.value_len = l_value_len; + assert(l_store_obj.value_len < sizeof(l_value)); + + + dap_hash_fast (prec->data, prec->len, &prec->csum); /* Compute a hash of the payload part of the record */ + + + log_it(L_DEBUG, "Store object: [%s, %s, %d octets]", l_store_obj.group, l_store_obj.key, l_store_obj.value_len); + /* Write has been prepared record in to the DB */ + if ( ret = dap_chain_global_db_driver_add(&l_store_obj, 1) ) + return log_it(L_ERROR, "Write record to DB, code: %d", ret), ret; + } + + if ( a_mode ) + { + for ( struct timespec tmo = {0, 300*1024}; !atomic_load(&l_is_completed); tmo.tv_nsec = 300*1024) + { + log_it(L_NOTICE, "Let's finished DB request ..."); + nanosleep(&tmo, &tmo); + } + } + + + return 0; +} + +static int s_test_read(int a_count) +{ +dap_store_obj_t *l_store_obj; +int l_key_nr; +char l_key[64], l_buf[512]; +dap_chain_hash_fast_t csum; +dap_db_test_record_t *prec; + + log_it(L_NOTICE, "Start reading %d records ...", a_count); + + for (l_key_nr = 0; l_key_nr < a_count; l_key_nr++ ) + { + snprintf(l_key, sizeof(l_key) - 1, "KEY$%08x", l_key_nr); /* Generate a key of record */ + + if ( !(l_store_obj = dap_chain_global_db_driver_read(DAP_DB$T_GROUP, l_key, NULL)) ) + return log_it(L_ERROR, "Record-Not-Found for key: %s", l_key), -ENOENT; + + prec = (dap_db_test_record_t *) l_store_obj->value; + + log_it(L_DEBUG, "Retrieved object: [%s, %s, %d octets]", l_store_obj->group, l_store_obj->key, l_store_obj->value_len); + + log_it(L_DEBUG, "Record: ['%.*s', %d octets]", prec->len, prec->data, prec->len); + + + dap_hash_fast (prec->data, prec->len, &csum); /* Compute a hash of the payload part of the record */ + +#if 0 + dap_bin2hex (l_buf, prec->csum, sizeof(csum) ); + log_it(L_DEBUG, "%.*s", 2*DAP_HASH_FAST_SIZE, l_buf); + dap_bin2hex (l_buf, csum, sizeof(csum) ); + log_it(L_DEBUG, "%.*s", 2*DAP_HASH_FAST_SIZE, l_buf); +#endif + + if ( memcmp(&csum, &prec->csum,sizeof(dap_chain_hash_fast_t)) ) /* Integriry checking ... */ + return log_it(L_ERROR, "Record with key: %s, check sum error", l_key), -EINVAL; + } + + return 0; +} + + +static void s_test_close_db(void) +{ + dap_db_driver_deinit(); + log_it(L_NOTICE, "Close global_db"); +} + + +int main (int argc, char **argv) +{ +dap_events_t *l_events; + + dap_set_appname("dap_global_db_test"); /* Facility prefix for loggin purpose */ + + if ( dap_common_init("db_test", "./dbtest.log", "./" ) ) /* Log to console only ! */ + { + fprintf(stderr, "dap_common_init() failed, errno=%d", errno); + return -2; + } + + // log_it( L_ATT, l_debug_mode ? "*** DEBUG MODE ***" : "*** NORMAL MODE ***" ); + dap_log_level_set( L_NOTICE ); + + /* New event loop init */ + dap_events_init( 0, 0 ); + + if ( !(l_events = dap_events_new()) ) + return log_it( L_ERROR, "dap_events_new() failed" ), -4; + + dap_events_start( l_events ); + + /* CuttDB */ + log_it(L_NOTICE, "Start CuttDB R/W test in Sync mode ..."); + s_test_create_db("cdb", 0); + s_test_write(1350, 0); + s_test_read(1350); + s_test_close_db(); + + + log_it(L_NOTICE, "Start CuttDB R/W test in Async mode ..."); + s_test_create_db("cdb", 1); + s_test_write(1350, 1); + s_test_read(1350); + s_test_close_db(); + + /* SQLite3 */ + log_it(L_NOTICE, "Start SQLITE3 R/W test in Sync mode ..."); + s_test_create_db("sqlite", 0); + s_test_write(1350, 0); + s_test_read(1350); + + + log_it(L_NOTICE, "Start SQLITE3 R/W test in Async mode ..."); + s_test_create_db("sqlite", 1); + s_test_write(1350, 1); + s_test_read(1350); + + s_test_close_db(); +}