Add blerglatest tool for figuring latest traffic
[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) {
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 (file) {
85                         snprintf(filename, 512, "%s/%s/%s", path, f->d_name, file);
86                 } else {
87                         snprintf(filename, 512, "%s/%s", path, f->d_name);
88                 }
89                 stat(filename, &st);
90                 things_add(things, st.st_mtime, f->d_name);
91         }
92         closedir(d);
93
94         things_sort(things);
95
96         return things;
97 }
98
99 void latest_tags(yajl_gen g) {
100         int i;
101         struct things * things = latest_things(HASH_TAGS_PATH, NULL);
102
103         unsigned int count = (things->len >= 50 ? 50 : things->len);
104         yajl_gen_array_open(g);
105         for (i = 0; i < count; i++) {
106                 yajl_gen_string(g, things->arr[i].name, things->arr[i].len);
107         }
108         yajl_gen_array_close(g);
109
110         things_free(things);
111 }
112
113 void latest_records(yajl_gen g) {
114         int i;
115         struct things * things = latest_things(DATA_PATH, "meta");
116
117         unsigned int count = (things->len >= 50 ? 50 : things->len);
118         yajl_gen_array_open(g);
119         for (i = 0; i < count; i++) {
120                 struct blerg * b = blerg_open(things->arr[i].name);
121                 if (b == NULL) {
122                         fprintf(stderr, "Could not open blerg for %s\n", things->arr[i].name);
123                         continue;
124                 }
125                 uint64_t record_count = blerg_get_record_count(b);
126                 if (record_count > 0)
127                         json_generate_one_record(g, things->arr[i].name, b, record_count - 1);
128                 blerg_close(b);
129         }
130         yajl_gen_array_close(g);
131         things_free(things);
132 }
133
134 int main(int argc, char *argv[]) {
135         const unsigned char *buf;
136         unsigned int len;
137
138         yajl_gen g = yajl_gen_alloc(&yajl_config, NULL);
139
140         yajl_gen_map_open(g);
141         yajl_gen_string(g, "tags", 4);
142
143         latest_tags(g);
144
145         yajl_gen_get_buf(g, &buf, &len);
146         fwrite(buf, len, 1, stdout);
147         yajl_gen_clear(g);
148
149         yajl_gen_string(g, "records", 7);
150
151         latest_records(g);
152
153         yajl_gen_map_close(g);
154         yajl_gen_get_buf(g, &buf, &len);
155         fwrite(buf, len, 1, stdout);
156
157         yajl_gen_free(g);
158 }