pgpool2.git / summary / log / commit / refs

commit    d2695092b106c37367ba44d8565c364efce9addf
Author:   Tatsuo Ishii <ishii at sraoss.co.jp>
Date:     Wed Feb 03 08:11:42 2010 +0000

    Emit statement log when error or notice message comes from backend when
    SimpleQuery or Parse executed.
    This is usefull because PostgreSQL does not log particular statement
    if the error was detected *before* raw parser get executed.
    This typlically happens when encoding error was found.


pool.h | 3 +- pool_process_query.c | 54 +++++++++++++++++++++++--------- pool_proto_modules.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 127 insertions(+), 18 deletions(-) diff --git a/pool.h b/pool.h index 9a01674d3..cd8566278 100644 --- a/pool.h +++ b/pool.h @@ -693,7 +693,8 @@ extern void check_stop_request(void); extern void reset_variables(void); extern void reset_connection(void); extern void per_node_statement_log(POOL_CONNECTION_POOL *backend, int node_id, char *query); -extern POOL_STATUS pool_extract_error_message(POOL_CONNECTION *backend, int major, bool unread, char **message); +extern void per_node_error_log(POOL_CONNECTION_POOL *backend, int node_id, char *query, char *prefix, bool unread); +extern int pool_extract_error_message(bool read_kind, POOL_CONNECTION *backend, int major, bool unread, char **message); extern POOL_STATUS do_command(POOL_CONNECTION *frontend, POOL_CONNECTION *backend, char *query, int protoMajor, int pid, int key, int no_ready_for_query); extern POOL_STATUS do_query(POOL_CONNECTION *backend, char *query, POOL_SELECT_RESULT **result, int major); diff --git a/pool_process_query.c b/pool_process_query.c index 7a00d869e..c3ac68d4a 100644 --- a/pool_process_query.c +++ b/pool_process_query.c @@ -3594,7 +3594,7 @@ POOL_STATUS read_kind_from_backend(POOL_CONNECTION *frontend, POOL_CONNECTION_PO snprintf(buf, sizeof(buf), " %d[%c: ", i, kind_list[i]); string_append_char(msg, buf); - if (pool_extract_error_message(CONNECTION(backend, i), MAJOR(backend), true, &m) == POOL_CONTINUE) + if (pool_extract_error_message(false, CONNECTION(backend, i), MAJOR(backend), true, &m) == POOL_CONTINUE) { string_append_char(msg, m); string_append_char(msg, "]"); @@ -4333,16 +4333,21 @@ static int detect_error(POOL_CONNECTION *backend, char *error_code, int major, c } /* - * pool_error_message: Extract human readble message from ERROR/NOTICE - * reponse packet and return it. Packet kind should have already been - * read, and it should be either 'E' or 'N'. The returned string is - * placed in static buffer. Message larger than the buffer will be - * silently truncated. Be warned that next call to this function will - * break the buffer. If unread is true, the packet will be returned - * to the stream. + * pool_extract_error_message: Extract human readable message from + * ERROR/NOTICE reponse packet and return it. If read_kind is true, + * kind will be read in this function. If read_kind is false, kind + * should have been already read and it should be either 'E' or + * 'N'.The returned string is placed in static buffer. Message larger + * than the buffer will be silently truncated. Be warned that next + * call to this function will break the buffer. If unread is true, + * the packet will be returned to the stream. + * + * Return values are: 0: not error or notice message 1: succeeded to + * extract error message -1: error) */ -POOL_STATUS pool_extract_error_message(POOL_CONNECTION *backend, int major, bool unread, char **message) +int pool_extract_error_message(bool read_kind, POOL_CONNECTION *backend, int major, bool unread, char **message) { + char kind; int readlen = 0, len; static char buf[8192]; /* unread buffer */ static char message_buf[8192]; /* mesasge buffer */ @@ -4350,13 +4355,32 @@ POOL_STATUS pool_extract_error_message(POOL_CONNECTION *backend, int major, bool p = buf; + if (read_kind) + { + len = sizeof(kind); + + if (pool_read(backend, &kind, len) < 0) + return -1; + + readlen += len; + memcpy(p, &kind, len); + p += len; + + if (kind != 'E' && kind != 'N') + { + if (pool_unread(backend, buf, readlen) != 0) + return -1; + return 0; + } + } + /* read actual message */ if (major == PROTO_MAJOR_V3) { char *e; if (pool_read(backend, &len, sizeof(len)) < 0) - return POOL_END; + return -1; readlen += sizeof(len); memcpy(p, &len, sizeof(len)); p += sizeof(len); @@ -4366,7 +4390,7 @@ POOL_STATUS pool_extract_error_message(POOL_CONNECTION *backend, int major, bool if (!str) { pool_error("pool_extract_error_message: malloc failed"); - return POOL_END; + return -1; } pool_read(backend, str, len); @@ -4376,7 +4400,7 @@ POOL_STATUS pool_extract_error_message(POOL_CONNECTION *backend, int major, bool { pool_error("pool_extract_error_message: not enough buffer space"); free(str); - return POOL_END; + return -1; } memcpy(p, str, len); @@ -4410,7 +4434,7 @@ POOL_STATUS pool_extract_error_message(POOL_CONNECTION *backend, int major, bool if (readlen >= sizeof(buf)) { pool_error("pool_extract_error_message: not enough buffer space"); - return POOL_END; + return -1; } memcpy(p, str, len); @@ -4422,11 +4446,11 @@ POOL_STATUS pool_extract_error_message(POOL_CONNECTION *backend, int major, bool { /* Put the message to read buffer */ if (pool_unread(backend, buf, readlen) != 0) - return POOL_END; + return -1; } *message = message_buf; - return POOL_CONTINUE; + return 1; } /* diff --git a/pool_proto_modules.c b/pool_proto_modules.c index 2a647d492..aa8176518 100644 --- a/pool_proto_modules.c +++ b/pool_proto_modules.c @@ -599,6 +599,16 @@ POOL_STATUS NotificationResponse(POOL_CONNECTION *frontend, free_parser(); return POOL_END; } + + /* + * Check if some error detected. If so, emit + * log. This is usefull when invalid encoding error + * occurs. In this case, PostgreSQL does not report + * what statement caused that error and make users + * confused. + */ + per_node_error_log(backend, i, string, "SimpleQuery: Error or notice message from backend: ", true); + } if (commit) { @@ -643,6 +653,17 @@ POOL_STATUS NotificationResponse(POOL_CONNECTION *frontend, string = POOL_ERROR_QUERY; len = strlen(string) + 1; } + else + { + /* + * Check if some error detected. If so, emit + * log. This is usefull when invalid encoding error + * occurs. In this case, PostgreSQL does not report + * what statement caused that error and make users + * confused. + */ + per_node_error_log(backend, MASTER_NODE_ID, string, "SimpleQuery: Error or notice message from backend: ", true); + } } /* send query to other than master nodes */ @@ -679,6 +700,16 @@ POOL_STATUS NotificationResponse(POOL_CONNECTION *frontend, free_parser(); return POOL_END; } + + /* + * Check if some error detected. If so, emit + * log. This is usefull when invalid encoding error + * occurs. In this case, PostgreSQL does not report + 1* what statement caused that error and make users + * confused. + */ + per_node_error_log(backend, i, string, "SimpleQuery: Error or notice message from backend: ", true); + } /* send "COMMIT" or "ROLLBACK" to only master node if query is "COMMIT" or "ROLLBACK" */ @@ -706,6 +737,14 @@ POOL_STATUS NotificationResponse(POOL_CONNECTION *frontend, return POOL_END; } + /* + * Check if some error detected. If so, emit + * log. This is usefull when invalid encoding error + * occurs. In this case, PostgreSQL does not report + 1* what statement caused that error and make users + * confused. + */ + per_node_error_log(backend, MASTER_NODE_ID, string, "SimpleQuery: Error or notice message from backend: ", true); TSTATE(backend) = 'I'; } @@ -713,8 +752,6 @@ POOL_STATUS NotificationResponse(POOL_CONNECTION *frontend, } else { - free_parser(); - per_node_statement_log(backend, MASTER_NODE_ID, string); if (send_simplequery_message(MASTER(backend), len, string, MAJOR(backend)) != POOL_CONTINUE) @@ -730,8 +767,20 @@ POOL_STATUS NotificationResponse(POOL_CONNECTION *frontend, cancel_packet.key= MASTER_CONNECTION(backend)->key; cancel_request(&cancel_packet); + free_parser(); return POOL_END; } + + /* + * Check if some error detected. If so, emit + * log. This is usefull when invalid encoding error + * occurs. In this case, PostgreSQL does not report + 1* what statement caused that error and make users + * confused. + */ + per_node_error_log(backend, MASTER_NODE_ID, string, "SimpleQuery: Error or notice message from backend: ", true); + + free_parser(); } return POOL_CONTINUE; @@ -1227,6 +1276,16 @@ POOL_STATUS Parse(POOL_CONNECTION *frontend, free_parser(); return POOL_END; } + else + { + /* + * Check if other than dealock error detected. If so, emit + * log. This is usefull when invalid encoding error occurs. In + * this case, PostgreSQL does not report what statement caused + * that error and make users confused. + */ + per_node_error_log(backend, MASTER_NODE_ID, stmt, "Parse(): Error or notice message from backend: ", true); + } for (i=0;i<NUM_BACKENDS;i++) { @@ -1280,6 +1339,15 @@ POOL_STATUS Parse(POOL_CONNECTION *frontend, free_parser(); return POOL_END; } + + /* + * Check if error (or notice response) from backend is + * detected. If so, emit log. This is usefull when + * invalid encoding error occurs. In this case, PostgreSQL + * does not report what statement caused that error and + * make users confused. + */ + per_node_error_log(backend, i, stmt, "Parse(): Error or notice message from backend: ", true); } } @@ -2747,3 +2815,19 @@ void per_node_statement_log(POOL_CONNECTION_POOL *backend, int node_id, char *qu if (pool_config->log_per_node_statement) pool_log("DB node id: %d backend pid: %d statement: %s", node_id, ntohl(slot->pid), query); } + +/* + * Check kind and produce error message + * All data read in this function is returned to stream. + */ +void per_node_error_log(POOL_CONNECTION_POOL *backend, int node_id, char *query, char *prefix, bool unread) +{ + POOL_CONNECTION_POOL_SLOT *slot = backend->slots[node_id]; + char *message; + + if (pool_extract_error_message(true, CONNECTION(backend, node_id), MAJOR(backend), true, &message) > 0) + { + pool_log("%s: DB node id: %d backend pid: %d statement: %s message: %s", + prefix, node_id, ntohl(slot->pid), query, message); + } +} [parent: d873f66fe121]