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