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 == MAP_FAILED) {
- 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);
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) {
}
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;