aboutsummaryrefslogtreecommitdiff
path: root/src/database.c
diff options
context:
space:
mode:
authorSoikk2022-07-23 01:46:24 +0200
committerSoikk2022-07-23 01:46:24 +0200
commit28578b192d0828a9820983b5624b9bcc3577cd18 (patch)
tree2f30b1730f30a7eeee80995ee3984c10f5bdc2ff /src/database.c
parent377dc104be127291ede5b32640c23eea0ba6791a (diff)
downloadsoikk-DB-28578b192d0828a9820983b5624b9bcc3577cd18.tar.xz
soikk-DB-28578b192d0828a9820983b5624b9bcc3577cd18.tar.zst
Improved the database storage system. Added persistency.
Diffstat (limited to 'src/database.c')
-rw-r--r--src/database.c179
1 files changed, 179 insertions, 0 deletions
diff --git a/src/database.c b/src/database.c
new file mode 100644
index 0000000..521b0a1
--- /dev/null
+++ b/src/database.c
@@ -0,0 +1,179 @@
+#include "db.h"
+
+
+database *newDatabase(char *name){
+ database *db = malloc(sizeof(database));
+ memcpy(db->name, name, len(name)+1);
+ db->lfiles = newLtable(0);
+ db->ltags = newLtable(0);
+ db->hfiles = newHtable(0);
+ db->htags = newHtable(0);
+ db->map = newMtable(0);
+ return db;
+}
+
+database *loadDatabase(const char* path){
+ FILE *fp = fopen(path, "rb");
+ char *header = calloc(2, sizeof(char));
+ fread(header, sizeof(char), 2, fp);
+ if(!sameStr(header, "DB")){
+ printf("header is %c%c and not DB\n", header[0], header[1]);
+ }
+ char name[32];
+ fread(&name, sizeof(char), 32, fp);
+ database *db = newDatabase(name);
+ db->lfiles = loadLtable(fp);
+ db->ltags = loadLtable(fp);
+ db->hfiles = loadHtable(fp);
+ db->htags = loadHtable(fp);
+ db->map = loadMtable(fp);
+ char end[4];
+ fread(&end, sizeof(char), 3, fp);
+ if(!sameStr(end, "END")){
+ printf("end is %s and not END\n", end);
+ }
+ fclose(fp);
+ return db;
+}
+
+int storeDatabase(database *db, const char *path){
+ FILE *fp = fopen(path, "wb");
+
+ char header[2] = "DB";
+ fwrite(header, sizeof(char), 2, fp);
+ fwrite(db->name, sizeof(char), 32, fp);
+
+ storeLtable(db->lfiles, fp);
+ storeLtable(db->ltags, fp);
+ storeHtable(db->hfiles, fp);
+ storeHtable(db->htags, fp);
+ storeMtable(db->map, fp);
+
+ char end[3] = "END";
+ fwrite(end, sizeof(char), 3, fp);
+
+ fclose(fp);
+}
+
+static int addRelation(database *db, relation r){
+ if(mtableSearch(db->map, r) != -1){
+ return -1;
+ }
+ mtableAdd(db->map, r);
+
+ return 0;
+}
+
+int addFileTag(database *db, char *file, char *tag){
+ uint32_t lf, lt;
+ file = normalizeStrLimit(file, &lf, MAXPATH-1);
+ tag = normalizeStrLimit(tag, &lt, MAXPATH-1);
+ uint64_t hf = crc64(0, file, lf), ht = crc64(0, tag, lt);
+ uint64_t fi = htableSearch(db->hfiles, hf), ti = htableSearch(db->htags, ht);
+
+ if(fi == -1){
+ ltableAdd(db->lfiles, file);
+ htableAdd(db->hfiles, hf);
+ fi = db->hfiles->size-1;
+ }
+ if(ti == -1){
+ ltableAdd(db->ltags, tag);
+ htableAdd(db->htags, ht);
+ ti = db->htags->size-1;
+ }
+
+ addRelation(db, (relation){.file = fi, .tag = ti});
+ return 0;
+}
+
+int addFileTags(database *db, char *file, int ntags, ...){
+ uint32_t lf;
+ file = normalizeStrLimit(file, &lf, MAXPATH-1);
+ uint64_t hf = crc64(0, file, lf);
+ uint64_t fi = htableSearch(db->hfiles, hf);
+
+ if(fi == -1){
+ ltableAdd(db->lfiles, file);
+ htableAdd(db->hfiles, hf);
+ fi = db->hfiles->size-1;
+ }
+
+ va_list tags;
+ va_start(tags, ntags);
+ for(uint64_t i = 0; i < ntags; ++i){
+ char *tag = va_arg(tags, char*);
+ uint32_t lt;
+ tag = normalizeStrLimit(tag, &lt, MAXPATH-1);
+ uint64_t ht = crc64(0, tag, lt);
+ uint64_t ti = htableSearch(db->htags, ht);
+
+ if(ti == -1){
+ ltableAdd(db->ltags, tag);
+ htableAdd(db->htags, ht);
+ ti = db->htags->size-1;
+ }
+
+ addRelation(db, (relation){.file = fi, .tag = ti});
+ }
+ va_end(tags);
+
+ return 0;
+}
+
+// Should return a list with the indexes of the files that have this tag
+int searchTag(database *db, char *tag, uint64_t *rl){
+ uint32_t l;
+ tag = normalizeStrLimit(tag, &l, MAXPATH-1);
+ uint64_t h = crc64(0, tag, l);
+ uint64_t ti = htableSearch(db->htags, h);
+ // TODO: error checking
+
+ uint64_t c = 0;
+ for(uint64_t i = 0; i < db->map->size; ++i){
+ if(db->map->table[i].tag == ti){
+ ++c;
+ }
+ }
+ uint64_t *r = malloc(c*sizeof(uint64_t));
+ c = 0;
+ for(uint64_t i = 0; i < db->map->size; ++i){
+ if(db->map->table[i].tag == ti){
+ r[c++] = db->map->table[i].file;
+ }
+ }
+ rl = r;
+ return 0;
+}
+
+void printDatabase(database *db){
+ for(uint64_t i = 0; i < db->map->size; ++i){
+ printf("%s -> %s\n", db->lfiles->table[db->map->table[i].file], db->ltags->table[db->map->table[i].tag]);
+ }
+ printf("\n");
+}
+
+void debugDatabase(database *db){
+ printf("\n");
+ printf("Name: %s\n", db->name);
+ printf("\t-lfiles: %d\n", db->lfiles->size);
+ for(uint64_t i = 0; i < db->lfiles->size; ++i){
+ printf("\t\t+%s\n", db->lfiles->table[i]);
+ }
+ printf("\t-ltags: %d\n", db->ltags->size);
+ for(uint64_t i = 0; i < db->ltags->size; ++i){
+ printf("\t\t+%s\n", db->ltags->table[i]);
+ }
+ printf("\t-hfiles: %d\n", db->hfiles->size);
+ for(uint64_t i = 0; i < db->hfiles->size; ++i){
+ printf("\t\t+%" PRIu64 "\n", db->hfiles->table[i]);
+ }
+ printf("\t-htags: %d\n", db->htags->size);
+ for(uint64_t i = 0; i < db->htags->size; ++i){
+ printf("\t\t+%" PRIu64 "\n", db->htags->table[i]);
+ }
+ printf("\t-map: %d\n", db->map->size);
+ for(uint64_t i = 0; i < db->map->size; ++i){
+ printf("\t\t+%" PRIu64 ":%" PRIu64 "\n", db->map->table[i].file, db->map->table[i].tag);
+ }
+ printf("\n");
+}