From: Soikk <76824648+Soikk@users.noreply.github.com> Date: Sun, 7 Aug 2022 13:41:19 +0000 (+0200) Subject: Added removing things from db. Ref counts update when removing things. Added changelog. X-Git-Url: https://git.xolatile.top/?a=commitdiff_plain;h=5dd0d7700fa98197cdadaa2369d789e092cc0f49;p=soikk-DB.git Added removing things from db. Ref counts update when removing things. Added changelog. --- diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 0000000..9565fa1 --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,5 @@ +1659879571 (Sun Aug 07 2022 15:39:31 GMT+0200 (Central European Summer Time)) +Added removing things from db. Ref counts update when removing things. Added changelog. + +1659832822 (Sun Aug 07 2022 02:40:22 GMT+0200 (Central European Summer Time)) +Created changelog diff --git a/TODO b/TODO index 3ffe276..e7a6030 100644 --- a/TODO +++ b/TODO @@ -1,12 +1,17 @@ -TODO Use inttypes.h add, divide and multiply functions - -TODO Consider refactoring tables to B-Trees (better performance?) - -TODO Add remove* functions, restructure tables functions +TODO Standarize function names TODO Get rid of old functionalities (strnatcmp, BM) ---------------------------------------------------------------- +DONE Make it so count of other files/tags gets updated when deleting files/tags + +DONE Add remove* functions, restructure tables functions + +DONE Add changelog files + +DONE Consider refactoring tables to B-Trees (better performance?) + NOTE: Ended up using AVL trees instead, only needed for hashes + DONE Change DB model from struct row typedef struct{ char path[MAXPATH]; diff --git a/include/database.h b/include/database.h index 5f2d99d..1ae65b6 100644 --- a/include/database.h +++ b/include/database.h @@ -15,10 +15,6 @@ typedef struct database{ database *newDatabase(char *name); -database *loadDatabase(const char* path); - -int storeDatabase(database *db, const char *path); - uint64_t addFile(database *db, char *file); uint64_t addTag(database *db, char *tag); @@ -27,10 +23,18 @@ int addFileTag(database *db, char *file, char *tag); int addFileTags(database *db, char *file, int ntags, ...); +int removeFile(database *db, char *file); + +int removeTag(database *db, char *tag); + int searchFile(database *db, char *file, uint64_t n, uint64_t **r, uint64_t *rl); int searchTag(database *db, char *tag, uint64_t n, uint64_t **r, uint64_t *rl); +int storeDatabase(database *db, const char *path); + +database *loadDatabase(const char* path); + void printDatabase(database *db); void debugAVLtree(node *n); diff --git a/include/storage.h b/include/storage.h index 8bfc751..dccfa5f 100644 --- a/include/storage.h +++ b/include/storage.h @@ -60,7 +60,7 @@ typedef struct lookupTable{ char **table; // They cant be longer than MAXPATH } ltable; -// Stores a number (used as the count for files and tags in the mapping table) +// Stores a number in the index that references the ltable (used as the count for files and tags in the mapping table) typedef struct countTable{ uint64_t size; uint64_t *table; @@ -94,6 +94,8 @@ ltable *newLtable(uint64_t size); int ltableAdd(ltable *lt, char *str); +int ltableRemove(ltable *lt, char *str); + uint64_t ltableSearch(ltable *lt, char *str); int storeLtable(const ltable *lt, FILE *fp); @@ -106,7 +108,7 @@ ctable *newCtable(uint64_t size); int ctableAdd(ctable *ct, uint64_t n); -int ctableDelete(ctable *ct, uint64_t n); +int ctableRemove(ctable *ct, uint64_t n); uint64_t ctableSearch(ctable *ct, uint64_t n); @@ -120,6 +122,12 @@ mtable *newMtable(uint64_t size); int mtableAdd(mtable *mt, relation r); +int mtableRemove(mtable *mt, relation r); + +int mtableRemoveFile(mtable *mt, uint64_t file); + +int mtableRemoveTag(mtable *mt, uint64_t tag); + uint64_t mtableSearch(mtable *mt, relation r); uint64_t mtableSearchFile(mtable *mt, uint64_t file); @@ -132,8 +140,6 @@ mtable *loadMtable(FILE *fp); // AVL TREE -uint64_t height(node *n); - node *newNode(uint64_t h, uint64_t i); node *insertNode(node *r, uint64_t h, uint64_t i); diff --git a/src/database.c b/src/database.c index a6a9dfa..5b6249b 100644 --- a/src/database.c +++ b/src/database.c @@ -14,60 +14,14 @@ database *newDatabase(char *name){ 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")){ - fprintf(stderr, "Header is '%s' not 'DB'\n", header); - } - - char name[32]; - fread(&name, sizeof(char), 32, fp); - database *db = newDatabase(name); - db->lfiles = loadLtable(fp); - db->ltags = loadLtable(fp); - db->cfiles = loadCtable(fp); - db->ctags = loadCtable(fp); - db->hfiles = loadAVLTree(fp); - db->htags = loadAVLTree(fp); - db->map = loadMtable(fp); - - char *end = calloc(3, sizeof(char)); - fread(end, sizeof(char), 3, fp); - if(!sameStr(end, "END")){ - fprintf(stderr, "End is '%s' 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); - storeCtable(db->cfiles, fp); - storeCtable(db->ctags, fp); - storeAVLTree(db->hfiles, fp); - storeAVLTree(db->htags, fp); - storeMtable(db->map, fp); - - char end[3] = "END"; - fwrite(end, sizeof(char), 3, fp); - - fclose(fp); - return 0; -} - static void increaseCount(ctable *ct, uint64_t i){ ct->table[i]++; } +static void decreaseCount(ctable *ct, uint64_t i){ + ct->table[i]--; +} + uint64_t addFile(database *db, char *file){ uint32_t l; file = normalizeStrLimit(file, &l, MAXPATH-1); @@ -131,6 +85,46 @@ int addFileTags(database *db, char *file, int ntags, ...){ return 0; } +int removeFile(database *db, char *file){ + uint32_t l; + file = normalizeStrLimit(file, &l, MAXPATH-1); + uint64_t i = ltableSearch(db->lfiles, file); + if(i == -1){ + return -1; + } + uint64_t *r, rl; + searchFile(db, file, 0, &r, &rl); + for(uint64_t j = 0; j < rl; ++j){ + decreaseCount(db->ctags, r[j]); + } + uint64_t h = crc64(0, file, l); + ltableRemove(db->lfiles, file); + ctableRemove(db->cfiles, i); + deleteNode(db->hfiles, h); + mtableRemoveFile(db->map, i); + return 0; +} + +int removeTag(database *db, char *tag){ + uint32_t l; + tag = normalizeStrLimit(tag, &l, MAXPATH-1); + uint64_t i = ltableSearch(db->ltags, tag); + if(i == -1){ + return -1; + } + uint64_t *r, rl; + searchTag(db, tag, 0, &r, &rl); + for(uint64_t j = 0; j < rl; ++j){ + decreaseCount(db->cfiles, r[j]); + } + uint64_t h = crc64(0, tag, l); + ltableRemove(db->ltags, tag); + ctableRemove(db->ctags, i); + deleteNode(db->htags, h); + mtableRemoveTag(db->map, i); + return 0; +} + // Stores in r a list with the indexes of the first n tags that this file has // If n is 0 or lower, it returns all of them. Stores in rl the length of r int searchFile(database *db, char *file, uint64_t n, uint64_t **r, uint64_t *rl){ @@ -191,6 +185,56 @@ int searchTag(database *db, char *tag, uint64_t n, uint64_t **r, uint64_t *rl){ return 0; } +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); + storeCtable(db->cfiles, fp); + storeCtable(db->ctags, fp); + storeAVLTree(db->hfiles, fp); + storeAVLTree(db->htags, fp); + storeMtable(db->map, fp); + + char end[3] = "END"; + fwrite(end, sizeof(char), 3, fp); + + fclose(fp); + return 0; +} + +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")){ + fprintf(stderr, "Header is '%s' not 'DB'\n", header); + } + + char name[32]; + fread(&name, sizeof(char), 32, fp); + database *db = newDatabase(name); + db->lfiles = loadLtable(fp); + db->ltags = loadLtable(fp); + db->cfiles = loadCtable(fp); + db->ctags = loadCtable(fp); + db->hfiles = loadAVLTree(fp); + db->htags = loadAVLTree(fp); + db->map = loadMtable(fp); + + char *end = calloc(3, sizeof(char)); + fread(end, sizeof(char), 3, fp); + if(!sameStr(end, "END")){ + fprintf(stderr, "End is '%s' not 'END'\n", end); + } + fclose(fp); + return db; +} + 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]); @@ -217,9 +261,9 @@ void debugDatabase(database *db){ for(uint64_t i = 0; i < db->ltags->size; ++i){ printf("\t\t+%s (%" PRIu64 ")\n", db->ltags->table[i], db->ctags->table[i]); } - printf("\t-hfiles: %d\n", height(db->hfiles)); + printf("\t-hfiles: %d\n", db->lfiles->size); debugAVLtree(db->hfiles); - printf("\t-htags: %d\n", height(db->htags)); + printf("\t-htags: %d\n", db->ltags->size); debugAVLtree(db->htags); printf("\t-map: %d\n", db->map->size); for(uint64_t i = 0; i < db->map->size; ++i){ diff --git a/src/db.db b/src/db.db new file mode 100644 index 0000000..1c12210 Binary files /dev/null and b/src/db.db differ diff --git a/src/main.c b/src/main.c index 71df5bf..c51b5d5 100644 --- a/src/main.c +++ b/src/main.c @@ -4,8 +4,8 @@ int main(){ - database *db = newDatabase("miDB"); inputBuffer *in = newInputBuffer(); + /*database *db = newDatabase("miDB"); addFileTag(db, "vaca.png", "naturaleza"); @@ -13,9 +13,11 @@ int main(){ addFileTag(db, "vaca.png", "lovely"); addFileTags(db, "vaca.png", 3, "nature", "animal", "very cool"); - storeDatabase(db, "db.db"); + loadDatabase(db, "db.db"); - printDatabase(db); + printDatabase(db);*/ + + database *db = loadDatabase("db.db"); debugDatabase(db); @@ -28,6 +30,8 @@ int main(){ } + + while(0){ diff --git a/src/main.exe b/src/main.exe new file mode 100644 index 0000000..9ac3ba5 Binary files /dev/null and b/src/main.exe differ diff --git a/src/storage.c b/src/storage.c index 8ad938d..3e45b2e 100644 --- a/src/storage.c +++ b/src/storage.c @@ -37,6 +37,18 @@ int ltableAdd(ltable *lt, char *str){ return 0; } +int ltableRemove(ltable *lt, char *str){ + uint64_t i = ltableSearch(lt, str); + if(i == -1){ + return -1; + } + lt->size--; + for(uint64_t j = i; j < lt->size-1; ++j){ + lt->table[j] = lt->table[j+1]; + } + return 0; +} + uint64_t ltableSearch(ltable *lt, char *str){ uint32_t l; str = normalizeStrLimit(str, &l, MAXPATH-1); @@ -114,9 +126,8 @@ int ctableAdd(ctable *ct, uint64_t n){ return 0; } -int ctableDelete(ctable *ct, uint64_t n){ - uint64_t i = ctableSearch(ct, n); - if(i == -1){ +int ctableRemove(ctable *ct, uint64_t i){ + if(i >= ct->size){ return -1; } ct->size--; @@ -194,6 +205,52 @@ int mtableAdd(mtable *mt, relation r){ return 0; } +int mtableRemove(mtable *mt, relation r){ + uint64_t i = mtableSearch(mt, r); + if(i == -1){ + return -1; + } + mt->size--; + for(uint64_t j = i; j < mt->size-1; ++j){ + mt->table[j] = mt->table[j+1]; + } + return 0; +} + +int mtableRemoveFile(mtable *mt, uint64_t file){ + relation *nmt = malloc(mt->size*sizeof(relation)); + uint64_t ni = 0; + for(uint64_t i = 0; i < mt->size; ++i){ + if(file != mt->table[i].file){ + nmt[ni] = mt->table[i]; + ++ni; + } + } + mt->size = ni; + mt->table = malloc(mt->size*sizeof(relation)); + for(uint64_t i = 0; i < mt->size; ++i){ + mt->table[i] = nmt[i]; + } + return 0; +} + +int mtableRemoveTag(mtable *mt, uint64_t tag){ + relation *nmt = malloc(mt->size*sizeof(relation)); + uint64_t ni = 0; + for(uint64_t i = 0; i < mt->size; ++i){ + if(tag != mt->table[i].tag){ + nmt[ni] = mt->table[i]; + ++ni; + } + } + mt->size = ni; + mt->table = malloc(mt->size*sizeof(relation)); + for(uint64_t i = 0; i < mt->size; ++i){ + mt->table[i] = nmt[i]; + } + return 0; +} + uint64_t mtableSearch(mtable *mt, relation r){ for(uint64_t i = 0; i < mt->size; ++i){ if(r.file == mt->table[i].file && r.tag == mt->table[i].tag){ @@ -261,7 +318,7 @@ static inline uint64_t max(uint64_t a, uint64_t b){ return ((a > b) ? a : b); } -uint64_t height(node *n){ +static uint64_t height(node *n){ if(n != NULL){ return 1 + max(height(n->left), height(n->right)); } @@ -367,7 +424,7 @@ node *deleteNode(node *r, uint64_t h){ return r; } - uint64_t b = balance(r), bl = balance(r->left), br = balance(r->right); + int64_t b = balance(r), bl = balance(r->left), br = balance(r->right); if(b > 1 && bl >= 0){ // Left left return rotateNodeRight(r); }