From 5eaf60b1f34a73c9ac12ee4ba09cb044387753dd Mon Sep 17 00:00:00 2001 From: Netrunner Date: Mon, 6 May 2024 10:10:24 +0100 Subject: [PATCH 1/4] shogdb: implement new client library --- makefiles/build.mk | 16 +-- makefiles/tools.mk | 2 +- netlibc/include/netlibc.h | 6 + shogdb/README.txt | 34 +++-- shogdb/examples/simple.c | 34 +++++ shogdb/makefile | 25 ++-- shogdb/src/{lib/lib.c => client/client.c} | 132 +++++++++++++++++- .../shogdb.h => shogdb/src/client/client.h | 18 ++- shogdb/src/db/db.h | 4 +- .../lib/lib.h => src/include/shogdb-client.h | 0 src/include/sonic.h | 2 +- src/node/db/db.c | 2 +- src/node/tunnel/tunnel.c | 2 +- 13 files changed, 236 insertions(+), 41 deletions(-) rename shogdb/src/{lib/lib.c => client/client.c} (55%) rename src/include/shogdb.h => shogdb/src/client/client.h (60%) rename shogdb/src/lib/lib.h => src/include/shogdb-client.h (100%) diff --git a/makefiles/build.mk b/makefiles/build.mk index 2b8c839..a8d649c 100644 --- a/makefiles/build.mk +++ b/makefiles/build.mk @@ -49,8 +49,8 @@ OBJS += $(TARGET_DIR)/args.o $(TARGET_DIR)/server.o $(TARGET_DIR)/manifest.o $(T OBJS += $(TARGET_DIR)/server_explorer.o # static libraries -STATIC_LIBS = $(TARGET_DIR)/libnetlibc.a $(TARGET_DIR)/sonic.a $(TARGET_DIR)/tuwi.a $(TARGET_DIR)/libhandlebazz.a $(TARGET_DIR)/cjson.a $(TARGET_DIR)/tomlc.a $(TARGET_DIR)/libshogdb.a -STATIC_LIBS_SANITIZED = $(TARGET_DIR)/libnetlibc.a $(TARGET_DIR)/sonic-sanitized.a $(TARGET_DIR)/tuwi.a $(TARGET_DIR)/libhandlebazz.a $(TARGET_DIR)/cjson.a $(TARGET_DIR)/tomlc.a $(TARGET_DIR)/libshogdb-sanitized.a +STATIC_LIBS = $(TARGET_DIR)/libnetlibc.a $(TARGET_DIR)/sonic.a $(TARGET_DIR)/tuwi.a $(TARGET_DIR)/libhandlebazz.a $(TARGET_DIR)/cjson.a $(TARGET_DIR)/tomlc.a $(TARGET_DIR)/shogdb-client.a +STATIC_LIBS_SANITIZED = $(TARGET_DIR)/libnetlibc.a $(TARGET_DIR)/sonic-sanitized.a $(TARGET_DIR)/tuwi.a $(TARGET_DIR)/libhandlebazz.a $(TARGET_DIR)/cjson.a $(TARGET_DIR)/tomlc.a $(TARGET_DIR)/shogdb-client-sanitized.a .PHONY: target-dir shogdb model-server $(TARGET_DIR)/tuwi.a $(TARGET_DIR)/camel.a .PHONY: $(TARGET_DIR)/sonic.a $(TARGET_DIR)/sonic-sanitized.a $(TARGET_DIR)/cjson.a $(TARGET_DIR)/tomlc.a @@ -96,13 +96,13 @@ $(TARGET_DIR)/sonic.a: cd ./sonic/ && make cp ./sonic/target/libsonic.a $(TARGET_DIR)/sonic.a -$(TARGET_DIR)/libshogdb.a: - cd ./shogdb/ && make lib - cp ./shogdb/target/libshogdb.a $(TARGET_DIR)/libshogdb.a +$(TARGET_DIR)/shogdb-client.a: + cd ./shogdb/ && make client + cp ./shogdb/target/shogdb-client.a $(TARGET_DIR)/shogdb-client.a -$(TARGET_DIR)/libshogdb-sanitized.a: - cd ./shogdb/ && make lib-sanitized - cp ./shogdb/target/libshogdb-sanitized.a $(TARGET_DIR)/libshogdb-sanitized.a +$(TARGET_DIR)/shogdb-client-sanitized.a: + cd ./shogdb/ && make client-sanitized + cp ./shogdb/target/shogdb-client-sanitized.a $(TARGET_DIR)/shogdb-client-sanitized.a $(TARGET_DIR)/sonic-sanitized.a: cd ./sonic/ && make build-sanitized diff --git a/makefiles/tools.mk b/makefiles/tools.mk index 0f15169..8be0514 100644 --- a/makefiles/tools.mk +++ b/makefiles/tools.mk @@ -46,7 +46,7 @@ sync-libs-headers: cp ./camel/camel.h ./src/include/camel.h cp ./sonic/sonic.h ./src/include/sonic.h cp ./tuwi/tuwi.h ./src/include/tuwi.h - cp ./shogdb/src/lib/lib.h ./src/include/shogdb.h + cp ./shogdb/src/client/client.h ./src/include/shogdb-client.h kill-db: killall -v -w -s 9 shogdb diff --git a/netlibc/include/netlibc.h b/netlibc/include/netlibc.h index 926fbb4..f1e89f0 100644 --- a/netlibc/include/netlibc.h +++ b/netlibc/include/netlibc.h @@ -44,6 +44,12 @@ typedef size_t usize; #define S64_FORMAT_SPECIFIER "%ld" #endif +#ifdef __APPLE__ +#define F64_FORMAT_SPECIFIER "%f" +#else +#define F64_FORMAT_SPECIFIER "%f" +#endif + #define LOOP() \ for (;;) { \ } diff --git a/shogdb/README.txt b/shogdb/README.txt index a89db6f..2eef5d1 100644 --- a/shogdb/README.txt +++ b/shogdb/README.txt @@ -2,10 +2,16 @@ SHOGDB - Shoggoth Database =============================================================================== -ShogDB is an in-memory, key-value database written in the C programming language, developed by ShogAI for use in the Shoggoth project (https://shoggoth.network). +ShogDB is an in-memory, key-value database written in the C programming language, developed by ShogAI for use in the Shoggoth project. ShogDB is the database used by Shoggoth Nodes to store information like DHTs and pins. ShogDB also persists data on disk by periodically saving data to a file. -ShogDB uses string keys, with values of different types like int, uint, float, string, bool and JSON. +ShogDB uses string keys, with values of different types like: +* int +* uint +* float +* string +* bool +* JSON. Applications can communicate with ShogDB via HTTP requests. ShogDB exposes the HTTP API at http://127.0.0.1:6961 by default. @@ -17,7 +23,21 @@ ShogDB is still early in development and should be considered unstable and exper USING SHOGDB =============================================================================== -TODO + +Using the HTTP API +================================================ + + +Using the C client library +================================================ + + + +Configuration +================================================ + +ShogDB requires a TOML configuration file ./dbconfig.toml located in the current working directory, and stores data on disk in a ./save.sdb file. + =============================================================================== @@ -50,14 +70,6 @@ $ make The above command will build a binary into ./target/shogdb -ShogDB requires a TOML configuration file ./dbconfig.toml located in the current working directory, and stores data on disk in a ./save.sdb file. - - -=============================================================================== -DOCUMENTATION -=============================================================================== - -TODO =============================================================================== CONTRIBUTING diff --git a/shogdb/examples/simple.c b/shogdb/examples/simple.c index e69de29..cd08e8a 100644 --- a/shogdb/examples/simple.c +++ b/shogdb/examples/simple.c @@ -0,0 +1,34 @@ +#include "../include/cjson.h" +#include "../src/client/client.h" + +int main() { + NETLIBC_INIT(); + + shogdb_ctx_t *db_ctx = new_shogdb("http://127.0.0.1:6961"); + + UNWRAP(shogdb_set_int(db_ctx, "my_int", 69)); + db_value_t *res_int = UNWRAP(shogdb_get(db_ctx, "my_int")); + printf("INT VALUE: %lld\n", res_int->value_int); + + UNWRAP(shogdb_set_uint(db_ctx, "my_uint", 68)); + db_value_t *res_uint = UNWRAP(shogdb_get(db_ctx, "my_uint")); + printf("UINT VALUE: %lld\n", res_uint->value_uint); + + UNWRAP(shogdb_set_float(db_ctx, "my_float", 68.993)); + db_value_t *res_float = UNWRAP(shogdb_get(db_ctx, "my_float")); + printf("FLOAT VALUE: %f\n", res_float->value_float); + + UNWRAP(shogdb_set_str(db_ctx, "my_str", "deez nutz")); + db_value_t *res_str = UNWRAP(shogdb_get(db_ctx, "my_str")); + printf("STR VALUE: %s\n", res_str->value_str); + + UNWRAP(shogdb_set_bool(db_ctx, "my_bool", 1)); + db_value_t *res_bool = UNWRAP(shogdb_get(db_ctx, "my_bool")); + printf("BOOL VALUE: %d\n", res_bool->value_bool); + + UNWRAP(shogdb_set_json(db_ctx, "my_json", "[1, 2, 4]")); + db_value_t *res_json = UNWRAP(shogdb_get(db_ctx, "my_json")); + printf("JSON VALUE: %s\n", cJSON_Print(res_json->value_json)); + + free_shogdb(db_ctx); +} diff --git a/shogdb/makefile b/shogdb/makefile index 6c8a12a..f1b94c4 100644 --- a/shogdb/makefile +++ b/shogdb/makefile @@ -23,29 +23,34 @@ build: ./target/shogdb cp ./src/dbconfig.toml ./target/dbconfig.toml -lib: target-dir - echo "Building libshogdb..." +client: target-dir + echo "Building shogdb client..." - $(CC) $(CFLAGS) -c ./src/lib/lib.c -o ./target/lib.o - ar rcs ./target/libshogdb.a ./target/lib.o + $(CC) $(CFLAGS) -c ./src/client/client.c -o ./target/client.o + ar rcs ./target/shogdb-client.a ./target/client.o -lib-sanitized: target-dir - echo "Building libshogdb..." - $(CC) $(CFLAGS) $(CFLAGS_SANITIZED) -c ./src/lib/lib.c -o ./target/lib.o - ar rcs ./target/libshogdb-sanitized.a ./target/lib.o +client-sanitized: target-dir + echo "Building shogdb client (sanitized)..." + $(CC) $(CFLAGS) $(CFLAGS_SANITIZED) -c ./src/client/client.c -o ./target/client.o + ar rcs ./target/shogdb-client-sanitized.a ./target/client.o run: build cd target && ./shogdb +run-example: target-dir + $(CC) -g $(CFLAGS) ./examples/$(E).c ./src/client/client.c $(STATIC_LIBS) $(LDFLAGS) -o ./target/examples/$(E) + ./target/examples/$(E) + + ./target/shogdb: target-dir echo "Building shogdb..." - $(CC) $(CFLAGS) ./src/main.c ./src/lib/lib.c ./src/db/db.c ./src/db/dht.c ./src/db/pins.c ./src/hashmap/hashmap.c $(STATIC_LIBS) $(LDFLAGS) -o ./target/shogdb + $(CC) $(CFLAGS) ./src/main.c ./src/client/client.c ./src/db/db.c ./src/db/dht.c ./src/db/pins.c ./src/hashmap/hashmap.c $(STATIC_LIBS) $(LDFLAGS) -o ./target/shogdb ./target/shogdb-sanitized: target-dir echo "Building shogdb..." - $(CC) $(CFLAGS_SANITIZED) $(CFLAGS) $(LDFLAGS_SANITIZED) ./src/main.c ./src/lib/lib.c ./src/db/db.c ./src/db/dht.c ./src/db/pins.c ./src/hashmap/hashmap.c $(STATIC_LIBS) $(LDFLAGS) -o ./target/shogdb + $(CC) $(CFLAGS_SANITIZED) $(CFLAGS) $(LDFLAGS_SANITIZED) ./src/main.c ./src/client/client.c ./src/db/db.c ./src/db/dht.c ./src/db/pins.c ./src/hashmap/hashmap.c $(STATIC_LIBS) $(LDFLAGS) -o ./target/shogdb target-dir: mkdir -p target diff --git a/shogdb/src/lib/lib.c b/shogdb/src/client/client.c similarity index 55% rename from shogdb/src/lib/lib.c rename to shogdb/src/client/client.c index a9a9df4..2a2ef6a 100644 --- a/shogdb/src/lib/lib.c +++ b/shogdb/src/client/client.c @@ -8,13 +8,135 @@ * ****/ -#include "lib.h" +#include "client.h" #include "../../include/cjson.h" +#include "../../include/sonic.h" #include #include +#include +#include #include +result_t shogdb_set(shogdb_ctx_t *ctx, char *key, char *value) { + char url[256]; + sprintf(url, "%s/set/%s", ctx->address, key); + + sonic_request_t *req = sonic_new_request(METHOD_GET, url); + + // char body[256]; + // sprintf(body, "INT %d", value); + + sonic_set_body(req, value, strlen(value)); + + sonic_response_t *resp = sonic_send_request(req); + sonic_free_request(req); + + if (resp->failed) { + return ERR("request failed: %s \n", resp->error); + } + + nfree(resp->response_body); + sonic_free_response(resp); + + return OK(NULL); +} + +result_t shogdb_set_int(shogdb_ctx_t *ctx, char *key, s64 value) { + char body[256]; + sprintf(body, "INT " S64_FORMAT_SPECIFIER, value); + + result_t res = shogdb_set(ctx, key, body); + + return res; +} + +result_t shogdb_set_uint(shogdb_ctx_t *ctx, char *key, u64 value) { + char body[256]; + sprintf(body, "UINT " U64_FORMAT_SPECIFIER, value); + + result_t res = shogdb_set(ctx, key, body); + + return res; +} + +result_t shogdb_set_float(shogdb_ctx_t *ctx, char *key, f64 value) { + char body[256]; + sprintf(body, "FLOAT " F64_FORMAT_SPECIFIER, value); + + result_t res = shogdb_set(ctx, key, body); + + return res; +} + +result_t shogdb_set_str(shogdb_ctx_t *ctx, char *key, char *value) { + char *body = string_from("STR ", value, NULL); + + result_t res = shogdb_set(ctx, key, body); + + nfree(body); + + return res; +} + +result_t shogdb_set_bool(shogdb_ctx_t *ctx, char *key, bool value) { + char body[256]; + if (value == true) { + sprintf(body, "BOOL true"); + } else { + sprintf(body, "BOOL false"); + } + + result_t res = shogdb_set(ctx, key, body); + + return res; +} + +result_t shogdb_set_json(shogdb_ctx_t *ctx, char *key, char *value) { + char *body = string_from("JSON ", value, NULL); + + result_t res = shogdb_set(ctx, key, body); + + nfree(body); + + return res; +} + +result_t shogdb_get(shogdb_ctx_t *ctx, char *key) { + char url[256]; + sprintf(url, "%s/get/%s", ctx->address, key); + + sonic_request_t *req = sonic_new_request(METHOD_GET, url); + + sonic_response_t *resp = sonic_send_request(req); + sonic_free_request(req); + + if (resp->failed) { + return ERR("request failed: %s \n", resp->error); + } + + result_t res = shogdb_parse_message(resp->response_body); + db_value_t *value = PROPAGATE(res); + + nfree(resp->response_body); + sonic_free_response(resp); + + return OK(value); +} + +shogdb_ctx_t *new_shogdb(char *address) { + shogdb_ctx_t *ctx = ncalloc(1, sizeof(shogdb_ctx_t)); + ctx->address = nstrdup(address); + + return ctx; +} + +void free_shogdb(shogdb_ctx_t *ctx) { + nfree(ctx->address); + + nfree(ctx); +} + db_value_t *new_db_value(value_type_t value_type) { db_value_t *db_value = calloc(1, sizeof(db_value_t)); db_value->value_type = value_type; @@ -87,18 +209,18 @@ result_t shogdb_parse_message(char *msg) { size_t length = strcspn(msg, " "); - char *msg_type = strdup(msg); + char *msg_type = nstrdup(msg); msg_type[length] = '\0'; // LOG(INFO, "TYPE: `%s`", msg_type); - char *msg_value = strdup(&msg[length + 1]); + char *msg_value = nstrdup(&msg[length + 1]); // LOG(INFO, "VALUE: `%s`", msg_value); value->value_type = str_to_value_type(msg_type); - free(msg_type); + nfree(msg_type); if (value->value_type == VALUE_STR) { - value->value_str = msg_value; + value->value_str = nstrdup(msg_value); } else if (value->value_type == VALUE_BOOL) { bool result = false; diff --git a/src/include/shogdb.h b/shogdb/src/client/client.h similarity index 60% rename from src/include/shogdb.h rename to shogdb/src/client/client.h index bcfb088..e94cafb 100644 --- a/src/include/shogdb.h +++ b/shogdb/src/client/client.h @@ -16,6 +16,10 @@ #include +typedef struct { + char *address; +} shogdb_ctx_t; + typedef enum { VALUE_NULL, @@ -44,6 +48,18 @@ typedef struct { void *value_json; } db_value_t; +result_t shogdb_set_int(shogdb_ctx_t *ctx, char *key, s64 value); +result_t shogdb_set_uint(shogdb_ctx_t *ctx, char *key, u64 value); +result_t shogdb_set_float(shogdb_ctx_t *ctx, char *key, f64 value); +result_t shogdb_set_str(shogdb_ctx_t *ctx, char *key, char *value); +result_t shogdb_set_bool(shogdb_ctx_t *ctx, char *key, bool value); +result_t shogdb_set_json(shogdb_ctx_t *ctx, char *key, char *value); + +result_t shogdb_get(shogdb_ctx_t *ctx, char *key); + +shogdb_ctx_t *new_shogdb(char *address); +void free_shogdb(shogdb_ctx_t *ctx); + db_value_t *new_db_value(value_type_t value_type); value_type_t str_to_value_type(char *str); @@ -54,4 +70,4 @@ void free_db_value(db_value_t *value); result_t shogdb_parse_message(char *msg); -#endif \ No newline at end of file +#endif diff --git a/shogdb/src/db/db.h b/shogdb/src/db/db.h index 3f8aaa2..5c93eb3 100644 --- a/shogdb/src/db/db.h +++ b/shogdb/src/db/db.h @@ -14,7 +14,7 @@ #include "../../include/cjson.h" #include "../../include/sonic.h" #include "../hashmap/hashmap.h" -#include "../lib/lib.h" +#include "../client/client.h" #include #include @@ -58,4 +58,4 @@ void db_save_data(db_ctx_t *ctx); result_t db_delete_value(db_ctx_t *ctx, char *key); -#endif \ No newline at end of file +#endif diff --git a/shogdb/src/lib/lib.h b/src/include/shogdb-client.h similarity index 100% rename from shogdb/src/lib/lib.h rename to src/include/shogdb-client.h diff --git a/src/include/sonic.h b/src/include/sonic.h index 2429c7b..78e53c7 100644 --- a/src/include/sonic.h +++ b/src/include/sonic.h @@ -213,7 +213,7 @@ void sonic_add_header(sonic_client_request_t *req, char *key, char *value); void sonic_set_body(sonic_client_request_t *req, char *request_body, u64 request_body_size); -char *sonic_status_to_string(sonic_status_t status_code); +result_t sonic_status_to_string(sonic_status_t status_code); // =================================================================================================================== diff --git a/src/node/db/db.c b/src/node/db/db.c index a107cab..6778213 100644 --- a/src/node/db/db.c +++ b/src/node/db/db.c @@ -16,7 +16,7 @@ #include #include "../../include/cjson.h" -#include "../../include/shogdb.h" +#include "../../include/shogdb-client.h" #include "../../include/sonic.h" #include "../../json/json.h" #include "../../utils/utils.h" diff --git a/src/node/tunnel/tunnel.c b/src/node/tunnel/tunnel.c index 0618e47..8fe5871 100644 --- a/src/node/tunnel/tunnel.c +++ b/src/node/tunnel/tunnel.c @@ -15,7 +15,7 @@ #include #include "../../include/cjson.h" -#include "../../include/shogdb.h" +// #include "../../include/shogdb-client.h" #include "../../include/sonic.h" #include "../../json/json.h" #include "../../utils/utils.h" From caa722ba69eda07b9f39f6eda0df1dc77c5ed0fa Mon Sep 17 00:00:00 2001 From: Netrunner Date: Mon, 6 May 2024 19:02:19 +0100 Subject: [PATCH 2/4] shogdb: update client library --- shogdb/examples/simple.c | 5 +++ shogdb/src/client/client.c | 65 ++++++++++++++++++++++++++++++++++---- shogdb/src/client/client.h | 6 ++++ shogdb/src/db/db.c | 46 +++++++++++++++++++++------ shogdb/src/db/db.h | 1 + shogdb/src/dbconfig.toml | 3 +- shogdb/src/main.c | 3 ++ 7 files changed, 112 insertions(+), 17 deletions(-) diff --git a/shogdb/examples/simple.c b/shogdb/examples/simple.c index cd08e8a..ec84b2d 100644 --- a/shogdb/examples/simple.c +++ b/shogdb/examples/simple.c @@ -30,5 +30,10 @@ int main() { db_value_t *res_json = UNWRAP(shogdb_get(db_ctx, "my_json")); printf("JSON VALUE: %s\n", cJSON_Print(res_json->value_json)); + UNWRAP(shogdb_delete(db_ctx, "my_str")); + + char *res_all = UNWRAP(shogdb_print(db_ctx)); + printf("ALL VALUES: %s\n", res_all); + free_shogdb(db_ctx); } diff --git a/shogdb/src/client/client.c b/shogdb/src/client/client.c index 2a2ef6a..b02cc47 100644 --- a/shogdb/src/client/client.c +++ b/shogdb/src/client/client.c @@ -24,9 +24,6 @@ result_t shogdb_set(shogdb_ctx_t *ctx, char *key, char *value) { sonic_request_t *req = sonic_new_request(METHOD_GET, url); - // char body[256]; - // sprintf(body, "INT %d", value); - sonic_set_body(req, value, strlen(value)); sonic_response_t *resp = sonic_send_request(req); @@ -36,10 +33,16 @@ result_t shogdb_set(shogdb_ctx_t *ctx, char *key, char *value) { return ERR("request failed: %s \n", resp->error); } - nfree(resp->response_body); - sonic_free_response(resp); + if (strcmp(resp->response_body, "OK") != 0) { + char *msg = nstrdup(resp->response_body); - return OK(NULL); + return ERR(msg); + } else { + nfree(resp->response_body); + sonic_free_response(resp); + + return OK(NULL); + } } result_t shogdb_set_int(shogdb_ctx_t *ctx, char *key, s64 value) { @@ -124,6 +127,46 @@ result_t shogdb_get(shogdb_ctx_t *ctx, char *key) { return OK(value); } +result_t shogdb_print(shogdb_ctx_t *ctx) { + char url[256]; + sprintf(url, "%s/print", ctx->address); + + sonic_request_t *req = sonic_new_request(METHOD_GET, url); + + sonic_response_t *resp = sonic_send_request(req); + sonic_free_request(req); + + if (resp->failed) { + return ERR("request failed: %s \n", resp->error); + } + + char *res = nstrdup(resp->response_body); + + nfree(resp->response_body); + sonic_free_response(resp); + + return OK(res); +} + +result_t shogdb_delete(shogdb_ctx_t *ctx, char *key) { + char url[256]; + sprintf(url, "%s/delete/%s", ctx->address, key); + + sonic_request_t *req = sonic_new_request(METHOD_GET, url); + + sonic_response_t *resp = sonic_send_request(req); + sonic_free_request(req); + + if (resp->failed) { + return ERR("request failed: %s \n", resp->error); + } + + nfree(resp->response_body); + sonic_free_response(resp); + + return OK(NULL); +} + shogdb_ctx_t *new_shogdb(char *address) { shogdb_ctx_t *ctx = ncalloc(1, sizeof(shogdb_ctx_t)); ctx->address = nstrdup(address); @@ -150,6 +193,8 @@ db_value_t *new_db_value(value_type_t value_type) { value_type_t str_to_value_type(char *str) { if (strcmp(str, "STR") == 0) { return VALUE_STR; + } else if (strcmp(str, "ERR") == 0) { + return VALUE_ERR; } else if (strcmp(str, "BOOL") == 0) { return VALUE_BOOL; } else if (strcmp(str, "UINT") == 0) { @@ -168,6 +213,8 @@ value_type_t str_to_value_type(char *str) { char *value_type_to_str(value_type_t value_type) { if (value_type == VALUE_STR) { return "STR"; + } else if (value_type == VALUE_ERR) { + return "ERR"; } else if (value_type == VALUE_BOOL) { return "BOOL"; } else if (value_type == VALUE_UINT) { @@ -191,6 +238,10 @@ void free_db_value(db_value_t *value) { free(value->value_str); } + if (value->value_type == VALUE_ERR) { + free(value->value_err); + } + if (value->value_type == VALUE_JSON) { cJSON_Delete(value->value_json); } @@ -221,6 +272,8 @@ result_t shogdb_parse_message(char *msg) { if (value->value_type == VALUE_STR) { value->value_str = nstrdup(msg_value); + } else if (value->value_type == VALUE_ERR) { + value->value_err = nstrdup(msg_value); } else if (value->value_type == VALUE_BOOL) { bool result = false; diff --git a/shogdb/src/client/client.h b/shogdb/src/client/client.h index e94cafb..486cbb2 100644 --- a/shogdb/src/client/client.h +++ b/shogdb/src/client/client.h @@ -22,6 +22,7 @@ typedef struct { typedef enum { VALUE_NULL, + VALUE_ERR, VALUE_UINT, VALUE_INT, @@ -37,6 +38,8 @@ typedef struct { value_type_t value_type; + char *value_err; + // integer types u64 value_uint; s64 value_int; @@ -54,9 +57,12 @@ result_t shogdb_set_float(shogdb_ctx_t *ctx, char *key, f64 value); result_t shogdb_set_str(shogdb_ctx_t *ctx, char *key, char *value); result_t shogdb_set_bool(shogdb_ctx_t *ctx, char *key, bool value); result_t shogdb_set_json(shogdb_ctx_t *ctx, char *key, char *value); +result_t shogdb_print(shogdb_ctx_t *ctx); result_t shogdb_get(shogdb_ctx_t *ctx, char *key); +result_t shogdb_delete(shogdb_ctx_t *ctx, char *key); + shogdb_ctx_t *new_shogdb(char *address); void free_shogdb(shogdb_ctx_t *ctx); diff --git a/shogdb/src/db/db.c b/shogdb/src/db/db.c index b598ccd..2912f1a 100644 --- a/shogdb/src/db/db.c +++ b/shogdb/src/db/db.c @@ -429,6 +429,27 @@ void get_route(sonic_server_request_t *req) { void set_route(sonic_server_request_t *req) { char *key = sonic_get_path_segment(req, "key"); + result_t res_existing = db_get_value(global_ctx, key); + + if (is_ok(res_existing)) { + sonic_server_response_t *resp = + sonic_new_response(STATUS_406, MIME_TEXT_PLAIN); + + char err[256]; + sprintf(err, "ERR key already exists"); + + sonic_response_set_body(resp, err, strlen(err)); + sonic_send_response(req, resp); + + sonic_free_server_response(resp); + + free_result(res_existing); + + return; + } else { + free_result(res_existing); + } + if (req->request_body_size < 5) { sonic_server_response_t *resp = sonic_new_response(STATUS_406, MIME_TEXT_PLAIN); @@ -1544,17 +1565,20 @@ result_t start_db(db_ctx_t *ctx) { LOG(INFO, "Database running at http://%s:%d", ctx->config->network.host, ctx->config->network.port); - int restored = UNWRAP_INT(db_restore_data(ctx)); + pthread_t data_saver_thread; - if (restored == 1) { - LOG(INFO, "Setting up DHT and PINS"); - UNWRAP(setup_dht(ctx)); - UNWRAP(setup_pins(ctx)); - } + if (ctx->config->save.enabled) { + int restored = UNWRAP_INT(db_restore_data(ctx)); - pthread_t data_saver_thread; - if (pthread_create(&data_saver_thread, NULL, start_data_saver, NULL) != 0) { - PANIC("could not spawn server thread"); + if (restored == 1) { + LOG(INFO, "Setting up DHT and PINS"); + UNWRAP(setup_dht(ctx)); + UNWRAP(setup_pins(ctx)); + } + + if (pthread_create(&data_saver_thread, NULL, start_data_saver, NULL) != 0) { + PANIC("could not spawn server thread"); + } } ctx->server_started = true; @@ -1564,7 +1588,9 @@ result_t start_db(db_ctx_t *ctx) { exit(1); } - pthread_join(data_saver_thread, NULL); + if (ctx->config->save.enabled) { + pthread_join(data_saver_thread, NULL); + } return OK(NULL); } diff --git a/shogdb/src/db/db.h b/shogdb/src/db/db.h index 5c93eb3..84fa3b7 100644 --- a/shogdb/src/db/db.h +++ b/shogdb/src/db/db.h @@ -26,6 +26,7 @@ typedef struct { } network_config_t; typedef struct { + bool enabled; char *path; u64 interval; } save_config_t; diff --git a/shogdb/src/dbconfig.toml b/shogdb/src/dbconfig.toml index 8551db5..bf45a5b 100644 --- a/shogdb/src/dbconfig.toml +++ b/shogdb/src/dbconfig.toml @@ -3,5 +3,6 @@ host = "127.0.0.1" port = 6961 [save] +enabled = false path = "./save.sdb" -interval = 2 # seconds \ No newline at end of file +interval = 2 # seconds diff --git a/shogdb/src/main.c b/shogdb/src/main.c index ab45d4a..b3a43db 100644 --- a/shogdb/src/main.c +++ b/shogdb/src/main.c @@ -48,6 +48,9 @@ result_t parse_config(char *config_str) { return ERR("TOML: Could not parse save table \n"); } + toml_datum_t save_enabled = toml_bool_in(save_table, "enabled"); + config->save.enabled = save_enabled.u.b; + toml_datum_t save_path = toml_string_in(save_table, "path"); config->save.path = strdup(save_path.u.s); free(save_path.u.s); From 8d84905e88badc327b6bc09a458763be6ba4a03f Mon Sep 17 00:00:00 2001 From: Netrunner Date: Mon, 6 May 2024 19:20:40 +0100 Subject: [PATCH 3/4] fix shogdb compile errors --- deploy/1/dbconfig.toml | 1 + deploy/2/dbconfig.toml | 1 + deploy/3/dbconfig.toml | 3 ++- makefiles/package.mk | 2 +- src/node/db/db.c | 30 +++++++++++++++--------------- src/node/dbconfig.toml | 8 ++++++++ 6 files changed, 28 insertions(+), 17 deletions(-) create mode 100644 src/node/dbconfig.toml diff --git a/deploy/1/dbconfig.toml b/deploy/1/dbconfig.toml index e30d7e9..3379c97 100644 --- a/deploy/1/dbconfig.toml +++ b/deploy/1/dbconfig.toml @@ -3,5 +3,6 @@ host = "127.0.0.1" port = 4961 [save] +enabled = true path = "./save.sdb" interval = 2 # seconds diff --git a/deploy/2/dbconfig.toml b/deploy/2/dbconfig.toml index 519bbb4..11c0a71 100644 --- a/deploy/2/dbconfig.toml +++ b/deploy/2/dbconfig.toml @@ -3,5 +3,6 @@ host = "127.0.0.1" port = 6961 [save] +enabled = true path = "./save.sdb" interval = 2 # seconds diff --git a/deploy/3/dbconfig.toml b/deploy/3/dbconfig.toml index 87d0837..551082a 100644 --- a/deploy/3/dbconfig.toml +++ b/deploy/3/dbconfig.toml @@ -3,5 +3,6 @@ host = "127.0.0.1" port = 5961 [save] +enabled = true path = "./save.sdb" -interval = 2 # seconds \ No newline at end of file +interval = 2 # seconds diff --git a/makefiles/package.mk b/makefiles/package.mk index c71ffbb..db5b17f 100644 --- a/makefiles/package.mk +++ b/makefiles/package.mk @@ -55,7 +55,7 @@ generate-runtime: check-path-arg build-explorer shogdb tunnel cp ./src/node/default-node-config.toml $(RP)/node/config.toml cp $(TARGET_DIR)/shogdb $(RP)/bin/ - cp ./shogdb/src/dbconfig.toml $(RP)/node/ + cp ./src/node/dbconfig.toml $(RP)/node/ cp $(TARGET_DIR)/tunnel $(RP)/bin/shog_tunnel diff --git a/src/node/db/db.c b/src/node/db/db.c index 6778213..e1aea72 100644 --- a/src/node/db/db.c +++ b/src/node/db/db.c @@ -163,7 +163,7 @@ void launch_db(node_ctx_t *ctx) { } } -result_t shogdb_get(node_ctx_t *ctx, char *endpoint, char *body) { +result_t shogdb_get_value(node_ctx_t *ctx, char *endpoint, char *body) { char url[256]; sprintf(url, "http://%s:%d/%s", ctx->config->db.host, ctx->config->db.port, endpoint); @@ -211,7 +211,7 @@ result_t shogdb_get(node_ctx_t *ctx, char *endpoint, char *body) { * ****/ result_t db_get_dht_str(node_ctx_t *ctx) { - result_t res_str = shogdb_get(ctx, "dht/get_dht", NULL); + result_t res_str = shogdb_get_value(ctx, "dht/get_dht", NULL); char *str = PROPAGATE(res_str); // LOG(INFO, "DHT: %s", str); @@ -224,7 +224,7 @@ result_t db_get_dht_str(node_ctx_t *ctx) { * ****/ result_t db_get_pins_str(node_ctx_t *ctx) { - result_t res_str = shogdb_get(ctx, "pins/get_pins", NULL); + result_t res_str = shogdb_get_value(ctx, "pins/get_pins", NULL); char *str = PROPAGATE(res_str); // LOG(INFO, "PINS: %s", str); @@ -235,7 +235,7 @@ result_t db_get_pins_str(node_ctx_t *ctx) { result_t db_get_pin_label(node_ctx_t *ctx, char *shoggoth_id) { char *path = string_from("pins/get_pin_label/", shoggoth_id, NULL); - result_t res_str = shogdb_get(ctx, path, NULL); + result_t res_str = shogdb_get_value(ctx, path, NULL); char *str = PROPAGATE(res_str); nfree(path); @@ -268,7 +268,7 @@ result_t db_dht_add_item(node_ctx_t *ctx, dht_item_t *item) { result_t res_item_str = dht_item_to_str(item); char *item_str = PROPAGATE(res_item_str); - result_t res_str = shogdb_get(ctx, "dht/add_item", item_str); + result_t res_str = shogdb_get_value(ctx, "dht/add_item", item_str); char *str = PROPAGATE(res_str); nfree(str); @@ -278,7 +278,7 @@ result_t db_dht_add_item(node_ctx_t *ctx, dht_item_t *item) { } result_t db_dht_remove_item(node_ctx_t *ctx, char *node_id) { - result_t res_str = shogdb_get(ctx, "dht/remove_item", node_id); + result_t res_str = shogdb_get_value(ctx, "dht/remove_item", node_id); char *str = PROPAGATE(res_str); nfree(str); @@ -287,7 +287,7 @@ result_t db_dht_remove_item(node_ctx_t *ctx, char *node_id) { result_t db_increment_unreachable_count(node_ctx_t *ctx, char *node_id) { result_t res_str = - shogdb_get(ctx, "dht/increment_unreachable_count", node_id); + shogdb_get_value(ctx, "dht/increment_unreachable_count", node_id); char *str = PROPAGATE(res_str); nfree(str); @@ -295,7 +295,7 @@ result_t db_increment_unreachable_count(node_ctx_t *ctx, char *node_id) { } result_t db_reset_unreachable_count(node_ctx_t *ctx, char *node_id) { - result_t res_str = shogdb_get(ctx, "dht/reset_unreachable_count", node_id); + result_t res_str = shogdb_get_value(ctx, "dht/reset_unreachable_count", node_id); char *str = PROPAGATE(res_str); nfree(str); @@ -303,7 +303,7 @@ result_t db_reset_unreachable_count(node_ctx_t *ctx, char *node_id) { } result_t db_get_unreachable_count(node_ctx_t *ctx, char *node_id) { - result_t res_str = shogdb_get(ctx, "dht/get_unreachable_count", node_id); + result_t res_str = shogdb_get_value(ctx, "dht/get_unreachable_count", node_id); char *str = PROPAGATE(res_str); return OK(str); @@ -316,7 +316,7 @@ result_t db_get_unreachable_count(node_ctx_t *ctx, char *node_id) { result_t db_pins_add_resource(node_ctx_t *ctx, char *shoggoth_id, char *label) { char *path = string_from("pins/add_resource/", shoggoth_id, "/", label, NULL); - result_t res_str = shogdb_get(ctx, path, NULL); + result_t res_str = shogdb_get_value(ctx, path, NULL); char *str = PROPAGATE(res_str); nfree(str); nfree(path); @@ -327,7 +327,7 @@ result_t db_pins_add_resource(node_ctx_t *ctx, char *shoggoth_id, char *label) { result_t db_pins_remove_resource(node_ctx_t *ctx, char *shoggoth_id) { char *path = string_from("pins/remove_resource/", shoggoth_id, NULL); - result_t res_str = shogdb_get(ctx, path, NULL); + result_t res_str = shogdb_get_value(ctx, path, NULL); char *str = PROPAGATE(res_str); nfree(str); @@ -335,7 +335,7 @@ result_t db_pins_remove_resource(node_ctx_t *ctx, char *shoggoth_id) { } result_t db_get_peers_with_pin(node_ctx_t *ctx, char *shoggoth_id) { - result_t res_str = shogdb_get(ctx, "dht/get_peers_with_pins", shoggoth_id); + result_t res_str = shogdb_get_value(ctx, "dht/get_peers_with_pins", shoggoth_id); char *str = PROPAGATE(res_str); // LOG(INFO, "PINS: %s", str); @@ -344,7 +344,7 @@ result_t db_get_peers_with_pin(node_ctx_t *ctx, char *shoggoth_id) { } result_t db_clear_peer_pins(node_ctx_t *ctx, char *node_id) { - result_t res_str = shogdb_get(ctx, "dht/peer_clear_pins", node_id); + result_t res_str = shogdb_get_value(ctx, "dht/peer_clear_pins", node_id); char *str = PROPAGATE(res_str); nfree(str); @@ -357,7 +357,7 @@ result_t db_peer_pins_add_resource(node_ctx_t *ctx, char *node_id, char endpoint[256]; sprintf(endpoint, "dht/peer_pins_add_resource/%s", node_id); - result_t res_str = shogdb_get(ctx, endpoint, shoggoth_id); + result_t res_str = shogdb_get_value(ctx, endpoint, shoggoth_id); char *str = PROPAGATE(res_str); nfree(str); @@ -365,7 +365,7 @@ result_t db_peer_pins_add_resource(node_ctx_t *ctx, char *node_id, } result_t db_clear_local_pins(node_ctx_t *ctx) { - result_t res_str = shogdb_get(ctx, "pins/clear", NULL); + result_t res_str = shogdb_get_value(ctx, "pins/clear", NULL); char *str = PROPAGATE(res_str); nfree(str); diff --git a/src/node/dbconfig.toml b/src/node/dbconfig.toml new file mode 100644 index 0000000..11c0a71 --- /dev/null +++ b/src/node/dbconfig.toml @@ -0,0 +1,8 @@ +[network] +host = "127.0.0.1" +port = 6961 + +[save] +enabled = true +path = "./save.sdb" +interval = 2 # seconds From 81236748b584623ff556691aa21409e80808fb03 Mon Sep 17 00:00:00 2001 From: Netrunner Date: Mon, 6 May 2024 21:23:06 +0100 Subject: [PATCH 4/4] shogdb: implement shogdb cli --- shogdb/README.txt | 5 ++- shogdb/examples/simple.c | 2 +- shogdb/makefile | 9 +++++ shogdb/src/cli/cli.c | 73 ++++++++++++++++++++++++++++++++++++++ shogdb/src/client/client.c | 45 +++++++++++++++++++++++ shogdb/src/client/client.h | 2 ++ 6 files changed, 134 insertions(+), 2 deletions(-) create mode 100644 shogdb/src/cli/cli.c diff --git a/shogdb/README.txt b/shogdb/README.txt index 2eef5d1..be1217d 100644 --- a/shogdb/README.txt +++ b/shogdb/README.txt @@ -27,10 +27,13 @@ USING SHOGDB Using the HTTP API ================================================ - Using the C client library ================================================ +Using the CLI +================================================ + + Configuration diff --git a/shogdb/examples/simple.c b/shogdb/examples/simple.c index ec84b2d..af295bc 100644 --- a/shogdb/examples/simple.c +++ b/shogdb/examples/simple.c @@ -30,7 +30,7 @@ int main() { db_value_t *res_json = UNWRAP(shogdb_get(db_ctx, "my_json")); printf("JSON VALUE: %s\n", cJSON_Print(res_json->value_json)); - UNWRAP(shogdb_delete(db_ctx, "my_str")); + // UNWRAP(shogdb_delete(db_ctx, "my_str")); char *res_all = UNWRAP(shogdb_print(db_ctx)); printf("ALL VALUES: %s\n", res_all); diff --git a/shogdb/makefile b/shogdb/makefile index f1b94c4..d3b472d 100644 --- a/shogdb/makefile +++ b/shogdb/makefile @@ -29,6 +29,15 @@ client: target-dir $(CC) $(CFLAGS) -c ./src/client/client.c -o ./target/client.o ar rcs ./target/shogdb-client.a ./target/client.o +cli: + $(CC) -g $(CFLAGS) ./src/cli/cli.c ./src/client/client.c $(STATIC_LIBS) $(LDFLAGS) -o ./target/cli + +install-cli: + cp ./target/cli ~/bin/shogdbcli + +run-cli: cli + ./target/cli $(A) + client-sanitized: target-dir echo "Building shogdb client (sanitized)..." $(CC) $(CFLAGS) $(CFLAGS_SANITIZED) -c ./src/client/client.c -o ./target/client.o diff --git a/shogdb/src/cli/cli.c b/shogdb/src/cli/cli.c new file mode 100644 index 0000000..bde1e18 --- /dev/null +++ b/shogdb/src/cli/cli.c @@ -0,0 +1,73 @@ +#include + +#include "../../include/cjson.h" +#include "../client/client.h" + +int main(int argc, char **argv) { + NETLIBC_INIT(); + + if (argc < 2) { + PANIC("no argument supplied"); + } + + char *address = argv[1]; + + shogdb_ctx_t *db_ctx = new_shogdb(address); + + char input[100]; + + do { + // Prompt the user for input + printf("> "); + + // Read the input + fgets(input, sizeof(input), stdin); + + // Remove the trailing newline character + input[strcspn(input, "\n")] = '\0'; + + if (strlen(input) < 3) { + printf("invalid command - too short `%s`\n", input); + continue; + } + + // Check if the user wants to exit + if (strcmp(input, "exit") == 0) { + break; + } else if (strcmp(input, "help") == 0) { + printf("Commands:\n"); + printf("help - show this screen\n"); + printf("exit - exit the program\n"); + printf("print - print all the keys and their values\n"); + printf("address - show the server address\n"); + printf("\n"); + } else if (strcmp(input, "print") == 0) { + char *res_all = UNWRAP(shogdb_print(db_ctx)); + printf("%s\n", res_all); + } else if (strcmp(input, "address") == 0) { + printf("%s\n", address); + } else if (strncmp(input, "GET ", 4) == 0) { + char *key = &input[4]; + + db_value_t *res = UNWRAP(shogdb_get(db_ctx, key)); + char *res_str = shogdb_print_value(res); + + printf("%s\n", res_str); + } else if (strncmp(input, "SET ", 4) == 0) { + // char *key = &input[4]; + + // db_value_t *res = UNWRAP(shogdb_get(db_ctx, key)); + // char *res_str = shogdb_print_value(res); + + printf("OK\n"); + } else { + printf("invalid command `%s`\n", input); + } + } while (1); + + printf("Exiting ...\n"); + + free_shogdb(db_ctx); + + return 0; +} diff --git a/shogdb/src/client/client.c b/shogdb/src/client/client.c index b02cc47..121c4e7 100644 --- a/shogdb/src/client/client.c +++ b/shogdb/src/client/client.c @@ -18,6 +18,47 @@ #include #include +char *shogdb_print_value(db_value_t *value) { + char *value_type = value_type_to_str(value->value_type); + + char *res = NULL; + + if (value->value_type == VALUE_STR) { + res = string_from(value_type, " ", value->value_str, NULL); + } else if (value->value_type == VALUE_ERR) { + res = string_from(value_type, " ", value->value_err, NULL); + } else if (value->value_type == VALUE_BOOL) { + if (value->value_bool == 1) { + res = string_from(value_type, " true", NULL); + } else { + res = string_from(value_type, " false", NULL); + } + } else if (value->value_type == VALUE_UINT) { + char val[256]; + sprintf(val, U64_FORMAT_SPECIFIER, value->value_uint); + + res = string_from(value_type, " ", val, NULL); + } else if (value->value_type == VALUE_INT) { + char val[256]; + sprintf(val, S64_FORMAT_SPECIFIER, value->value_int); + + res = string_from(value_type, " ", val, NULL); + } else if (value->value_type == VALUE_FLOAT) { + char val[256]; + sprintf(val, F64_FORMAT_SPECIFIER, value->value_float); + + res = string_from(value_type, " ", val, NULL); + } else if (value->value_type == VALUE_JSON) { + char *str = cJSON_Print(value->value_json); + res = string_from(value_type, " ", str, NULL); + free(str); + } else { + PANIC("unhandled type"); + } + + return res; +} + result_t shogdb_set(shogdb_ctx_t *ctx, char *key, char *value) { char url[256]; sprintf(url, "%s/set/%s", ctx->address, key); @@ -121,6 +162,10 @@ result_t shogdb_get(shogdb_ctx_t *ctx, char *key) { result_t res = shogdb_parse_message(resp->response_body); db_value_t *value = PROPAGATE(res); + if (value->value_type == VALUE_ERR) { + return ERR(value->value_err); + } + nfree(resp->response_body); sonic_free_response(resp); diff --git a/shogdb/src/client/client.h b/shogdb/src/client/client.h index 486cbb2..0e2f0e3 100644 --- a/shogdb/src/client/client.h +++ b/shogdb/src/client/client.h @@ -59,6 +59,8 @@ result_t shogdb_set_bool(shogdb_ctx_t *ctx, char *key, bool value); result_t shogdb_set_json(shogdb_ctx_t *ctx, char *key, char *value); result_t shogdb_print(shogdb_ctx_t *ctx); +char *shogdb_print_value(db_value_t *value); + result_t shogdb_get(shogdb_ctx_t *ctx, char *key); result_t shogdb_delete(shogdb_ctx_t *ctx, char *key);