null+****@clear*****
null+****@clear*****
2010年 6月 9日 (水) 22:38:10 JST
Daijiro MORI 2010-06-09 13:38:10 +0000 (Wed, 09 Jun 2010) New Revision: 107eb494f486d73903ead54c350dbf36b4547c2e Log: return code and error info would be output in http mode. Modified files: src/groonga.c Modified: src/groonga.c (+112 -90) =================================================================== --- src/groonga.c 2010-06-09 04:41:37 +0000 (43ba045) +++ src/groonga.c 2010-06-09 13:38:10 +0000 (3570da5) @@ -358,53 +358,134 @@ parse_htpath(const char *p, const char *pe, (GRN_TEXT_LEN((obj)) == strlen((str)) && !memcmp(GRN_TEXT_VALUE((obj)), (str), strlen((str)))) static void -print_return_code_with_body(grn_ctx *ctx, grn_obj *buf, grn_content_type ct, - grn_obj *body) +print_return_code(grn_ctx *ctx, grn_rc rc, grn_obj *head, grn_obj *body, grn_obj *foot) { - switch (ct) { + switch (ctx->impl->output_type) { case GRN_CONTENT_JSON: - GRN_TEXT_PUTS(ctx, buf, "[["); - grn_text_itoa(ctx, buf, ctx->rc); + GRN_TEXT_PUTS(ctx, head, "[["); + grn_text_itoa(ctx, head, rc); { double dv; grn_timeval tv; grn_timeval_now(ctx, &tv); dv = ctx->impl->tv.tv_sec; dv += ctx->impl->tv.tv_usec / 1000000.0; - GRN_TEXT_PUTC(ctx, buf, ','); - grn_text_ftoa(ctx, buf, dv); + GRN_TEXT_PUTC(ctx, head, ','); + grn_text_ftoa(ctx, head, dv); dv = (tv.tv_sec - ctx->impl->tv.tv_sec); dv += (tv.tv_usec - ctx->impl->tv.tv_usec) / 1000000.0; - GRN_TEXT_PUTC(ctx, buf, ','); - grn_text_ftoa(ctx, buf, dv); + GRN_TEXT_PUTC(ctx, head, ','); + grn_text_ftoa(ctx, head, dv); } - if (ctx->rc != GRN_SUCCESS) { - GRN_TEXT_PUTS(ctx, buf, ","); - grn_text_esc(ctx, buf, ctx->errbuf, strlen(ctx->errbuf)); - } - if (body && GRN_TEXT_LEN(body)) { - GRN_TEXT_PUTS(ctx, buf, "],"); - GRN_TEXT_PUT(ctx, buf, GRN_TEXT_VALUE(body), GRN_TEXT_LEN(body)); - GRN_TEXT_PUTS(ctx, buf, "]"); - } else { - GRN_TEXT_PUTS(ctx, buf, "]]"); + if (rc != GRN_SUCCESS) { + GRN_TEXT_PUTC(ctx, head, ','); + grn_text_esc(ctx, head, ctx->errbuf, strlen(ctx->errbuf)); + if (ctx->errfunc && ctx->errfile) { + /* TODO: output backtrace */ + GRN_TEXT_PUTS(ctx, head, ",[["); + grn_text_esc(ctx, head, ctx->errfunc, strlen(ctx->errfunc)); + GRN_TEXT_PUTC(ctx, head, ','); + grn_text_esc(ctx, head, ctx->errfile, strlen(ctx->errfile)); + GRN_TEXT_PUTC(ctx, head, ','); + grn_text_itoa(ctx, head, ctx->errline); + GRN_TEXT_PUTS(ctx, head, "]]"); + } } + GRN_TEXT_PUTC(ctx, head, ']'); + if (GRN_TEXT_LEN(body)) { GRN_TEXT_PUTC(ctx, head, ','); } + GRN_TEXT_PUTC(ctx, foot, ']'); break; case GRN_CONTENT_TSV: case GRN_CONTENT_XML: - if (body) { - GRN_TEXT_PUT(ctx, buf, GRN_TEXT_VALUE(body), GRN_TEXT_LEN(body)); - } - break; case GRN_CONTENT_NONE: break; } } static void -print_return_code(grn_ctx *ctx, grn_obj *buf, grn_content_type ct) +h_output(grn_ctx *ctx, grn_rc expr_rc, grn_sock fd, + grn_obj *jsonp_func, grn_obj *body, const char *mime_type) { - print_return_code_with_body(ctx, buf, ct, NULL); + grn_obj head, foot, *outbuf = ctx->impl->outbuf; + GRN_TEXT_INIT(&head, 0); + GRN_TEXT_INIT(&foot, 0); + if (!expr_rc) { + if (GRN_TEXT_LEN(jsonp_func)) { + GRN_TEXT_PUT(ctx, &head, GRN_TEXT_VALUE(jsonp_func), GRN_TEXT_LEN(jsonp_func)); + GRN_TEXT_PUTC(ctx, &head, '('); + print_return_code(ctx, expr_rc, &head, outbuf, &foot); + GRN_TEXT_PUTS(ctx, &foot, ");"); + } else { + print_return_code(ctx, expr_rc, &head, outbuf, &foot); + } + GRN_TEXT_SETS(ctx, body, "HTTP/1.1 200 OK\r\n"); + GRN_TEXT_PUTS(ctx, body, "Connection: close\r\n"); + GRN_TEXT_PUTS(ctx, body, "Content-Type: "); + GRN_TEXT_PUTS(ctx, body, mime_type); + GRN_TEXT_PUTS(ctx, body, "\r\nContent-Length: "); + grn_text_lltoa(ctx, body, + GRN_TEXT_LEN(&head) + GRN_TEXT_LEN(outbuf) + GRN_TEXT_LEN(&foot)); + GRN_TEXT_PUTS(ctx, body, "\r\n\r\n"); + } else { + GRN_BULK_REWIND(outbuf); + print_return_code(ctx, expr_rc, &head, outbuf, &foot); + if (expr_rc == GRN_NO_SUCH_FILE_OR_DIRECTORY) { + GRN_TEXT_SETS(ctx, body, "HTTP/1.1 404 Not Found\r\n"); + } else { + GRN_TEXT_SETS(ctx, body, "HTTP/1.1 500 Internal Server Error\r\n"); + } + GRN_TEXT_PUTS(ctx, body, "Content-Type: application/json\r\n\r\n"); + } + { + ssize_t ret; +#ifdef WIN32 + WSABUF wsabufs[4]; + wsabufs[0].buf = GRN_TEXT_VALUE(body); + wsabufs[0].len = GRN_TEXT_LEN(body); + wsabufs[1].buf = GRN_TEXT_VALUE(&head); + wsabufs[1].len = GRN_TEXT_LEN(&head); + wsabufs[2].buf = GRN_TEXT_VALUE(outbuf); + wsabufs[2].len = GRN_TEXT_LEN(outbuf); + wsabufs[3].buf = GRN_TEXT_VALUE(&foot); + wsabufs[4].len = GRN_TEXT_LEN(&foot); + if (WSASend(fd, wsabufs, 4, &ret, 0, NULL, NULL) == SOCKET_ERROR) { + SERR("WSASend"); + } +#else /* WIN32 */ + struct iovec msg_iov[4]; + struct msghdr msg; + msg.msg_name = NULL; + msg.msg_namelen = 0; + msg.msg_iov = msg_iov; + msg.msg_iovlen = 4; + msg.msg_control = NULL; + msg.msg_controllen = 0; + msg.msg_flags = 0; + msg_iov[0].iov_base = GRN_TEXT_VALUE(body); + msg_iov[0].iov_len = GRN_TEXT_LEN(body); + msg_iov[1].iov_base = GRN_TEXT_VALUE(&head); + msg_iov[1].iov_len = GRN_TEXT_LEN(&head); + msg_iov[2].iov_base = GRN_TEXT_VALUE(outbuf); + msg_iov[2].iov_len = GRN_TEXT_LEN(outbuf); + msg_iov[3].iov_base = GRN_TEXT_VALUE(&foot); + msg_iov[3].iov_len = GRN_TEXT_LEN(&foot); + if ((ret = sendmsg(fd, &msg, MSG_NOSIGNAL)) == -1) { + SERR("sendmsg"); + } +#endif /* WIN32 */ + } + GRN_BULK_REWIND(body); + GRN_BULK_REWIND(outbuf); + GRN_OBJ_FIN(ctx, &foot); + GRN_OBJ_FIN(ctx, &head); + { + uint64_t et; + grn_timeval tv; + grn_timeval_now(ctx, &tv); + et = (tv.tv_sec - ctx->impl->tv.tv_sec) * GRN_TIME_USEC_PER_SEC + + (tv.tv_usec - ctx->impl->tv.tv_usec); + GRN_LOG(ctx, GRN_LOG_NONE, "%08x|<%012zu rc=%d", (intptr_t)ctx, et, ctx->rc); + } } static void @@ -442,12 +523,10 @@ do_htreq(grn_ctx *ctx, grn_msg *msg, grn_obj *body) } /* TODO: handle post body */ { + const char *mime_type = NULL; grn_rc expr_rc = GRN_SUCCESS; grn_obj jsonp_func; - const char *mime_type; - GRN_TEXT_INIT(&jsonp_func, 0); - if (*path != '/') { expr_rc = GRN_INVALID_ARGUMENT; } else { @@ -466,7 +545,8 @@ do_htreq(grn_ctx *ctx, grn_msg *msg, grn_obj *body) &key_end, &filename_end, &ot, &mime_type); if ((GRN_TEXT_LEN(&key) >= 2 && GRN_TEXT_VALUE(&key)[0] == 'd' && GRN_TEXT_VALUE(&key)[1] == '/') && - (expr = grn_ctx_get(ctx, GRN_TEXT_VALUE(&key) + 2, key_end - GRN_TEXT_VALUE(&key) - 2))) { + (expr = grn_ctx_get(ctx, GRN_TEXT_VALUE(&key) + 2, + key_end - GRN_TEXT_VALUE(&key) - 2))) { while (g < pathe) { GRN_BULK_REWIND(&key); g = grn_text_cgidec(ctx, &key, g, pathe, '='); @@ -487,6 +567,7 @@ do_htreq(grn_ctx *ctx, grn_msg *msg, grn_obj *body) grn_obj_reinit(ctx, val, GRN_DB_INT32, 0); GRN_INT32_SET(ctx, val, (int32_t)ot); } + ctx->impl->output_type = ot; grn_ctx_push(ctx, ctx->impl->outbuf); expr_rc = grn_expr_exec(ctx, expr, 1); val = grn_ctx_pop(ctx); @@ -498,6 +579,7 @@ do_htreq(grn_ctx *ctx, grn_msg *msg, grn_obj *body) GRN_TEXT_SET(ctx, val, GRN_TEXT_VALUE(&key), filename_end - GRN_TEXT_VALUE(&key)); } + ctx->impl->output_type = ot; grn_ctx_push(ctx, ctx->impl->outbuf); expr_rc = grn_expr_exec(ctx, expr, 1); val = grn_ctx_pop(ctx); @@ -505,68 +587,8 @@ do_htreq(grn_ctx *ctx, grn_msg *msg, grn_obj *body) } GRN_OBJ_FIN(ctx, &key); } - /* TODO: Content-Length */ - if (!expr_rc) { - GRN_TEXT_SETS(ctx, body, "HTTP/1.1 200 OK\r\n"); - GRN_TEXT_PUTS(ctx, body, "Connection: close\r\n"); - GRN_TEXT_PUTS(ctx, body, "Content-Type: "); - GRN_TEXT_PUTS(ctx, body, mime_type); - GRN_TEXT_PUTS(ctx, body, "\r\nContent-Length: "); - if (GRN_TEXT_LEN(&jsonp_func)) { - grn_text_lltoa(ctx, body, - GRN_TEXT_LEN(ctx->impl->outbuf) + GRN_TEXT_LEN(&jsonp_func) + 3); - GRN_TEXT_PUTS(ctx, body, "\r\n\r\n"); - GRN_TEXT_PUT(ctx, body, GRN_TEXT_VALUE(&jsonp_func), GRN_TEXT_LEN(&jsonp_func)); - GRN_TEXT_PUTC(ctx, body, '('); - GRN_TEXT_PUT(ctx, body, GRN_TEXT_VALUE(ctx->impl->outbuf), - GRN_TEXT_LEN(ctx->impl->outbuf)); - GRN_TEXT_PUTS(ctx, body, ");"); - } else { - grn_text_lltoa(ctx, body, GRN_TEXT_LEN(ctx->impl->outbuf)); - GRN_TEXT_PUTS(ctx, body, "\r\n\r\n"); - GRN_TEXT_PUT(ctx, body, GRN_TEXT_VALUE(ctx->impl->outbuf), - GRN_TEXT_LEN(ctx->impl->outbuf)); - } - } else { - if (expr_rc == GRN_NO_SUCH_FILE_OR_DIRECTORY) { - GRN_TEXT_SETS(ctx, body, "HTTP/1.1 404 Not Found\r\n"); - } else { - GRN_TEXT_SETS(ctx, body, "HTTP/1.1 500 Internal Server Error\r\n"); - } - GRN_TEXT_PUTS(ctx, body, "Content-Type: application/json\r\n\r\n"); - GRN_TEXT_PUTS(ctx, body, "[["); - grn_text_itoa(ctx, body, expr_rc); - GRN_TEXT_PUTS(ctx, body, ",0,0"); - if (ctx->errbuf && strlen(ctx->errbuf)) { - GRN_TEXT_PUTC(ctx, body, ','); - grn_text_esc(ctx, body, ctx->errbuf, strlen(ctx->errbuf)); - if (ctx->errfunc && ctx->errfile) { - /* TODO: output backtrace */ - GRN_TEXT_PUTS(ctx, body, ",[["); - grn_text_esc(ctx, body, ctx->errfunc, strlen(ctx->errfile)); - GRN_TEXT_PUTC(ctx, body, ','); - grn_text_esc(ctx, body, ctx->errfile, strlen(ctx->errfile)); - GRN_TEXT_PUTC(ctx, body, ','); - grn_text_itoa(ctx, body, ctx->errline); - GRN_TEXT_PUTS(ctx, body, "]]"); - } - } - GRN_TEXT_PUTS(ctx, body, "]]"); - } + h_output(ctx, expr_rc, fd, &jsonp_func, body, mime_type); GRN_OBJ_FIN(ctx, &jsonp_func); - if (send(fd, GRN_BULK_HEAD(body), GRN_BULK_VSIZE(body), MSG_NOSIGNAL) == -1) { - SERR("send"); - } - GRN_BULK_REWIND(body); - GRN_BULK_REWIND(ctx->impl->outbuf); - { - uint64_t et; - grn_timeval tv; - grn_timeval_now(ctx, &tv); - et = (tv.tv_sec - ctx->impl->tv.tv_sec) * GRN_TIME_USEC_PER_SEC - + (tv.tv_usec - ctx->impl->tv.tv_usec); - GRN_LOG(ctx, GRN_LOG_NONE, "%08x|<%012zu rc=%d", (intptr_t)ctx, et, ctx->rc); - } } } exit :