Check for null clear argument
[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         return things;
37 }
38
39 void things_free(struct things *things) {
40         int i;
41
42         for (i = 0; i < things->len; i++) {
43                 free(things->arr[i].name);
44         }
45
46         free(things->arr);
47         free(things);
48 }
49
50 void things_add(struct things *things, time_t t, char *name) {
51         things->arr[things->len].t = t;
52         things->arr[things->len].len = strlen(name);
53         things->arr[things->len].name = malloc(things->arr[things->len].len + 1);
54         strcpy(things->arr[things->len].name, name);
55         things->len++;
56         if (things->len == things->size) {
57                 things->size *= 2;
58                 things->arr = realloc(things->arr, sizeof(struct thing) * things->size);
59         }
60 }
61
62 int thing_compare(const void *a, const void *b) {
63         struct thing * aa = (struct thing *) a;
64         struct thing * bb = (struct thing *) b;
65
66         if (aa->t == bb->t)
67                 return 0;
68         else if (aa->t > bb->t)
69                 return -1;
70         else
71                 return 1;
72 }
73
74 void things_sort(struct things *things) {
75         qsort(things->arr, things->len, sizeof(struct thing), thing_compare);
76 }
77
78 struct things * latest_things(const char *path, const char *file, int minlen) {
79         DIR* d;
80         struct dirent *f;
81         struct things * things = things_alloc();
82         char filename[512];
83         struct stat st;
84         int i;
85
86         d = opendir(path);
87         if (d == NULL) {
88                 fprintf(stderr, "Could not open %s: ", path);
89                 perror("");
90                 exit(1);
91         }
92         while ((f = readdir(d)) != NULL) {
93                 if (f->d_name[0] == '.') continue;
94                 if (minlen > 0 && strlen(f->d_name) < minlen) continue;
95                 if (file) {
96                         snprintf(filename, 512, "%s/%s/%s", path, f->d_name, file);
97                 } else {
98                         snprintf(filename, 512, "%s/%s", path, f->d_name);
99                 }
100                 stat(filename, &st);
101                 things_add(things, st.st_mtime, f->d_name);
102         }
103         closedir(d);
104
105         things_sort(things);
106
107         return things;
108 }
109
110 void latest_tags(yajl_gen g) {
111         int i;
112         struct things * things = latest_things(blergconf.hash_tags_path, NULL, 3);
113
114         unsigned int count = (things->len >= 50 ? 50 : things->len);
115         yajl_gen_array_open(g);
116         for (i = 0; i < count; i++) {
117                 yajl_gen_string(g, (unsigned char *)things->arr[i].name, things->arr[i].len);
118         }
119         yajl_gen_array_close(g);
120
121         things_free(things);
122 }
123
124 void latest_records(yajl_gen g) {
125         int i;
126         struct things * things = latest_things(blergconf.data_path, "meta", 0);
127
128         unsigned int count = (things->len >= 50 ? 50 : things->len);
129         yajl_gen_array_open(g);
130         for (i = 0; i < count; i++) {
131                 struct blerg * b = blerg_open(things->arr[i].name);
132                 if (b == NULL) {
133                         fprintf(stderr, "Could not open blerg for %s\n", things->arr[i].name);
134                         continue;
135                 }
136                 uint64_t record_count = blerg_get_record_count(b);
137                 if (record_count > 0)
138                         json_generate_one_record(g, things->arr[i].name, b, record_count - 1, 1);
139                 blerg_close(b);
140         }
141         yajl_gen_array_close(g);
142         things_free(things);
143 }
144
145 int main(int argc, char *argv[]) {
146         const unsigned char *buf;
147         unsigned int len;
148
149         if (!blerg_init())
150                 exit(1);
151
152         yajl_gen g = yajl_gen_alloc(&yajl_config, NULL);
153
154         yajl_gen_map_open(g);
155         yajl_gen_string(g, (unsigned char *)"tags", 4);
156
157         latest_tags(g);
158
159         yajl_gen_get_buf(g, &buf, &len);
160         fwrite(buf, len, 1, stdout);
161         yajl_gen_clear(g);
162
163         yajl_gen_string(g, (unsigned char *)"records", 7);
164
165         latest_records(g);
166
167         yajl_gen_map_close(g);
168         yajl_gen_get_buf(g, &buf, &len);
169         fwrite(buf, len, 1, stdout);
170
171         yajl_gen_free(g);
172 }