Limit latest tags to only those three characters or longer
[blerg.git] / tools / blerglatest.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <sys/types.h>
5 #include <sys/stat.h>
6 #include <unistd.h>
7 #include <dirent.h>
8 #include <yajl/yajl_gen.h>
9 #include "database.h"
10 #include "json.h"
11 #include "config.h"
12
13 yajl_gen_config yajl_config = {0, 0};
14
15 struct thing {
16         time_t t;
17         char *name;
18         int len;
19 };
20
21 struct things {
22         struct thing *arr;
23         unsigned int len;
24         unsigned int size;
25 };
26
27 struct things * things_alloc() {
28         struct things *things = malloc(sizeof(struct things));
29         things->len = 0;
30         things->size = 65536;
31         things->arr = malloc(sizeof(struct thing) * things->size);
32 }
33
34 void things_free(struct things *things) {
35         int i;
36
37         for (i = 0; i < things->len; i++) {
38                 free(things->arr[i].name);
39         }
40
41         free(things->arr);
42         free(things);
43 }
44
45 void things_add(struct things *things, time_t t, char *name) {
46         things->arr[things->len].t = t;
47         things->arr[things->len].len = strlen(name);
48         things->arr[things->len].name = malloc(things->arr[things->len].len + 1);
49         strcpy(things->arr[things->len].name, name);
50         things->len++;
51         if (things->len == things->size) {
52                 things->size *= 2;
53                 things->arr = realloc(things->arr, sizeof(struct thing) * things->size);
54         }
55 }
56
57 int thing_compare(const void *a, const void *b) {
58         struct thing * aa = (struct thing *) a;
59         struct thing * bb = (struct thing *) b;
60
61         if (aa->t == bb->t)
62                 return 0;
63         else if (aa->t > bb->t)
64                 return -1;
65         else
66                 return 1;
67 }
68
69 void things_sort(struct things *things) {
70         qsort(things->arr, things->len, sizeof(struct thing), thing_compare);
71 }
72
73 struct things * latest_things(const char *path, const char *file, int minlen) {
74         DIR* d;
75         struct dirent *f;
76         struct things * things = things_alloc();
77         char filename[512];
78         struct stat st;
79         int i;
80
81         d = opendir(path);
82         while (f = readdir(d)) {
83                 if (f->d_name[0] == '.') continue;
84                 if (minlen > 0 && strlen(f->d_name) < minlen) continue;
85                 if (file) {
86                         snprintf(filename, 512, "%s/%s/%s", path, f->d_name, file);
87                 } else {
88                         snprintf(filename, 512, "%s/%s", path, f->d_name);
89                 }
90                 stat(filename, &st);
91                 things_add(things, st.st_mtime, f->d_name);
92         }
93         closedir(d);
94
95         things_sort(things);
96
97         return things;
98 }
99
100 void latest_tags(yajl_gen g) {
101         int i;
102         struct things * things = latest_things(HASH_TAGS_PATH, NULL, 3);
103
104         unsigned int count = (things->len >= 50 ? 50 : things->len);
105         yajl_gen_array_open(g);
106         for (i = 0; i < count; i++) {
107                 yajl_gen_string(g, things->arr[i].name, things->arr[i].len);
108         }
109         yajl_gen_array_close(g);
110
111         things_free(things);
112 }
113
114 void latest_records(yajl_gen g) {
115         int i;
116         struct things * things = latest_things(DATA_PATH, "meta", 0);
117
118         unsigned int count = (things->len >= 50 ? 50 : things->len);
119         yajl_gen_array_open(g);
120         for (i = 0; i < count; i++) {
121                 struct blerg * b = blerg_open(things->arr[i].name);
122                 if (b == NULL) {
123                         fprintf(stderr, "Could not open blerg for %s\n", things->arr[i].name);
124                         continue;
125                 }
126                 uint64_t record_count = blerg_get_record_count(b);
127                 if (record_count > 0)
128                         json_generate_one_record(g, things->arr[i].name, b, record_count - 1, 1);
129                 blerg_close(b);
130         }
131         yajl_gen_array_close(g);
132         things_free(things);
133 }
134
135 int main(int argc, char *argv[]) {
136         const unsigned char *buf;
137         unsigned int len;
138
139         yajl_gen g = yajl_gen_alloc(&yajl_config, NULL);
140
141         yajl_gen_map_open(g);
142         yajl_gen_string(g, "tags", 4);
143
144         latest_tags(g);
145
146         yajl_gen_get_buf(g, &buf, &len);
147         fwrite(buf, len, 1, stdout);
148         yajl_gen_clear(g);
149
150         yajl_gen_string(g, "records", 7);
151
152         latest_records(g);
153
154         yajl_gen_map_close(g);
155         yajl_gen_get_buf(g, &buf, &len);
156         fwrite(buf, len, 1, stdout);
157
158         yajl_gen_free(g);
159 }