aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CHANGELOG5
-rw-r--r--TODO15
-rw-r--r--include/database.h12
-rw-r--r--include/storage.h14
-rw-r--r--src/database.c148
-rw-r--r--src/db.dbbin0 -> 715 bytes
-rw-r--r--src/main.c10
-rw-r--r--src/main.exebin0 -> 73988 bytes
-rw-r--r--src/storage.c67
9 files changed, 198 insertions, 73 deletions
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
--- /dev/null
+++ b/src/db.db
Binary files 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
--- /dev/null
+++ b/src/main.exe
Binary files 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);
}