-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add index mapping buckets for faster search
- Loading branch information
1 parent
713ded5
commit a4db515
Showing
4 changed files
with
133 additions
and
77 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,66 +1,110 @@ | ||
#include "index.h" | ||
|
||
#include <assert.h> | ||
#include <inttypes.h> | ||
#include <stdlib.h> | ||
#include <string.h> | ||
|
||
#define INDEXMAXFP 512 | ||
|
||
struct inode_s* indexfind(struct inode_s* idx, const char* fp) { | ||
struct inode_s* head = idx; | ||
static int indexhash(const char* fp) { | ||
int h = 0; | ||
for (const char* p = fp; *p != '\0'; p++) h = (h << 5) - h + *p; | ||
if (h < 0) h = -h; | ||
return h % INDEXBUCKETS; | ||
} | ||
|
||
struct inode_s* indexfind(struct index_s* idx, const char* fp) { | ||
struct inode_s* head = idx->buckets[indexhash(fp)]; | ||
while (head != NULL) { | ||
if (strcmp(head->fp, fp) == 0) return head; | ||
head = head->next; | ||
} | ||
return NULL; | ||
} | ||
|
||
int indexwrite(struct inode_s* idx, FILE* s) { | ||
static int indexnodecmp(const void* a, const void* b) { | ||
const struct inode_s* na = *(const struct inode_s**) a; | ||
const struct inode_s* nb = *(const struct inode_s**) b; | ||
return strcmp(na->fp, nb->fp); | ||
} | ||
|
||
int indexwrite(struct index_s* idx, FILE* s) { | ||
struct inode_s** fl; | ||
if ((fl = indexlist(idx)) == NULL) return -1; | ||
qsort(fl, idx->size, sizeof(struct inode_s*), indexnodecmp); | ||
|
||
char lbuf[INDEXMAXFP]; /* line output format buffer */ | ||
|
||
struct inode_s* head; | ||
for (head = idx; head != NULL; head = head->next) { | ||
int err = 0; | ||
for (size_t i = 0; i < idx->size; i++) { | ||
struct inode_s* node = fl[i]; | ||
const int n = snprintf(lbuf, sizeof(lbuf), "%s,%" PRIu64 ",%" PRIu64 "\n", | ||
head->fp, head->st.lmod, head->st.fsze); | ||
if (fwrite(lbuf, n, 1, s) != 1) return -1; | ||
node->fp, node->st.lmod, node->st.fsze); | ||
if (fwrite(lbuf, n, 1, s) != 1) { | ||
err = -1; | ||
break; | ||
} | ||
} | ||
|
||
return 0; | ||
free(fl); | ||
return err; | ||
} | ||
|
||
int indexread(struct inode_s** idx, FILE* s) { | ||
char fp[INDEXMAXFP] = {0}; /* fscanf filepath string buffer */ | ||
int indexread(struct index_s* idx, FILE* s) { | ||
char fp[INDEXMAXFP] = {0}; /* fscanf filepath string buffer */ | ||
struct inode_s b = {fp, {0}, NULL}; /* fscanf node buffer */ | ||
|
||
while (fscanf(s, "%[^,],%" PRIu64 ",%" PRIu64 "\n", b.fp, &b.st.lmod, | ||
&b.st.fsze) == 3) { | ||
// duplicate the string onto the heap | ||
if ((b.fp = strdup(b.fp)) == NULL) return -1; | ||
struct inode_s* r; | ||
if ((r = indexprepend(*idx, b)) == NULL) { | ||
free(*idx), *idx = NULL; | ||
return -1; | ||
} | ||
*idx = r; | ||
if (indexput(idx, b) == NULL) return -1; | ||
b.fp = fp; | ||
} | ||
|
||
return 0; | ||
} | ||
|
||
struct inode_s* indexprepend(struct inode_s* idx, const struct inode_s tail) { | ||
static struct inode_s* indexprepend(struct inode_s* idx, | ||
const struct inode_s tail) { | ||
struct inode_s* node; | ||
if ((node = malloc(sizeof(tail))) == NULL) return NULL; | ||
memcpy(node, &tail, sizeof(tail)); | ||
node->next = idx; | ||
return node; | ||
} | ||
|
||
void indexfree_r(struct inode_s* idx) { | ||
struct inode_s* indexput(struct index_s* idx, const struct inode_s node) { | ||
struct inode_s* bucket = idx->buckets[indexhash(node.fp)]; | ||
struct inode_s* head = indexprepend(bucket, node); | ||
if (head == NULL) return NULL; | ||
idx->buckets[indexhash(node.fp)] = head; | ||
idx->size++; | ||
return head; | ||
} | ||
|
||
static void indexfree_r(struct inode_s* idx) { | ||
struct inode_s *head, *prev; | ||
for (head = idx; head != NULL;) { | ||
free(head->fp); | ||
prev = head, head = head->next; | ||
free(prev); /* free previous node */ | ||
} | ||
} | ||
|
||
void indexfree(struct index_s* idx) { | ||
for (int i = 0; i < INDEXBUCKETS; i++) indexfree_r(idx->buckets[i]); | ||
} | ||
|
||
struct inode_s** indexlist(const struct index_s* idx) { | ||
struct inode_s** fl; | ||
if ((fl = calloc(idx->size, sizeof(struct inode_s*))) == NULL) return NULL; | ||
size_t ni = 0; | ||
for (int i = 0; i < INDEXBUCKETS; i++) { | ||
for (struct inode_s* head = idx->buckets[i]; head != NULL; | ||
head = head->next) | ||
fl[ni++] = head; | ||
} | ||
assert(ni == idx->size); | ||
return fl; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters