| 1 | #include <sys/types.h> |
|---|
| 2 | #include <sys/time.h> |
|---|
| 3 | #include <stdlib.h> |
|---|
| 4 | #include <err.h> |
|---|
| 5 | |
|---|
| 6 | #include <sys/queue.h> |
|---|
| 7 | #ifndef TAILQ_FOREACH |
|---|
| 8 | #define TAILQ_FOREACH(var, head, field) \ |
|---|
| 9 | for ((var) = ((head)->tqh_first); \ |
|---|
| 10 | (var); \ |
|---|
| 11 | (var) = ((var)->field.tqe_next)) |
|---|
| 12 | #endif /* LIST_FOREACH */ |
|---|
| 13 | #include <event.h> |
|---|
| 14 | #include <evhttp.h> |
|---|
| 15 | |
|---|
| 16 | #include <senna/senna.h> |
|---|
| 17 | |
|---|
| 18 | #include <stdio.h> |
|---|
| 19 | #include <string.h> |
|---|
| 20 | |
|---|
| 21 | typedef enum { |
|---|
| 22 | send_rc_success = 0, |
|---|
| 23 | send_memory_exhausted, |
|---|
| 24 | send_invalid_argument |
|---|
| 25 | } send_rc; |
|---|
| 26 | |
|---|
| 27 | #define PORT 8000 /* port number listened */ |
|---|
| 28 | #define BUFSIZE 8192 |
|---|
| 29 | |
|---|
| 30 | sen_sym *tags; |
|---|
| 31 | |
|---|
| 32 | void |
|---|
| 33 | generic_handler(struct evhttp_request *req, void *arg) |
|---|
| 34 | { |
|---|
| 35 | const char *prefix; |
|---|
| 36 | struct evbuffer *buf; |
|---|
| 37 | if (!(buf = evbuffer_new())) { |
|---|
| 38 | err(1, "failed to create response buffer"); |
|---|
| 39 | } |
|---|
| 40 | |
|---|
| 41 | /* get parameter */ |
|---|
| 42 | prefix = evhttp_decode_uri(evhttp_request_uri(req)) + 1; |
|---|
| 43 | |
|---|
| 44 | /* return tags */ |
|---|
| 45 | { |
|---|
| 46 | char tag[BUFSIZE]; |
|---|
| 47 | sen_set *s; |
|---|
| 48 | sen_id *tid; |
|---|
| 49 | sen_set_cursor *c; |
|---|
| 50 | if (!(s = sen_sym_prefix_search(tags, prefix))) { |
|---|
| 51 | /* no entry found */ |
|---|
| 52 | evbuffer_add(buf, "0\n", 2); |
|---|
| 53 | evhttp_send_reply(req, HTTP_OK, "OK", buf); |
|---|
| 54 | return; |
|---|
| 55 | /* err(1, "failed to sen_sym_prefix_search"); */ |
|---|
| 56 | } |
|---|
| 57 | if (!(c = sen_set_cursor_open(s))) { |
|---|
| 58 | err(1, "failed to sen_set_cursor_open"); |
|---|
| 59 | } |
|---|
| 60 | { |
|---|
| 61 | unsigned int nent; |
|---|
| 62 | sen_set_info(s, NULL, NULL, &nent); |
|---|
| 63 | evbuffer_add_printf(buf, "%u\n", nent); |
|---|
| 64 | } |
|---|
| 65 | while (sen_set_cursor_next(c, (void **)&tid, NULL)) { |
|---|
| 66 | int tag_len = sen_sym_key(tags, *tid, tag, BUFSIZE); |
|---|
| 67 | evbuffer_add(buf, tag, tag_len - 1); |
|---|
| 68 | evbuffer_add(buf, "\n", 1); |
|---|
| 69 | } |
|---|
| 70 | sen_set_cursor_close(c); |
|---|
| 71 | sen_set_close(s); |
|---|
| 72 | } |
|---|
| 73 | evhttp_send_reply(req, HTTP_OK, "OK", buf); |
|---|
| 74 | } |
|---|
| 75 | |
|---|
| 76 | int |
|---|
| 77 | main(int argc, char **argv) |
|---|
| 78 | { |
|---|
| 79 | struct evhttp *httpd; |
|---|
| 80 | |
|---|
| 81 | if (argc < 2) { |
|---|
| 82 | puts("usage: suggested tag-dic"); |
|---|
| 83 | return 1; |
|---|
| 84 | } |
|---|
| 85 | |
|---|
| 86 | sen_init(); |
|---|
| 87 | if (!(tags = sen_sym_open(argv[1]))) { |
|---|
| 88 | SEN_LOG(sen_log_alert, "sym open error!"); |
|---|
| 89 | return 2; |
|---|
| 90 | } |
|---|
| 91 | event_init(); |
|---|
| 92 | if (httpd = evhttp_start("0.0.0.0", PORT)) { |
|---|
| 93 | evhttp_set_gencb(httpd, generic_handler, NULL); |
|---|
| 94 | |
|---|
| 95 | event_dispatch(); |
|---|
| 96 | |
|---|
| 97 | evhttp_free(httpd); |
|---|
| 98 | } else { |
|---|
| 99 | puts("cannot bind"); |
|---|
| 100 | } |
|---|
| 101 | sen_sym_close(tags); |
|---|
| 102 | |
|---|
| 103 | sen_fin(); |
|---|
| 104 | return 0; |
|---|
| 105 | } |
|---|