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 */