From 2fac96d01e0097bbd47f0c4fb2bd14e84fd5bdaf Mon Sep 17 00:00:00 2001 From: "simpl.it" <fbk.eugaia@gmail.com> Date: Sat, 16 Apr 2011 04:14:34 +0300 Subject: [PATCH 1/3] Add drizzle_return_error_code and drizzle_no_log_error_codes directives --- README | 16 +++++++ src/ngx_http_drizzle_module.c | 80 +++++++++++++++++++++++++++++++- src/ngx_http_drizzle_module.h | 3 ++ src/ngx_http_drizzle_processor.c | 56 ++++++++++++++++------ 4 files changed, 140 insertions(+), 15 deletions(-) diff --git a/README b/README index 8a4862b..48898c5 100644 --- a/README +++ b/README @@ -222,6 +222,22 @@ Directives servers: 1 peers: 1 + drizzle_return_error_code on|off + Returns the drizzle / mysql error code when an error occurs, rather + than 500 (internal server error). + + This can be useful for example if you are using ngx_lua to process the + returned data, and wish to handle specific error situations, such as + when there is a duplicate entry on INSERT queries (see example below). + + drizzle_no_log_error_codes <num> [<num> ...] + Do not log error information for the error codes listed + + e.g. + + drizzle_return_error_code on; + drizzle_no_log_error_codes 1062; # doesn't log duplicate entries + Output This module generates binary query results in a format that will be shared among the various nginx database diff --git a/src/ngx_http_drizzle_module.c b/src/ngx_http_drizzle_module.c index c6d469f..0b66955 100644 --- a/src/ngx_http_drizzle_module.c +++ b/src/ngx_http_drizzle_module.c @@ -30,7 +30,9 @@ static ngx_int_t ngx_http_drizzle_tid_variable(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); static char * ngx_http_drizzle_enable_status(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); - +static char * ngx_http_drizzle_error_codes(ngx_conf_t *cf, + ngx_command_t *cmd, void *conf); + static ngx_http_variable_t ngx_http_drizzle_variables[] = { @@ -136,6 +138,22 @@ static ngx_command_t ngx_http_drizzle_cmds[] = { 0, NULL }, + { ngx_string("drizzle_return_error_code"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF + |NGX_HTTP_LIF_CONF|NGX_CONF_FLAG, + ngx_conf_set_flag_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_drizzle_loc_conf_t, return_error_code), + NULL }, + + { ngx_string("drizzle_no_log_error_codes"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF + |NGX_HTTP_LIF_CONF|NGX_CONF_1MORE, + ngx_http_drizzle_error_codes, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_drizzle_loc_conf_t, no_log_error_codes), + NULL }, + ngx_null_command }; @@ -229,13 +247,15 @@ ngx_http_drizzle_create_loc_conf(ngx_conf_t *cf) /* set by ngx_pcalloc: * conf->dbname = NULL * conf->query = NULL + * conf->no_log_error_codes = NULL */ + conf->return_error_code = NGX_CONF_UNSET; conf->complex_target = NGX_CONF_UNSET_PTR; conf->buf_size = NGX_CONF_UNSET_SIZE; conf->tid_var_index = NGX_CONF_UNSET; - + return conf; } @@ -271,6 +291,11 @@ ngx_http_drizzle_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) conf->queries = prev->queries; } + ngx_conf_merge_value(conf->return_error_code, prev->return_error_code, 0); + + if (conf->no_log_error_codes == NULL) + conf->no_log_error_codes = prev->no_log_error_codes; + ngx_conf_merge_size_value(conf->buf_size, prev->buf_size, (size_t) ngx_pagesize); @@ -560,3 +585,54 @@ ngx_http_drizzle_enable_status(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_OK; } + +static char * +ngx_http_drizzle_error_codes(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + char *p = conf; + + ngx_array_t **ap; + ngx_str_t *value, *e; + ngx_int_t i, *c; + + ap = (ngx_array_t **) (p + cmd->offset); + if (*ap) { + return "is duplicate"; + } + + *ap = ngx_array_create (cf->pool, cf->args->nelts - 1, sizeof (ngx_int_t)); + if (*ap == NULL) + return NGX_CONF_ERROR; + + value = cf->args->elts; + value++; + + e = value + cf->args->nelts - 1; + + for ( ;value<e; value++) { + + c = ngx_array_push (*ap); + if (c == NULL) + return NGX_CONF_ERROR; + + *c = ngx_atoi (value->data, value->len); + if (*c == NGX_ERROR) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "\"%V\" is not a valid drizzle error code", value); + + return NGX_CONF_ERROR; + } + + if (*c < 0 || *c > 0xffff) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "\"%V\" is not a valid drizzle error code", value); + + return NGX_CONF_ERROR; + } + + /* TODO: further check that numbers are valid error codes? */ + } + + return NGX_CONF_OK; +} + diff --git a/src/ngx_http_drizzle_module.h b/src/ngx_http_drizzle_module.h index 3af2ce8..751b42b 100644 --- a/src/ngx_http_drizzle_module.h +++ b/src/ngx_http_drizzle_module.h @@ -55,6 +55,9 @@ typedef struct { ngx_array_t *user_types; /* of ngx_http_drizzle_var_type_t */ + ngx_flag_t return_error_code; + ngx_array_t *no_log_error_codes; + ngx_http_complex_value_t *complex_target; size_t buf_size; diff --git a/src/ngx_http_drizzle_processor.c b/src/ngx_http_drizzle_processor.c index 194de4d..2ad850d 100644 --- a/src/ngx_http_drizzle_processor.c +++ b/src/ngx_http_drizzle_processor.c @@ -158,6 +158,7 @@ ngx_http_upstream_drizzle_send_query(ngx_http_request_t *r, ngx_connection_t *c, ngx_http_upstream_drizzle_peer_data_t *dp, drizzle_con_st *dc) { + ngx_http_drizzle_loc_conf_t *dlcf; ngx_http_upstream_t *u = r->upstream; drizzle_return_t ret; ngx_int_t rc; @@ -165,7 +166,9 @@ ngx_http_upstream_drizzle_send_query(ngx_http_request_t *r, size_t query_len; ngx_flag_t has_set_names = 0; ngx_flag_t enable_charset = 0; - + ngx_flag_t log_error; + ngx_int_t error_code, *codep, *codepe; + dd("enable charset: %d", (int) dp->enable_charset); if (dp->enable_charset && ! dp->has_set_names) { @@ -202,16 +205,37 @@ ngx_http_upstream_drizzle_send_query(ngx_http_request_t *r, } if (ret != DRIZZLE_RETURN_OK) { + + error_code = drizzle_error_code(dc->drizzle); + + dlcf = ngx_http_get_module_loc_conf (r, ngx_http_drizzle_module); + + log_error = 1; + + if (dlcf->no_log_error_codes) { + codep = dlcf->no_log_error_codes->elts; + codepe = codep + dlcf->no_log_error_codes->nelts; + + for ( ; codep < codepe; codep++) { + if (*codep == error_code) { + log_error = 0; + break; + } + } + } #if 1 if (ret == DRIZZLE_RETURN_ERROR_CODE) { - if (drizzle_error_code(dc->drizzle) == MYSQL_ER_NO_SUCH_TABLE) { - dd("XXX no such talbe"); - - ngx_log_error(NGX_LOG_NOTICE, c->log, 0, - "failed to send query: %d (%d): %s", - (int) ret, drizzle_error_code(dc->drizzle), - drizzle_error(dc->drizzle)); - + if (error_code == MYSQL_ER_NO_SUCH_TABLE) { + dd("XXX no such table"); + + if (log_error) { + + ngx_log_error(NGX_LOG_NOTICE, c->log, 0, + "failed to send query: %d (%ui): %s", + (int) ret, error_code, + drizzle_error(dc->drizzle)); + } + if (dp->enable_charset && ! dp->has_set_names) { c->log->action = "sending query to drizzle upstream"; dp->has_set_names = 1; @@ -226,11 +250,17 @@ ngx_http_upstream_drizzle_send_query(ngx_http_request_t *r, } #endif - ngx_log_error(NGX_LOG_ERR, c->log, 0, - "failed to send query: %d (%d): %s", - (int) ret, drizzle_error_code(dc->drizzle), - drizzle_error(dc->drizzle)); + if (log_error) { + ngx_log_error(NGX_LOG_ERR, c->log, 0, + "failed to send query: %d (%ui): %s", + (int) ret, error_code, + drizzle_error(dc->drizzle)); + } + + if (dlcf->return_error_code) + return error_code; + return NGX_HTTP_INTERNAL_SERVER_ERROR; } From 7fbaef10fea2fe26b488755dee1cf4cdcb85131d Mon Sep 17 00:00:00 2001 From: "simpl.it" <fbk.eugaia@gmail.com> Date: Sat, 16 Apr 2011 04:23:47 +0300 Subject: [PATCH 2/3] update conf logging of error in ngx_http_drizzle_error_codes() --- src/ngx_http_drizzle_module.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/ngx_http_drizzle_module.c b/src/ngx_http_drizzle_module.c index 0b66955..fc46505 100644 --- a/src/ngx_http_drizzle_module.c +++ b/src/ngx_http_drizzle_module.c @@ -618,14 +618,14 @@ ngx_http_drizzle_error_codes(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) *c = ngx_atoi (value->data, value->len); if (*c == NGX_ERROR) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "\"%V\" is not a valid drizzle error code", value); + "\"%V\" is not a valid drizzle error code (it must be an integer)", value); return NGX_CONF_ERROR; } - if (*c < 0 || *c > 0xffff) { + if (*c <= 0 || *c > 0xffff) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "\"%V\" is not a valid drizzle error code", value); + "\"%V\" is not a valid drizzle error code (it must be an integer between 1 and 65536)", value); return NGX_CONF_ERROR; } From eb90e78f332710111e9939940bdd33dc0bc51602 Mon Sep 17 00:00:00 2001 From: "simpl.it" <fbk.eugaia@gmail.com> Date: Sat, 16 Apr 2011 04:26:49 +0300 Subject: [PATCH 3/3] update conf logging of error in ngx_http_drizzle_error_codes() --- src/ngx_http_drizzle_module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ngx_http_drizzle_module.c b/src/ngx_http_drizzle_module.c index fc46505..58e96c1 100644 --- a/src/ngx_http_drizzle_module.c +++ b/src/ngx_http_drizzle_module.c @@ -618,7 +618,7 @@ ngx_http_drizzle_error_codes(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) *c = ngx_atoi (value->data, value->len); if (*c == NGX_ERROR) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "\"%V\" is not a valid drizzle error code (it must be an integer)", value); + "\"%V\" is not a valid drizzle error code (it must be an integer between 1 and 65536)", value); return NGX_CONF_ERROR; }