null+****@clear*****
null+****@clear*****
2012年 1月 25日 (水) 12:04:30 JST
Kouhei Sutou 2012-01-25 12:04:30 +0900 (Wed, 25 Jan 2012) New Revision: bca5b949328de759aae7769c764d50575b7557f9 Log: [suggest] pass unknown parameters to groonga. Modified files: src/suggest/groonga_suggest_httpd.c src/suggest/groonga_suggest_learner.c src/suggest/util.c src/suggest/util.h Modified: src/suggest/groonga_suggest_httpd.c (+26 -8) =================================================================== --- src/suggest/groonga_suggest_httpd.c 2012-01-25 10:48:19 +0900 (6346ae6) +++ src/suggest/groonga_suggest_httpd.c 2012-01-25 12:04:30 +0900 (118637d) @@ -68,6 +68,7 @@ typedef struct { grn_obj *db; void *zmq_sock; grn_obj cmd_buf; + grn_obj pass_through_parameters; pthread_t thd; uint32_t thread_id; struct event_base *base; @@ -96,10 +97,11 @@ static grn_obj *db; static uint32_t n_lines_per_log_file = 1000000; static int -suggest_result(struct evbuffer *res_buf, const char *types, const char *query, +suggest_result(grn_ctx *ctx, + struct evbuffer *res_buf, const char *types, const char *query, const char *target_name, int frequency_threshold, double conditional_probability_threshold, int limit, - grn_obj *cmd_buf, grn_ctx *ctx) + grn_obj *cmd_buf, grn_obj *pass_through_parameters) { if (target_name && types && query) { GRN_BULK_REWIND(cmd_buf); @@ -115,6 +117,12 @@ suggest_result(struct evbuffer *res_buf, const char *types, const char *query, grn_text_ftoa(ctx, cmd_buf, conditional_probability_threshold); GRN_TEXT_PUTS(ctx, cmd_buf, "&limit="); grn_text_itoa(ctx, cmd_buf, limit); + if (GRN_TEXT_LEN(pass_through_parameters) > 0) { + GRN_TEXT_PUTS(ctx, cmd_buf, "&"); + GRN_TEXT_PUT(ctx, cmd_buf, + GRN_TEXT_VALUE(pass_through_parameters), + GRN_TEXT_LEN(pass_through_parameters)); + } { char *res; int flags; @@ -142,9 +150,11 @@ log_send(struct evkeyvalq *output_headers, struct evbuffer *res_buf, const char *callback, *types, *query, *client_id, *target_name, *learn_target_name; - parse_keyval(get_args, &query, &types, &client_id, &target_name, + GRN_BULK_REWIND(&(thd->pass_through_parameters)); + parse_keyval(thd->ctx, get_args, &query, &types, &client_id, &target_name, &learn_target_name, &callback, &millisec, &frequency_threshold, - &conditional_probability_threshold, &limit); + &conditional_probability_threshold, &limit, + &(thd->pass_through_parameters)); /* send data to learn client */ if (thd->zmq_sock && millisec && client_id && query && learn_target_name) { @@ -218,18 +228,24 @@ log_send(struct evkeyvalq *output_headers, struct evbuffer *res_buf, content_length = strlen(callback); evbuffer_add(res_buf, callback, content_length); evbuffer_add(res_buf, "(", 1); - content_length += suggest_result(res_buf, types, query, target_name, + content_length += suggest_result(thd->ctx, + res_buf, types, query, target_name, frequency_threshold, conditional_probability_threshold, - limit, &(thd->cmd_buf), thd->ctx) + 3; + limit, + &(thd->cmd_buf), + &(thd->pass_through_parameters)) + 3; evbuffer_add(res_buf, ");", 2); } else { evhttp_add_header(output_headers, "Content-Type", "application/json; charset=UTF-8"); - content_length = suggest_result(res_buf, types, query, target_name, + content_length = suggest_result(thd->ctx, + res_buf, types, query, target_name, frequency_threshold, conditional_probability_threshold, - limit, &(thd->cmd_buf), thd->ctx); + limit, + &(thd->cmd_buf), + &(thd->pass_through_parameters)); } if (content_length >= 0) { char num_buf[16]; @@ -251,6 +267,7 @@ cleanup_httpd_thread(thd_data *thd) { zmq_close(thd->zmq_sock); } grn_obj_unlink(thd->ctx, &(thd->cmd_buf)); + grn_obj_unlink(thd->ctx, &(thd->pass_through_parameters)); if (thd->ctx) { grn_ctx_close(thd->ctx); } @@ -591,6 +608,7 @@ serve_threads(int nthreads, int port, const char *db_path, void *zmq_ctx, print_error("error in grn_db_open() on thread %d.", i); } else { GRN_TEXT_INIT(&(threads[i].cmd_buf), 0); + GRN_TEXT_INIT(&(threads[i].pass_through_parameters), 0); threads[i].log_base_path = log_base_path; threads[i].thread_id = i; evhttp_set_gencb(threads[i].httpd, generic_handler, &threads[i]); Modified: src/suggest/groonga_suggest_learner.c (+4 -2) =================================================================== --- src/suggest/groonga_suggest_learner.c 2012-01-25 10:48:19 +0900 (214b2f8) +++ src/suggest/groonga_suggest_learner.c 2012-01-25 12:04:30 +0900 (bf6a655) @@ -542,8 +542,10 @@ read_log_line(suggest_log_file **list) struct evkeyvalq get_args; *eol = '\0'; evhttp_parse_query(line_buf, &get_args); - parse_keyval(&get_args, &query, &types, &client_id, NULL, - &learn_target_name, NULL, &(t->millisec), NULL, NULL, NULL); + parse_keyval(NULL, + &get_args, &query, &types, &client_id, NULL, + &learn_target_name, NULL, &(t->millisec), NULL, NULL, NULL, + NULL); if (query && client_id && learn_target_name && t->millisec) { t->query = evhttp_decode_uri(query); t->submit = (types && !strcmp(types, "submit")); Modified: src/suggest/util.c (+89 -52) =================================================================== --- src/suggest/util.c 2012-01-25 10:48:19 +0900 (6852760) +++ src/suggest/util.c 2012-01-25 12:04:30 +0900 (793d55c) @@ -27,6 +27,7 @@ #include <fcntl.h> #include "util.h" +#include <evhttp.h> #define DEFAULT_FREQUENCY_THRESHOLD 100 #define DEFAULT_CONDITIONAL_PROBABILITY_THRESHOLD 0.2 @@ -95,7 +96,8 @@ atouint64_t(const char *s) } void -parse_keyval(struct evkeyvalq *get_args, +parse_keyval(grn_ctx *ctx, + struct evkeyvalq *get_args, const char **query, const char **types, const char **client_id, const char **target_name, const char **learn_target_name, @@ -103,7 +105,8 @@ parse_keyval(struct evkeyvalq *get_args, uint64_t *millisec, int *frequency_threshold, double *conditional_probability_threshold, - int *limit) + int *limit, + grn_obj *pass_through_parameters) { struct evkeyval *get; @@ -123,61 +126,95 @@ parse_keyval(struct evkeyvalq *get_args, if (limit) { *limit = -1; } TAILQ_FOREACH(get, get_args, next) { - switch(get->key[0]) { - case 'q': - if (query) { - *query = get->value; - } - break; - case 't': - /* TODO: check types */ - if (types) { - *types = get->value; - } - break; - case 'i': - if (client_id) { - *client_id = get->value; - } - break; - case 'c': - if (!strcmp(get->key, "callback") && callback) { - *callback = get->value; - } - break; - case 's': - if (millisec) { - *millisec = atouint64_t(get->value); - } - break; - case 'n': - /* TODO: check target_name */ - if (target_name) { - *target_name = get->value; - } - break; - case 'l': - if (learn_target_name) { - *learn_target_name = get->value; - } + grn_bool is_pass_through_parameter = GRN_FALSE; + size_t key_length; + + key_length = strlen(get->key); + switch (key_length) { + case 0: break; - case 'h': - if (frequency_threshold) { - *frequency_threshold = atoi(get->value); + case 1: + switch(get->key[0]) { + case 'q': + if (query) { + *query = get->value; + } + break; + case 't': + /* TODO: check types */ + if (types) { + *types = get->value; + } + break; + case 'i': + if (client_id) { + *client_id = get->value; + } + break; + case 's': + if (millisec) { + *millisec = atouint64_t(get->value); + } + break; + case 'n': + /* TODO: check target_name */ + if (target_name) { + *target_name = get->value; + } + break; + case 'l': + if (learn_target_name) { + *learn_target_name = get->value; + } + break; + case 'h': + if (frequency_threshold) { + *frequency_threshold = atoi(get->value); + } + break; + case 'p': + if (conditional_probability_threshold) { + *conditional_probability_threshold = strtod(get->value, NULL); + } + break; + case 'm': + if (limit) { + *limit = atoi(get->value); + } + break; + default: + is_pass_through_parameter = GRN_TRUE; + break; } break; - case 'p': - if (conditional_probability_threshold) { - *conditional_probability_threshold = strtod(get->value, NULL); + default: + switch (get->key[0]) { + case 'c': + if (!strcmp(get->key, "callback")) { + if (callback) { + *callback = get->value; + } + } else { + is_pass_through_parameter = GRN_TRUE; + } + break; + default: + is_pass_through_parameter = GRN_TRUE; } - break; - case 'm': - if (limit) { - *limit = atoi(get->value); + } + + if (is_pass_through_parameter && pass_through_parameters) { + char *encoded_key = NULL, *encoded_value = NULL; + encoded_key = evhttp_uriencode(get->key, -1, 1); + encoded_value = evhttp_uriencode(get->value, -1, 1); + if (GRN_TEXT_LEN(pass_through_parameters) > 0) { + GRN_TEXT_PUTS(ctx, pass_through_parameters, "&"); } - break; - default: - break; + GRN_TEXT_PUTS(ctx, pass_through_parameters, encoded_key); + GRN_TEXT_PUTS(ctx, pass_through_parameters, "="); + GRN_TEXT_PUTS(ctx, pass_through_parameters, encoded_value); + free(encoded_key); + free(encoded_value); } } } Modified: src/suggest/util.h (+6 -2) =================================================================== --- src/suggest/util.h 2012-01-25 10:48:19 +0900 (831c5b7) +++ src/suggest/util.h 2012-01-25 12:04:30 +0900 (a35dbe0) @@ -21,9 +21,12 @@ #include <event.h> #include <stdint.h> +#include <groonga.h> + int print_error(const char *format, ...); int daemonize(void); -void parse_keyval(struct evkeyvalq *get_args, +void parse_keyval(grn_ctx *ctx, + struct evkeyvalq *get_args, const char **query, const char **types, const char **client_id, const char **target_name, const char **learn_target_name, @@ -31,6 +34,7 @@ void parse_keyval(struct evkeyvalq *get_args, uint64_t *millisec, int *frequency_threshold, double *conditional_probability_threshold, - int *limit); + int *limit, + grn_obj *pass_through_parameters); #endif /* GRN_SUGGEST_UTIL_H */