From 5587a18e4edf1de84b443048a1f817ac6cde80b5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Al=D0=B5x=D0=B0nder=20Lysik=D0=BEv?=
 <alexander.lysikov@demlabs.net>
Date: Fri, 24 May 2019 21:32:04 +0500
Subject: [PATCH] added files dap_chain_global_db_driver.h/c and
 dap_chain_global_db_driver_sqlite.h/c

---
 CMakeLists.txt                      |   2 +-
 dap_chain_global_db.c               |  22 ++--
 dap_chain_global_db_driver.c        |  65 ++++++++++
 dap_chain_global_db_driver.h        |  66 ++++++++++
 dap_chain_global_db_driver_sqlite.c | 191 ++++++++++++++++++++++++++++
 dap_chain_global_db_driver_sqlite.h |  36 ++++++
 dap_chain_global_db_pvt.h           |   4 +-
 7 files changed, 374 insertions(+), 12 deletions(-)
 create mode 100644 dap_chain_global_db_driver.c
 create mode 100644 dap_chain_global_db_driver.h
 create mode 100644 dap_chain_global_db_driver_sqlite.c
 create mode 100644 dap_chain_global_db_driver_sqlite.h

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6ba5ba0..3c18ded 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -6,7 +6,7 @@ file(GLOB DAP_CHAIN_GLOBAL_DB_HDR *.h)
 
 add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_GLOBAL_DB_SRC} ${DAP_CHAIN_GLOBAL_DB_HDR})
 
-target_link_libraries(dap_chain_global_db dap_core dap_crypto dap_chain dap_chain_crypto ldb talloc tevent)
+target_link_libraries(dap_chain_global_db dap_core dap_crypto dap_chain dap_chain_crypto ldb talloc tevent sqlite3)
 target_include_directories(dap_chain_global_db INTERFACE .)
 
 set(${PROJECT_NAME}_DEFINITIONS CACHE INTERNAL "${PROJECT_NAME}: Definitions" FORCE)
diff --git a/dap_chain_global_db.c b/dap_chain_global_db.c
index 76d669f..661bd10 100755
--- a/dap_chain_global_db.c
+++ b/dap_chain_global_db.c
@@ -9,7 +9,8 @@
 #include "dap_hash.h"
 #include "dap_chain_common.h"
 #include "dap_strfuncs.h"
-#include "dap_chain_global_db_pvt.h"
+//#include "dap_chain_global_db_pvt.h"
+#include "dap_chain_global_db_driver.h"
 #include "dap_chain_global_db_hist.h"
 #include "dap_chain_global_db.h"
 
@@ -138,14 +139,14 @@ void dap_chain_global_db_objs_delete(dap_global_db_obj_t **objs)
  */
 int dap_chain_global_db_init(dap_config_t * g_config)
 {
-    const char *a_storage_path = dap_config_get_item_str(g_config, "resources", "dap_global_db_path");
-    if(a_storage_path){
-        lock();
-        int res = dap_db_init(a_storage_path);
-        unlock();
-        return res;
-    }
-    return -1;
+    const char *l_storage_path = dap_config_get_item_str(g_config, "resources", "dap_global_db_path");
+    const char *l_driver_name = dap_config_get_item_str_default(g_config, "resources", "dap_global_db_driver",
+            "sqlite");
+    lock();
+    int res = dap_db_driver_init(l_driver_name, l_storage_path);
+    //int res = dap_db_init(a_storage_path);
+    unlock();
+    return res;
 }
 
 /**
@@ -154,7 +155,8 @@ int dap_chain_global_db_init(dap_config_t * g_config)
 void dap_chain_global_db_deinit(void)
 {
     lock();
-    dap_db_deinit();
+    dap_db_driver_deinit();
+    //dap_db_deinit();
     unlock();
     history_group_item_t * l_item = NULL, *l_item_tmp = NULL;
     HASH_ITER(hh, s_history_group_items, l_item, l_item_tmp){
diff --git a/dap_chain_global_db_driver.c b/dap_chain_global_db_driver.c
new file mode 100644
index 0000000..ab0ddcb
--- /dev/null
+++ b/dap_chain_global_db_driver.c
@@ -0,0 +1,65 @@
+/*
+ * Authors:
+ * Alexander Lysikov <alexander.lysikov@demlabs.net>
+ * DeM Labs Inc.   https://demlabs.net
+ * Kelvin Project https://github.com/kelvinblockchain
+ * Copyright  (c) 2019
+ * All rights reserved.
+
+ This file is part of DAP (Deus Applications Prototypes) the open source project
+
+ DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ DAP is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+#include "dap_common.h"
+#include "dap_strfuncs.h"
+
+#include "dap_chain_global_db_driver_sqlite.h"
+#include "dap_chain_global_db_driver.h"
+
+static char *s_used_driver = NULL;
+/**
+ * Select driver
+ * driver_name may be "ldb", "sqlite"
+ *
+ * return 0 OK, <0 Error
+ */
+int dap_db_driver_init(const char *a_driver_name, const char *a_filename_db)
+{
+    if(s_used_driver)
+        dap_db_driver_deinit();
+    s_used_driver = dap_strdup(a_driver_name);
+    if(!dap_strcmp(s_used_driver, "ldb"))
+        return -1;
+    if(!dap_strcmp(s_used_driver, "sqlite"))
+        return dap_db_driver_sqlite_init(a_filename_db);
+    return -1;
+}
+
+/**
+ * Shutting down the db library
+ */
+
+void dap_db_driver_deinit(void)
+{
+//    if(!dap_strcmp(s_used_driver, "ldb"))
+//        ;
+    if(!dap_strcmp(s_used_driver, "sqlite"))
+        dap_db_driver_sqlite_deinit();
+    DAP_DELETE(s_used_driver);
+    s_used_driver = NULL;
+}
+
diff --git a/dap_chain_global_db_driver.h b/dap_chain_global_db_driver.h
new file mode 100644
index 0000000..76e5d97
--- /dev/null
+++ b/dap_chain_global_db_driver.h
@@ -0,0 +1,66 @@
+/*
+ * Authors:
+ * Alexander Lysikov <alexander.lysikov@demlabs.net>
+ * DeM Labs Inc.   https://demlabs.net
+ * Kelvin Project https://github.com/kelvinblockchain
+ * Copyright  (c) 2019
+ * All rights reserved.
+
+ This file is part of DAP (Deus Applications Prototypes) the open source project
+
+ DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ DAP is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _GLOBAL_DB_DRIVER_H_
+#define _GLOBAL_DB_DRIVER_H_
+
+#include <stddef.h>
+#include <stdint.h>
+//#include <ctime>
+#include "dap_common.h"
+
+typedef struct dap_store_obj {
+	time_t timestamp;
+	uint8_t type;
+//	char *section;
+	char *group;
+	char *key;
+	uint8_t *value;
+	size_t value_len;
+}DAP_ALIGN_PACKED dap_store_obj_t, *pdap_store_obj_t;
+
+typedef struct dap_store_obj_pkt {
+	time_t timestamp;
+	size_t data_size;
+	uint8_t data[];
+}__attribute__((packed)) dap_store_obj_pkt_t;
+
+int dap_db_driver_init(const char *driver_name, const char *a_filename_db);
+void dap_db_driver_deinit(void);
+
+int dap_db_add(pdap_store_obj_t a_store_obj, size_t a_store_count);
+int dap_db_delete(pdap_store_obj_t a_store_obj, size_t a_store_count);
+
+pdap_store_obj_t dap_db_read_data(const char *a_query, size_t *a_count);
+pdap_store_obj_t dap_db_read_file_data(const char *a_path, const char *a_group); // state of emergency only, if LDB database is inaccessible
+dap_store_obj_pkt_t *dap_store_packet_single(pdap_store_obj_t a_store_obj);
+dap_store_obj_pkt_t *dap_store_packet_multiple(pdap_store_obj_t a_store_obj,
+		time_t a_timestamp, size_t a_store_obj_count);
+dap_store_obj_t *dap_store_unpacket(const dap_store_obj_pkt_t *a_pkt,
+		size_t *a_store_obj_count);
+
+void dab_db_free_pdap_store_obj_t(pdap_store_obj_t a_store_data,
+		size_t a_count);
+
+#endif //_GLOBAL_DB_DRIVER_H_
diff --git a/dap_chain_global_db_driver_sqlite.c b/dap_chain_global_db_driver_sqlite.c
new file mode 100644
index 0000000..c7dade1
--- /dev/null
+++ b/dap_chain_global_db_driver_sqlite.c
@@ -0,0 +1,191 @@
+/*
+ * Authors:
+ * Alexander Lysikov <alexander.lysikov@demlabs.net>
+ * DeM Labs Inc.   https://demlabs.net
+ * Kelvin Project https://github.com/kelvinblockchain
+ * Copyright  (c) 2019
+ * All rights reserved.
+
+ This file is part of DAP (Deus Applications Prototypes) the open source project
+
+ DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ DAP is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stddef.h>
+#include "dap_common.h"
+#include "dap_chain_global_db_driver.h"
+#include "dap_chain_global_db_driver_sqlite.h"
+
+#define LOG_TAG "db_sqlite"
+
+static sqlite3 *s_db = NULL;
+
+/**
+ * SQLite library initialization, no thread safe
+ *
+ * return 0 if Ok, else error code >0
+ */
+int dap_db_driver_sqlite_init(const char *a_filename_db)
+{
+    int l_ret = -1;
+    if(sqlite3_threadsafe() && !sqlite3_config(SQLITE_CONFIG_SERIALIZED))
+        l_ret = sqlite3_initialize();
+    if(l_ret != SQLITE_OK) {
+        log_it(L_ERROR, "Can't init sqlite err=%d", l_ret);
+        return l_ret;
+    }
+    char *l_error_message = NULL;
+    s_db = dap_db_driver_sqlite_open(a_filename_db, SQLITE_OPEN_READWRITE, &l_error_message);
+    if(!s_db) {
+        log_it(L_ERROR, "Can't init sqlite err=%d", l_error_message);
+        dap_db_driver_sqlite_free(l_error_message);
+    }
+    return l_ret;
+}
+
+int dap_db_driver_sqlite_deinit(void)
+{
+    return sqlite3_shutdown();
+}
+
+
+/**
+ * Open SQLite database
+ * a_filename_utf8 - database file name
+ * a_flags - database access flags (SQLITE_OPEN_READONLY, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE)
+ * a_error_message[out] - Error messages (the memory requires deletion via sqlite_free ())
+ *
+ * return: database identifier, NULL when an error occurs.
+ */
+sqlite3* dap_db_driver_sqlite_open(const char *a_filename_utf8, int a_flags, char **a_error_message)
+{
+    sqlite3 *l_db = NULL;
+
+    int l_rc = sqlite3_open_v2(a_filename_utf8, &l_db, a_flags | SQLITE_OPEN_FULLMUTEX, NULL);
+    // if unable to open the database file
+    if(l_rc == SQLITE_CANTOPEN) {
+        // try to create database
+        l_rc = sqlite3_open_v2(a_filename_utf8, &l_db, a_flags | SQLITE_OPEN_FULLMUTEX | SQLITE_OPEN_CREATE, NULL);
+    }
+    if(l_rc != SQLITE_OK)
+    {
+        if(a_error_message)
+            *a_error_message = sqlite3_mprintf("Can't open database: %s\n", sqlite3_errmsg(l_db));
+        sqlite3_close(l_db);
+        return NULL;
+    }
+    return l_db;
+}
+
+/**
+ * Close the database
+ */
+void dap_db_driver_sqlite_close(sqlite3 *l_db)
+{
+    if(l_db)
+        sqlite3_close(l_db);
+}
+/*
+ * Clear the memory allocated via sqlite3_mprintf()
+ */
+void dap_db_driver_sqlite_free(char *memory)
+{
+    if(memory)
+        sqlite3_free(memory);
+}
+
+/**
+ * Execute SQL query to database that does not return data
+ *
+ * return 0 if Ok, else error code >0
+ */
+static int dap_db_driver_sqlite_exec(sqlite3 *l_db, const char *l_query, char **l_error_message)
+{
+    char *l_zErrMsg = NULL;
+    int l_rc = sqlite3_exec(l_db, l_query, NULL, 0, &l_zErrMsg);
+    if(l_rc != SQLITE_OK)
+    {
+        if(l_error_message && l_zErrMsg)
+            *l_error_message = sqlite3_mprintf("SQL error: %s", l_zErrMsg);
+        if(l_zErrMsg)
+            sqlite3_free(l_zErrMsg);
+        return l_rc;
+    }
+    if(l_zErrMsg)
+        sqlite3_free(l_zErrMsg);
+    return l_rc;
+}
+
+/*
+ * Add multiple entries received from remote node to local database.
+ * Since we don't know the size, it must be supplied too
+ *
+ * dap_store_size the count records
+ * return 0 if Ok, else error code >0
+ */
+int dap_db_add1(dap_store_obj_t *a_store_obj, size_t a_store_count)
+{
+    int l_ret = 0;
+    /*   if(a_store_obj == NULL) {
+     log_it(L_ERROR, "Invalid Dap store objects passed");
+     return -1;
+     }
+     if(ldb_connect(s_ldb, dap_db_path, 0, NULL) != LDB_SUCCESS) {
+     log_it(L_ERROR, "Couldn't connect to database");
+     return -2;
+     }
+     //log_it(L_INFO, "We're about to put %d records into database", a_store_count);
+     struct ldb_message *l_msg;
+     if(a_store_count == 0) {
+     a_store_count = 1;
+     }
+     for(size_t q = 0; q < a_store_count; q++) {
+     // level 3: leased address, single whitelist entity
+
+     // if it is marked, don't save
+     if(a_store_obj[q].timestamp == (time_t) -1)
+     continue;
+
+     l_msg = ldb_msg_new(s_ldb);
+     char dn[256];
+     memset(dn, '\0', 256);
+     strcat(dn, "cn=");
+     strcat(dn, a_store_obj[q].key);
+     //strcat(dn, ",ou=addrs_leased,dc=kelvin_nodes");
+     strcat(dn, ",ou=");
+     strcat(dn, a_store_obj[q].group);
+     strcat(dn, ",dc=kelvin_nodes");
+     l_msg->dn = ldb_dn_new(s_mem_ctx, s_ldb, dn);
+     int l_res = ldb_msg_add_string(l_msg, "cn", a_store_obj[q].key);
+     ldb_msg_add_string(l_msg, "objectClass", a_store_obj[q].group);
+     ldb_msg_add_string(l_msg, "section", "kelvin_nodes");
+     ldb_msg_add_string(l_msg, "description", "Approved Kelvin node");
+
+     struct ldb_val l_val;
+     struct ldb_message_element *return_el;
+     l_val.data = (uint8_t*) &a_store_obj[q].timestamp;
+     l_val.length = sizeof(time_t);
+     l_res = ldb_msg_add_value(l_msg, "time", &l_val, &return_el);
+
+     l_val.data = a_store_obj[q].value;
+     l_val.length = a_store_obj[q].value_len;
+     l_res = ldb_msg_add_value(l_msg, "val", &l_val, &return_el);
+
+     l_ret += dap_db_add_msg(l_msg); // accumulation error codes
+     talloc_free(l_msg->dn);
+     talloc_free(l_msg);
+     }*/
+    return l_ret;
+}
+
diff --git a/dap_chain_global_db_driver_sqlite.h b/dap_chain_global_db_driver_sqlite.h
new file mode 100644
index 0000000..35ae58c
--- /dev/null
+++ b/dap_chain_global_db_driver_sqlite.h
@@ -0,0 +1,36 @@
+/*
+ * Authors:
+ * Alexander Lysikov <alexander.lysikov@demlabs.net>
+ * DeM Labs Inc.   https://demlabs.net
+ * Kelvin Project https://github.com/kelvinblockchain
+ * Copyright  (c) 2019
+ * All rights reserved.
+
+ This file is part of DAP (Deus Applications Prototypes) the open source project
+
+ DAP (Deus Applicaions Prototypes) is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ DAP is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with any DAP based project.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "sqlite3.h"
+
+
+int dap_db_driver_sqlite_init(const char *a_filename_db);
+int dap_db_driver_sqlite_deinit(void);
+
+sqlite3* dap_db_driver_sqlite_open(const char *a_filename_utf8, int a_flags, char **error_message);
+void dap_db_driver_sqlite_close(sqlite3 *l_db);
+
+void dap_db_driver_sqlite_free(char *memory);
+
+
diff --git a/dap_chain_global_db_pvt.h b/dap_chain_global_db_pvt.h
index 7fab7e3..f9be991 100755
--- a/dap_chain_global_db_pvt.h
+++ b/dap_chain_global_db_pvt.h
@@ -1,4 +1,5 @@
-#pragma once
+#ifndef _GLOBAL_DB_DRIVER_H_
+#define _GLOBAL_DB_DRIVER_H_
 
 #include <stdint.h>
 #include "dap_common.h"
@@ -39,3 +40,4 @@ dap_store_obj_t *dap_store_unpacket(const dap_store_obj_pkt_t *a_pkt, size_t *a_
 
 void dab_db_free_pdap_store_obj_t(pdap_store_obj_t a_store_data, size_t a_count);
 
+#endif // #ifndef _GLOBAL_DB_DRIVER_H_
-- 
GitLab