X-Git-Url: http://git.bytex64.net/?a=blobdiff_plain;f=common%2Fstringbucket.c;h=86efff3cb6a46ae0ff8f6e54c577b804f21d9646;hb=d67dd1bf5a247e20141b9907f5a452da73624235;hp=d892541d8d6ac856b09ba3337672b6f923624962;hpb=ec8746b44dc85fd3e3b42835f779890684a9e90a;p=blerg.git diff --git a/common/stringbucket.c b/common/stringbucket.c index d892541..86efff3 100644 --- a/common/stringbucket.c +++ b/common/stringbucket.c @@ -8,6 +8,7 @@ #include #include #include +#include #include #include @@ -24,38 +25,76 @@ const char * strnchr(const char *s, int c, int n) { return NULL; } -struct stringbucket * stringbucket_open(const char *filename) { +int stringbucket_remap(struct stringbucket *sb) { struct stat st; + + if (sb->list != NULL) { + munmap(sb->list, sb->size); + } + + flock(sb->fd, LOCK_SH); + fstat(sb->fd, &st); + flock(sb->fd, LOCK_UN); + sb->size = st.st_size; + if (sb->size > 0) { + sb->list = mmap(NULL, sb->size, PROT_READ | PROT_WRITE, MAP_SHARED, sb->fd, 0); + if (sb->list == MAP_FAILED) { + perror("stringbucket mmap"); + return 0; + } + } else { + /* Don't map anything for now. */ + sb->list = NULL; + } + + return 1; +} + +struct stringbucket * stringbucket_open(const char *filename) { struct stringbucket *obj = malloc(sizeof(struct stringbucket)); + obj->list = NULL; + obj->size = 0; if (obj == NULL) { perror("stringbucket allocate"); - return NULL; + goto stringbucket_open__malloc_fail; } obj->fd = open(filename, O_RDWR | O_APPEND | O_CREAT, 0600); - flock(obj->fd, LOCK_SH); - fstat(obj->fd, &st); - flock(obj->fd, LOCK_UN); - obj->size = st.st_size; - obj->list = mmap(NULL, obj->size, PROT_READ | PROT_WRITE, MAP_SHARED, obj->fd, 0); - if (obj->list == NULL) { - perror("stringbucket mmap"); - close(obj->fd); - free(obj); - return 0; + if (obj->fd == -1) { + perror("stringbucket open"); + goto stringbucket_open__open_fail; + } + + if (stringbucket_remap(obj) == 0) { + goto stringbucket_open__mmap_fail; } return obj; + +stringbucket_open__mmap_fail: + close(obj->fd); +stringbucket_open__open_fail: + free(obj); +stringbucket_open__malloc_fail: + return NULL; } void stringbucket_close(struct stringbucket *sb) { - munmap(sb->list, sb->size); + if (sb == NULL) + return; + + if (sb->list != NULL) + munmap(sb->list, sb->size); + close(sb->fd); free(sb); } int stringbucket_find(struct stringbucket *sb, const char *string) { + if (sb->list == NULL) + return -1; + char * end = sb->list + sb->size; int string_len = strlen(string); @@ -78,11 +117,32 @@ int stringbucket_find(struct stringbucket *sb, const char *string) { int stringbucket_add(struct stringbucket *sb, const char *string) { if (stringbucket_find(sb, string) != -1) return 0; + int str_len = strlen(string); + int len; + flock(sb->fd, LOCK_EX); - write(sb->fd, string, strlen(string)); - write(sb->fd, "\n", 1); + len = write(sb->fd, string, str_len); + if (len < 0) + perror("stringbucket add"); + if (len < str_len) + goto stringbucket_add__fail; + len = write(sb->fd, "\n", 1); + if (len < 0) + perror("stringbucket add"); + if (len == 0) + goto stringbucket_add__fail; flock(sb->fd, LOCK_UN); + + /* remap the data to include added content */ + if (stringbucket_remap(sb) == 0) + return 0; + return 1; + +stringbucket_add__fail: + ftruncate(sb->fd, sb->size); + flock(sb->fd, LOCK_UN); + return 0; } int stringbucket_delete(struct stringbucket *sb, const char *string) { @@ -91,9 +151,13 @@ int stringbucket_delete(struct stringbucket *sb, const char *string) { /* We doin' it DOS style! */ sb->list[pos] = 0; + return 1; } void stringbucket_iterate(struct stringbucket *sb, void (*iter)(char *, void *), void *stuff) { + if (sb->list == NULL) + return; + char string[STRINGBUCKET_STRINGSIZE + 1]; char * ptr = sb->list; char * end = sb->list + sb->size;