diff options
| author | Soikk | 2022-07-24 22:18:31 +0200 |
|---|---|---|
| committer | Soikk | 2022-07-24 22:18:31 +0200 |
| commit | ff5da06da823ac3a0bc7e89b35ed573255139b2d (patch) | |
| tree | 41551fe546a34ad8f771b5a75eb4d883db5fb4ac /src/database.c | |
| parent | caacd02d3c6a6ab3ddea620214ee5d1836de2c31 (diff) | |
| download | soikk-DB-ff5da06da823ac3a0bc7e89b35ed573255139b2d.tar.xz soikk-DB-ff5da06da823ac3a0bc7e89b35ed573255139b2d.tar.zst | |
Added ref count for files & tags. Refactored database.c. Removed tags.h but kept documentation.
Diffstat (limited to 'src/database.c')
| -rw-r--r-- | src/database.c | 152 |
1 files changed, 98 insertions, 54 deletions
diff --git a/src/database.c b/src/database.c index db7759e..f034464 100644 --- a/src/database.c +++ b/src/database.c @@ -8,6 +8,8 @@ database *newDatabase(char *name){ db->ltags = newLtable(0); db->hfiles = newHtable(0); db->htags = newHtable(0); + db->fcount = newHtable(0); + db->tcount = newHtable(0); db->map = newMtable(0); return db; } @@ -19,6 +21,7 @@ database *loadDatabase(const char* path){ 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); @@ -26,9 +29,12 @@ database *loadDatabase(const char* path){ db->ltags = loadLtable(fp); db->hfiles = loadHtable(fp); db->htags = loadHtable(fp); + db->fcount = loadHtable(fp); + db->tcount = loadHtable(fp); db->map = loadMtable(fp); - char end[4]; - fread(&end, sizeof(char), 3, 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); } @@ -47,6 +53,8 @@ int storeDatabase(database *db, const char *path){ storeLtable(db->ltags, fp); storeHtable(db->hfiles, fp); storeHtable(db->htags, fp); + storeHtable(db->fcount, fp); + storeHtable(db->tcount, fp); storeMtable(db->map, fp); char end[3] = "END"; @@ -56,6 +64,44 @@ int storeDatabase(database *db, const char *path){ return 0; } +static void increaseCount(htable *ht, uint64_t i){ + ht->table[i]++; +} + +uint64_t addFile(database *db, char *file){ + uint32_t l; + file = normalizeStrLimit(file, &l, MAXPATH-1); + uint64_t h = crc64(0, file, l); + uint64_t i = htableSearch(db->hfiles, h); + + if(i == -1){ + ltableAdd(db->lfiles, file); + htableAdd(db->hfiles, h); + htableAdd(db->fcount, 0); + i = db->hfiles->size-1; + } + increaseCount(db->fcount, i); + + return i; +} + +uint64_t addTag(database *db, char *tag){ + uint32_t l; + tag = normalizeStrLimit(tag, &l, MAXPATH-1); + uint64_t h = crc64(0, tag, l); + uint64_t i = htableSearch(db->htags, h); + + if(i == -1){ + ltableAdd(db->ltags, tag); + htableAdd(db->htags, h); + htableAdd(db->tcount, 0); + i = db->htags->size-1; + } + increaseCount(db->tcount, i); + + return i; +} + static int addRelation(database *db, relation r){ if(mtableSearch(db->map, r) != -1){ return -1; @@ -66,83 +112,81 @@ static int addRelation(database *db, relation r){ } int addFileTag(database *db, char *file, char *tag){ - uint32_t lf, lt; - file = normalizeStrLimit(file, &lf, MAXPATH-1); - tag = normalizeStrLimit(tag, <, 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; - } - + uint64_t fi = addFile(db, file), ti = addTag(db, tag); 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, <, 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}); + addFileTag(db, file, tag); } 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){ +// Stores in r a list with the indexes of the first n files that have this tag +// If n is 0 or lower, it returns all of them. Stores in rl the length of r +int searchTag(database *db, char *tag, uint64_t n, uint64_t **r, 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 + if(ti == -1){ + return -1; + } - uint64_t c = 0; + *rl = 0; for(uint64_t i = 0; i < db->map->size; ++i){ + if(n < 1 || *rl < n){ + if(db->map->table[i].tag == ti){ + ++(*rl); + } + } + } + *r = malloc((*rl)*sizeof(uint64_t)); + uint64_t c = 0; + for(uint64_t i = 0; i < db->map->size && c < *rl; ++i){ if(db->map->table[i].tag == ti){ - ++c; + (*r)[c++] = db->map->table[i].file; } } - uint64_t *r = malloc(c*sizeof(uint64_t)); - c = 0; + + 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){ + uint32_t l; + file = normalizeStrLimit(file, &l, MAXPATH-1); + uint64_t h = crc64(0, file, l); + uint64_t fi = htableSearch(db->hfiles, h); + if(fi == -1){ + return -1; + } + + *rl = 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; + if(n < 1 || *rl < n){ + if(db->map->table[i].file == fi){ + ++(*rl); + } } } - rl = r; + *r = malloc((*rl)*sizeof(uint64_t)); + uint64_t c = 0; + for(uint64_t i = 0; i < db->map->size && c < *rl; ++i){ + if(db->map->table[i].file == fi){ + (*r)[c++] = db->map->table[i].tag; + } + } + return 0; } @@ -158,11 +202,11 @@ void debugDatabase(database *db){ 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\t+%s (%" PRIu64 ")\n", db->lfiles->table[i], db->fcount->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\t+%s (%" PRIu64 ")\n", db->ltags->table[i], db->tcount->table[i]); } printf("\t-hfiles: %d\n", db->hfiles->size); for(uint64_t i = 0; i < db->hfiles->size; ++i){ |
