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