From 7a48489bbc0cfafdc2a55b0e479454f8d8c965ae Mon Sep 17 00:00:00 2001 From: Chip Black Date: Sun, 19 Dec 2010 00:19:26 -0600 Subject: [PATCH] Add tag listing functionality --- .gitignore | 5 +++ Makefile | 5 --- blergtool.c | 14 +++++++++ config.h | 3 +- tags.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++--- tags.h | 2 +- 6 files changed, 107 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index e1c975d..34b462f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,8 @@ *~ *.o +*.a +*.so blergtool +http_blerg +cgi_blerg +fcgi_blerg diff --git a/Makefile b/Makefile index c0050db..a116407 100644 --- a/Makefile +++ b/Makefile @@ -5,8 +5,6 @@ targets = blerg.a blergtool tag_test blerg_a_objects = database.o tags.o blergtool_objects = blergtool.o blerg.a -tag_test_objects = tag_test.o tags.o - all: $(targets) clean: @@ -18,8 +16,5 @@ blerg.a: $(blerg_a_objects) blergtool: $(blergtool_objects) gcc $^ -o $@ -tag_test: $(tag_test_objects) - gcc $^ -o $@ - %.o: %.c gcc $(CFLAGS) $(LIBS) -c $< -o $@ diff --git a/blergtool.c b/blergtool.c index a0148c0..d5aef50 100644 --- a/blergtool.c +++ b/blergtool.c @@ -1,6 +1,7 @@ #include #include #include "database.h" +#include "tags.h" void help() { printf("Usage: blergtool [record]\n"); @@ -50,6 +51,19 @@ int main(int argc, char *argv[]) { blerg_close(f); fwrite(data, 1, size, stdout); free(data); + } else if (strncmp(argv[1], "list", 4) == 0) { + char *tag = argv[2]; + uint64_t count = 50; + struct tag *list = tag_list(tag, 0, &count, -1); + if (list == NULL) { + printf("No entries"); + } else { + int i; + for (i = 0; i < count; i++) { + printf("%s %d\n", list[i].author, list[i].record); + } + free(list); + } } else { help(); } diff --git a/config.h b/config.h index 1b5e49d..726792e 100644 --- a/config.h +++ b/config.h @@ -2,6 +2,7 @@ #define _CONFIG_H #define DATA_PATH "data" -#define TAGS_PATH "tags" +#define HASH_TAGS_PATH "hash_tags" +#define AUTHOR_TAGS_PATH "author_tags" #endif //_CONFIG_H diff --git a/tags.c b/tags.c index 96e7378..4705b87 100644 --- a/tags.c +++ b/tags.c @@ -6,6 +6,7 @@ #include #include #include +#include #include "tags.h" #include "config.h" @@ -21,18 +22,19 @@ int tag_scan(const char *author, const char *data, int len, uint64_t record) { for (i = 0; i < len; i++) { tag_scan_start: - if (data[i] == '#') { + if (data[i] == '#' || data[i] == '@') { if (n_tags == MAX_TAGS) { fprintf(stderr, "Too many tags in message\n"); break; } + int begin = i; int start = ++i; while (i < len && TAG_CHAR(data[i]) && (i - start < MAX_TAG_LENGTH)) { i++; } if (start - i == 0) continue; - char *tag = calloc(1, MAX_TAG_LENGTH + 1); - memcpy(tag, &data[start], i - start); + char *tag = calloc(1, MAX_TAG_LENGTH + 2); + memcpy(tag, &data[begin], i - begin); for (j = 0; j < n_tags; j++) { if (!strncmp(tag, taglist[j], MAX_TAG_LENGTH)) { // We already have this tag. Start over. @@ -61,7 +63,18 @@ int tag_add(const char *author, const char *tag, uint64_t record) { strncpy(t.author, author, 32); t.record = record; - snprintf(filename, 512, "%s/%s", TAGS_PATH, tag); + switch(tag[0]) { + case '#': + snprintf(filename, 512, "%s/%s", HASH_TAGS_PATH, tag + 1); + break; + case '@': + snprintf(filename, 512, "%s/%s", AUTHOR_TAGS_PATH, tag + 1); + break; + default: + fprintf(stderr, "Invalid tag type: %s\n", tag); + return 0; + } + int tag_fd = open(filename, O_WRONLY | O_APPEND | O_CREAT, 0600); flock(tag_fd, LOCK_EX); if (tag_fd == -1) { @@ -79,5 +92,72 @@ int tag_add(const char *author, const char *tag, uint64_t record) { return 1; } -int tag_list(const char *tag, int start, int count) { +struct tag * tag_list(const char *tag, uint64_t offset, uint64_t *count, int direction) { + char filename[512]; + struct stat st; + struct tag *taglist; + struct tag *retlist; + uint64_t n_tag_records; + + switch(tag[0]) { + case '#': + snprintf(filename, 512, "%s/%s", HASH_TAGS_PATH, tag + 1); + break; + case '@': + snprintf(filename, 512, "%s/%s", AUTHOR_TAGS_PATH, tag + 1); + break; + default: + fprintf(stderr, "Invalid tag type: %s\n", tag); + return 0; + } + + int tag_fd = open(filename, O_RDONLY, 0600); + if (tag_fd == -1) { + perror("Could not open tag file"); + *count = 0; + return NULL; + } + + fstat(tag_fd, &st); + if (st.st_size == 0) { + close(tag_fd); + *count = 0; + return NULL; + } + n_tag_records = st.st_size / sizeof(struct tag); + if (*count > n_tag_records) + *count = n_tag_records; + if (offset > n_tag_records) { + fprintf(stderr, "Cannot access tag record beyond end\n"); + return NULL; + } + + taglist = (struct tag *) mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, tag_fd, 0); + if (taglist == MAP_FAILED) { + perror("Could not mmap tag file"); + goto tag_list_map_failed; + } + retlist = (struct tag *) malloc(sizeof(struct tag) * *count); + if (retlist == NULL) { + perror("Could not allocate memory for tag list"); + goto tag_list_malloc_failed; + } + switch(direction) { + case 1: + memcpy(retlist, taglist + offset, sizeof(struct tag) * *count); + break; + case -1: + memcpy(retlist, taglist + (n_tag_records - *count - offset), sizeof(struct tag) * *count); + break; + } + + munmap(taglist, st.st_size); + return retlist; + +tag_list_malloc_failed: + munmap(taglist, st.st_size); +tag_list_map_failed: + close(tag_fd); +tag_list_open_failed: + return NULL; } diff --git a/tags.h b/tags.h index 3247caa..df0cf98 100644 --- a/tags.h +++ b/tags.h @@ -10,6 +10,6 @@ struct tag { int tag_scan(const char *, const char *, int, uint64_t); int tag_add(const char *, const char *, uint64_t); -int tag_list(const char *, int, int); +struct tag * tag_list(const char *, uint64_t, uint64_t *, int); #endif //_TAGS_H -- 2.25.1