1 #include <stdio.h>
2 #include <sys/stat.h>
3 #include <errno.h>
4 #define __USE_XOPEN_EXTENDED // for strdup() BS glibc now needs
5 #include <string.h>
6 #define __USE_GNU // qsort_r()
7 #include <stdlib.h>
8 #define _POSIX_SOURCE
9 #include <time.h>
10
11 #include <faup/faup.h>
12 #include <faup/snapshot.h>
13
rehash(const void * e,void * unused)14 static size_t rehash(const void *e, void *unused)
15 {
16 return hash_string(((faup_snapshot_value_count_t *)e)->value);
17 }
18
streq(const void * e,void * string)19 static bool streq(const void *e, void *string)
20 {
21 return strcmp(((faup_snapshot_value_count_t *)e)->value, string) == 0;
22 }
23
faup_snapshot_new(void)24 faup_snapshot_t *faup_snapshot_new(void)
25 {
26 faup_snapshot_t *snapshot;
27 snapshot = malloc(sizeof(*snapshot));
28 snapshot->length = 0;
29 snapshot->items = NULL;
30
31 return snapshot;
32 }
33
faup_snapshot_value_count_debug(faup_snapshot_value_count_t * vc)34 void faup_snapshot_value_count_debug(faup_snapshot_value_count_t *vc)
35 {
36 if (!vc) {
37 fprintf(stderr, "%s: No such value_count object\n", __FUNCTION__);
38 }
39 printf("**\t\tvalue:->%s<-\n", vc->value);
40 printf("**\t\tfirst time seen: %s", ctime(&vc->first_time_seen));
41 printf("**\t\tlast time seen: %s", ctime(&vc->last_time_seen));
42 printf("**\t\tcount:%ld\n", vc->count);
43 }
44
faup_snapshot_item_debug(faup_snapshot_item_t * item)45 void faup_snapshot_item_debug(faup_snapshot_item_t *item)
46 {
47 struct htable_iter iter;
48 faup_snapshot_value_count_t *vc;
49
50 if (!item) {
51 printf("** item empty, cannot debug!\n");
52 return;
53 }
54
55 printf("** \titem\n");
56 printf("** \tkey:%s\n", item->key);
57 printf("** \tlength:%ld\n", item->length);
58
59 if (item->length) {
60 vc = htable_first(&item->values, &iter);
61 while (vc) {
62 faup_snapshot_value_count_debug(vc);
63 vc = htable_next(&item->values, &iter);
64 }
65 }
66 }
67
faup_snapshot_debug(faup_snapshot_t * snapshot)68 void faup_snapshot_debug(faup_snapshot_t *snapshot)
69 {
70 size_t counter;
71
72 printf("** Snapshot debug:\n");
73 printf("** Name: %s\n", snapshot->name);
74 printf("** items length: %ld\n", snapshot->length);
75 for (counter = 0; counter < snapshot->length; counter++) {
76 faup_snapshot_item_debug(snapshot->items[counter]);
77 }
78 }
79
compare_items(const void * p1,const void * p2)80 static int compare_items(const void *p1, const void *p2)
81 {
82 faup_snapshot_item_t ** item1 = (faup_snapshot_item_t **)p1;
83 faup_snapshot_item_t ** item2 = (faup_snapshot_item_t **)p2;
84
85 printf("compare %s with %s\n", (*item1)->key, (*item2)->key);
86
87 return strcmp((*item1)->key, (*item2)->key);
88 }
89
compare_search(const void * key,const void * member)90 static int compare_search(const void *key, const void *member)
91 {
92 faup_snapshot_item_t *k = (faup_snapshot_item_t *)key;
93 faup_snapshot_item_t *m = (faup_snapshot_item_t *)member;
94
95
96 return strcmp(k->key, m->key);
97 }
98
compare_simple(const void * p1,const void * p2)99 static int compare_simple(const void *p1, const void *p2)
100 {
101 const faup_snapshot_item_t *item1 = (faup_snapshot_item_t *)p1;
102 const faup_snapshot_item_t *item2 = (faup_snapshot_item_t *)p2;
103
104 return strcmp(item1->key, item2->key);
105 }
106
107
faup_snapshot_value_count_new(void)108 faup_snapshot_value_count_t *faup_snapshot_value_count_new(void)
109 {
110 faup_snapshot_value_count_t *vc;
111
112 vc = malloc(sizeof(faup_snapshot_value_count_t));
113
114 vc->value = NULL;
115 vc->first_time_seen = 0;
116 vc->last_time_seen = 0;
117 vc->count = 0;
118
119 return vc;
120 }
121
faup_snapshot_value_count_copy(faup_snapshot_value_count_t * vc)122 faup_snapshot_value_count_t *faup_snapshot_value_count_copy(faup_snapshot_value_count_t *vc)
123 {
124 faup_snapshot_value_count_t *copy;
125
126 copy = faup_snapshot_value_count_new();
127 if (!copy) {
128 fprintf(stderr, "%s: could not copy object!\n", __FUNCTION__);
129 return NULL;
130 }
131 copy->value = strdup(vc->value);
132 copy->first_time_seen = vc->first_time_seen;
133 copy->last_time_seen = vc->last_time_seen;
134 copy->count = vc->count;
135
136 return copy;
137 }
138
faup_snapshot_value_count_free(faup_snapshot_value_count_t * vc)139 void faup_snapshot_value_count_free(faup_snapshot_value_count_t *vc)
140 {
141 free(vc->value);
142 free(vc);
143 }
144
faup_snapshot_item_new(char * key)145 faup_snapshot_item_t *faup_snapshot_item_new(char *key)
146 {
147 faup_snapshot_item_t *item;
148
149 item = malloc(sizeof(faup_snapshot_item_t));
150 if (!item) {
151 fprintf(stderr, "Cannot allocatate a snapshot_item item!\n");
152 return NULL;
153 }
154
155 item->length = 0;
156 item->key = strdup(key);
157 htable_init(&item->values, rehash, NULL);
158
159 return item;
160
161 }
162
faup_snapshot_item_copy(faup_snapshot_item_t * item)163 faup_snapshot_item_t *faup_snapshot_item_copy(faup_snapshot_item_t *item)
164 {
165 faup_snapshot_item_t *copy;
166 size_t counter;
167 struct htable_iter iter;
168 /* faup_snapshot_value_count_t *vc; */
169 /* faup_snapshot_value_count_t *vc_copy; */
170
171 copy = faup_snapshot_item_new(item->key);
172 memcpy(©->values, &item->values, sizeof(item->values));
173 /* vc = htable_first(©->values, &iter); */
174 /* while (vc) { */
175 /* /\* vc_copy = faup_snapshot_value_count_copy(vc); *\/ */
176 /* /\* faup_snapshot_value_count_append_object(item, vc_copy); *\/ */
177 /* printf("vc->value:%s\n", vc->value); */
178
179 /* vc = htable_next(©->values, &iter); */
180 /* } */
181 copy->length = item->length;
182
183 return copy;
184 }
185
faup_snapshot_value_count_get(faup_snapshot_item_t * item,char * value)186 faup_snapshot_value_count_t *faup_snapshot_value_count_get(faup_snapshot_item_t *item, char *value)
187 {
188 size_t counter;
189
190 if (!item) {
191 fprintf(stderr, "Item is empty!\n");
192 return NULL;
193 }
194
195 return (faup_snapshot_value_count_t *)htable_get(&item->values, hash_string(value), streq, value);
196 }
197
faup_snapshot_value_count_set_value(faup_snapshot_value_count_t * vc,char * value)198 int faup_snapshot_value_count_set_value(faup_snapshot_value_count_t *vc, char *value)
199 {
200 vc->value = strdup(value);
201 }
202
faup_snapshot_value_count_set_first_time_seen(faup_snapshot_value_count_t * vc,time_t first_time_seen)203 int faup_snapshot_value_count_set_first_time_seen(faup_snapshot_value_count_t *vc, time_t first_time_seen)
204 {
205 vc->first_time_seen = first_time_seen;
206 }
207
faup_snapshot_value_count_set_last_time_seen(faup_snapshot_value_count_t * vc,time_t last_time_seen)208 int faup_snapshot_value_count_set_last_time_seen(faup_snapshot_value_count_t *vc, time_t last_time_seen)
209 {
210 vc->last_time_seen = last_time_seen;
211 }
212
faup_snapshot_value_count_set_count(faup_snapshot_value_count_t * vc,size_t count)213 int faup_snapshot_value_count_set_count(faup_snapshot_value_count_t *vc, size_t count)
214 {
215 vc->count = count;
216 }
217
faup_snapshot_value_count_append(faup_snapshot_item_t * item,char * value)218 int faup_snapshot_value_count_append(faup_snapshot_item_t *item, char *value)
219 {
220 faup_snapshot_value_count_t *vc;
221
222 if (!item) {
223 fprintf(stderr, "Cannot append value '%s' to item\n", value);
224 return -1;
225 }
226
227 /* printf("Adding value '%s' to the item '%s'\n", item->key, value); */
228
229 vc = faup_snapshot_value_count_get(item, value);
230 if (!vc) {
231 vc = faup_snapshot_value_count_new();
232 vc->value = strdup(value);
233 vc->first_time_seen = vc->last_time_seen = time(NULL);
234 vc->count++;
235
236 htable_add(&item->values, hash_string(vc->value), vc);
237
238 item->length++;
239 } else {
240 vc->count++;
241 vc->last_time_seen = time(NULL);
242 }
243
244 return 0;
245 }
246
faup_snapshot_value_count_append_object(faup_snapshot_item_t * item,faup_snapshot_value_count_t * vc)247 int faup_snapshot_value_count_append_object(faup_snapshot_item_t *item, faup_snapshot_value_count_t *vc)
248 {
249 htable_add(&item->values, hash_string(vc->value), vc);
250
251 item->length++;
252 }
253
faup_snapshot_item_free(faup_snapshot_item_t * item)254 void faup_snapshot_item_free(faup_snapshot_item_t *item)
255 {
256 struct htable_iter iter;
257 faup_snapshot_value_count_t *vc;
258
259 vc = htable_first(&item->values, &iter);
260 while (vc) {
261 htable_del(&item->values, hash_string(vc->value), vc);
262 faup_snapshot_value_count_free(vc);
263
264 vc = htable_next(&item->values, &iter);
265 }
266
267 htable_clear(&item->values);
268
269 free(item->key);
270 free(item);
271 }
272
faup_snapshot_item_get(faup_snapshot_t * snapshot,char * item_name)273 faup_snapshot_item_t *faup_snapshot_item_get(faup_snapshot_t *snapshot, char *item_name)
274 {
275 faup_snapshot_item_t *res, key;
276 size_t counter;
277
278 if (!snapshot) {
279 fprintf(stderr, "Snapshot is NULL!\n");
280 return NULL;
281 }
282
283 for (counter = 0; counter < snapshot->length; counter++) {
284 if (!strcmp(snapshot->items[counter]->key, item_name)) {
285 return snapshot->items[counter];
286 }
287 }
288
289 return NULL;
290 }
291
faup_snapshot_item_append(faup_snapshot_t * snapshot,char * item_name)292 int faup_snapshot_item_append(faup_snapshot_t *snapshot, char *item_name)
293 {
294 faup_snapshot_item_t *item;
295 void *arg;
296
297 item = faup_snapshot_item_get(snapshot, item_name);
298 if (!item) {
299 snapshot->items = realloc(snapshot->items, sizeof(faup_snapshot_item_t *) * (snapshot->length + 1));
300 if (!snapshot->items) {
301 fprintf(stderr, "Cannot allocatate a snapshot_item!\n");
302 return -1;
303 }
304 snapshot->items[snapshot->length] = faup_snapshot_item_new(item_name);
305 snapshot->length++;
306
307 qsort(snapshot->items, snapshot->length, sizeof(faup_snapshot_item_t *), compare_simple);
308
309 }
310
311 return 0;
312 }
313
faup_snapshot_free(faup_snapshot_t * snapshot)314 void faup_snapshot_free(faup_snapshot_t *snapshot)
315 {
316 size_t counter;
317 if (!snapshot) {
318 return;
319 }
320
321 free(snapshot->name);
322 for (counter = 0; counter < snapshot->length; counter++) {
323 faup_snapshot_item_free(snapshot->items[counter]);
324 }
325 free(snapshot->items);
326
327 free(snapshot);
328 }
329
faup_snapshot_open(char * name)330 faup_snapshot_t *faup_snapshot_open(char *name)
331 {
332 faup_snapshot_t *snapshot;
333 int retval;
334
335 snapshot = faup_snapshot_new();
336 snapshot->name = strdup(name);
337
338 return snapshot;
339 }
340
341
faup_snapshot_close(faup_snapshot_t * snapshot)342 void faup_snapshot_close(faup_snapshot_t *snapshot)
343 {
344 faup_snapshot_free(snapshot);
345 }
346
faup_snapshot_append(faup_snapshot_t * snapshot,char * key,char * value)347 int faup_snapshot_append(faup_snapshot_t *snapshot, char *key, char *value)
348 {
349 faup_snapshot_item_t *item;
350
351 faup_snapshot_item_append(snapshot, key);
352 item = faup_snapshot_item_get(snapshot, key);
353 if (item) {
354 faup_snapshot_value_count_append(item, value);
355 } else {
356 fprintf(stderr, "Item does not exists. Cannot append value!\n");
357 }
358
359 return 0;
360 }
361
362 // FIXME: Remove this useless function
faup_snapshot_append_item(faup_snapshot_t * snapshot,char * item_name,faup_snapshot_item_t * item)363 int faup_snapshot_append_item(faup_snapshot_t *snapshot, char *item_name, faup_snapshot_item_t *item)
364 {
365 if (!snapshot) {
366 fprintf(stderr, "Cannot append item to an unexisting snapshot!\n");
367 return -1;
368 }
369
370 snapshot->items = realloc(snapshot->items, sizeof(faup_snapshot_item_t *) * (snapshot->length + 1));
371 if (!snapshot->items) {
372 fprintf(stderr, "Cannot allocatate a snapshot_item!\n");
373 return -1;
374 }
375
376 snapshot->items[snapshot->length] = faup_snapshot_item_copy(item);
377
378 snapshot->length++;
379
380 return 0;
381
382 }
383
faup_snapshot_output(faup_handler_t * fh,faup_snapshot_t * snapshot,FILE * fd)384 void faup_snapshot_output(faup_handler_t *fh, faup_snapshot_t *snapshot, FILE *fd)
385 {
386 size_t counter;
387 size_t values_count;
388 faup_snapshot_value_count_t *vc;
389 struct htable_iter iter;
390 char first_timebuf[200];
391 char last_timebuf[200];
392
393 if (!snapshot) {
394 fprintf(stderr, "Error reading snapshot. Stopping.\n");
395 return;
396 }
397
398 fprintf(fd, "{\n");
399 fprintf(fd,"\t\"snapshot name\": \"%s\",\n", snapshot->name);
400 if (!snapshot->length) {
401 fprintf(fd,"\t\"snapshot length\": %ld\n", snapshot->length);
402 } else {
403 fprintf(fd,"\t\"snapshot length\": %ld,\n", snapshot->length);
404 fprintf(fd,"\t\"items\":[");
405 for (counter = 0; counter < snapshot->length; counter++) {
406 faup_snapshot_item_t *item = snapshot->items[counter];
407 fprintf(fd,"\t\t{\n");
408 fprintf(fd,"\t\t\"key\": \"%s\",\n", item->key);
409 fprintf(fd,"\t\t\"length\": %ld,\n", item->length);
410 fprintf(fd,"\t\t\"values\": [\n");
411
412 if (item->length) {
413 values_count = 1;
414 vc = htable_first(&item->values, &iter);
415 while (vc) {
416 strftime(first_timebuf, sizeof(first_timebuf), "%Y-%m-%d %H:%M:%S %z", localtime(&vc->first_time_seen));
417 strftime(last_timebuf, sizeof(last_timebuf), "%Y-%m-%d %H:%M:%S %z", localtime(&vc->last_time_seen));
418 fprintf(fd,"\t\t\t{\"value\": \"%s\", \"count\": %ld, \"first seen\": \"%s\", \"last seen\": \"%s\"}", vc->value, vc->count, first_timebuf, last_timebuf);
419
420 if (values_count == item->length) {
421 fprintf(fd,"\n");
422 } else {
423 fprintf(fd,",\n");
424 }
425
426 values_count++;
427 vc = htable_next(&item->values, &iter);
428 }
429 }
430 fprintf(fd,"\t\t]\n\t}");
431 if (counter == snapshot->length - 1) {
432 fprintf(fd,"\n");
433 fprintf(fd, "\t]\n");
434 } else {
435 fprintf(fd,",\n");
436 }
437 }
438 }
439 fprintf(fd, "\n}\n");
440 }
441