diff options
Diffstat (limited to 'src/protocol.c')
-rw-r--r-- | src/protocol.c | 310 |
1 files changed, 310 insertions, 0 deletions
diff --git a/src/protocol.c b/src/protocol.c new file mode 100644 index 0000000..77b806a --- /dev/null +++ b/src/protocol.c @@ -0,0 +1,310 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright © 2020 rsiddharth <s@ricketyspace.net> + */ + +#include <protocol.h> + +static TSTree *tst; + +int sscreate(char *key) +{ + check(key != NULL || strlen(key) < 1, "key invalid"); + + // 1. Check if key is already in the tree. + Record *rec = (Record *) TSTree_search(tst, key, strlen(key)); + + // If it's already there; there's nothing to do. + if (rec != NULL && rec->deleted == 0) { + return 1; + } + // If it's already there and deleted, undelete it. + if (rec != NULL && rec->deleted == 1) { + rec->deleted = 0; + + // Allocate fresh Stats. + rec->st = Stats_create(); + check(rec->st != NULL, "stats creation failed"); + + return 2; + } + + // 2. Create bstring from 'key'. + bstring k = bfromcstr(key); + check(k != NULL, "key creation failed"); + + // 3. Allocate fresh Stats. + Stats *st = Stats_create(); + check(st != NULL, "stats creation failed"); + + // 4. Create Record. + rec = (Record *) calloc(1, sizeof(Record)); + check_mem(rec); + + // 5. Initialize Record. + rec->key = k; + rec->st = st; + rec->deleted = 0; + + // 6. Add Record to tree. + tst = TSTree_insert(tst, key, strlen(key), rec); + check(tst != NULL, "tstree insert failed"); + + return 0; + error: + return -1; +} + +int ssdelete(char *key) +{ + check(key != NULL || strlen(key) < 1, "key invalid"); + check(tst != NULL, "tstree not initialized"); + + Record *rec = (Record *) TSTree_search(tst, key, strlen(key)); + if (rec == NULL) { + // key does not exists. + return 0; + } + + // Mark as deleted. + rec->deleted = 1; + + // Free Stats. + free(rec->st); + + return 0; + error: + return -1; +} + +int sssample_parent(char *key, double s) +{ + check(key != NULL || strlen(key) < 1, "key invalid"); + check(tst != NULL, "tstree not initialized"); + + // 1. Try to get Record with key prefix. + Record *rec = (Record *) TSTree_search_prefix(tst, key, strlen(key)); + + if (rec == NULL) { + // No record with key prefix. + return 0; + } + check(rec->st != NULL, "record's st invalid"); + + if (rec->deleted == 1) { + // Record was deleted; nop. + return 0; + } + + // 2. Sample! + Stats_sample(rec->st, s); + + return 1; + error: + return -1; +} + +double sssample(char *key, double s) +{ + check(key != NULL || strlen(key) < 1, "key invalid"); + check(tst != NULL, "tstree not initialized"); + + // 1. Try to get Record for key. + Record *rec = (Record *) TSTree_search(tst, key, strlen(key)); + + check(rec != NULL, "record not found"); + check(rec->st != NULL, "record's st invalid"); + check(rec->deleted != 1, "record was deleted"); + + // 2. Sample! + Stats_sample(rec->st, s); + + // 3. Sample parent! + int rc = sssample_parent(key, s); + check(rc >= 0, "sampling parent failed"); + + // 4. Get mean. + double m = Stats_mean(rec->st); + + return m; + error: + return -1; +} + +double ssmean(char *key) +{ + check(key != NULL || strlen(key) < 1, "key invalid"); + check(tst != NULL, "tstree not initialized"); + + // 1. Try to get Record for key. + Record *rec = (Record *) TSTree_search(tst, key, strlen(key)); + + check(rec != NULL, "record not found"); + check(rec->deleted != 1, "record was deleted"); + check(rec->st != NULL, "record's st invalid"); + + // 2. Get mean. + double m = Stats_mean(rec->st); + + return m; + error: + return -1; +} + +char *ssdump(char *key) +{ + check(key != NULL && strlen(key) > 0, "key invalid"); + check(tst != NULL, "tstree not initialized"); + + // 1. create bstring from 'key'. + Record *rec = (Record *) TSTree_search(tst, key, strlen(key)); + + check(rec != NULL, "record not found"); + check(rec->st != NULL, "stats not found for key"); + check(rec->deleted != 1, "record was deleted"); + + // 2. get dump. + char *dstr = Stats_dump(rec->st); + check(dstr != NULL, "dump failed for key"); + + return dstr; + error: + return NULL; +} + +// meant to be used by sslist. +void traverse_tree(void *value, void *data) +{ + Record *rec = (Record *) value; + bstring bstr = (bstring) data; + + check(rec != NULL, "Record is NULL"); + check(rec->deleted != 1, "Record was deleted"); + check(bstr != NULL, "bstr is NULL"); + check(rec->key != NULL, "Record's key is NULL"); + check(blength(rec->key) > 0, "Record's key is an empty string"); + + int rc = bconcat(bstr, rec->key); + check(rc == BSTR_OK, "bstr key concat failed"); + + rc = bconchar(bstr, '\n'); + check(rc == BSTR_OK, "bstr newline concat failed"); + + error: + return; +} + + +char *sslist() +{ + char *list = NULL, *tmp = NULL; + + if (tst == NULL) { + list = (char *) calloc(7 + 1, sizeof(char)); + check_mem(list); + + list = strncpy(list, "EMPTY\n\r", 7); + + return list; + } + + // 1. Create "accumulator" string. + bstring ks_str = bfromcstr(""); + check(ks_str != NULL, "error creating keys_str"); + + // 2. Accumulate keys into "accumulator" string. + TSTree_traverse(tst, traverse_tree, ks_str); + + // 3. Make result. + tmp = bstr2cstr(ks_str, ' '); + + list = (char *) calloc(strlen(tmp) + 1, sizeof(char)); + check_mem(list); + + list = strncpy(list, tmp, strlen(tmp)); + + // 4. Clean up. + bcstrfree(tmp); + + // 3. Return result. + return list; + error: + if (tmp) { + bcstrfree(tmp); + } + return NULL; +} + +int ssstore(char *key) +{ + check(key != NULL && strlen(key) > 0, "key invalid"); + check(tst != NULL, "tstree not initialized"); + + // 1. create bstring from 'key'. + Record *rec = (Record *) TSTree_search(tst, key, strlen(key)); + + check(rec != NULL, "record not found"); + check(rec->st != NULL, "stats not found for key"); + check(rec->deleted != 1, "record was deleted"); + + // 2. stringify the stats. + char *st_str = Stats_stringify(rec->st); + check(st_str != NULL, "stats stringify failed"); + + // 3. store stats in db. + int rc = db_store(key, st_str); + check(rc == 0, "db store failed"); + + return 0; + error: + return -1; +} + +int ssload(char *from, char *to) +{ + check(from != NULL && strlen(from) > 0, "from invalid"); + check(to != NULL && strlen(to) > 0, "to invalid"); + check(tst != NULL, "tstree not initialized"); + + // 1. Check if 'to' key already exists. + Record *rec = (Record *) TSTree_search(tst, to, strlen(to)); + + // 2. if 'to' key exists return immediately with -2. + if (rec != NULL && rec->deleted == 0) { + return -2; + } + + // 3. read 'from' key from database. + char *st_str = db_load(from); + check(st_str != NULL, "db load failed"); + + // 4. construct stats from string. + Stats *st = Stats_unstringify(st_str); + check(st != NULL, "stats unstringify failed"); + + // 5. create Record if needed. + int rec_created = 0; + if (rec == NULL) { + rec = (Record *) calloc(1, sizeof(Record)); + check_mem(rec); + rec_created = 1; + } + + // 6. get things ready for insertiion + bstring tk = bfromcstr(to); + check(tk != NULL, "key creation failed"); + + rec->key = tk; + rec->st = st; + rec->deleted = 0; + + // 7. insert Record into 'to' key in the TSTree if needed. + if (rec_created == 1) { + tst = TSTree_insert(tst, to, strlen(to), rec); + check(tst != NULL, "tstree insert failed"); + } + + return 0; + error: + return -1; +} |