pgpool2.git / summary / log / commit / refs

commit    78921f3bcbab6174af964e34cdcb371ecb73d71d
Author:   Tatsuo Ishii <ishii at sraoss.co.jp>
Date:     Wed Dec 16 07:19:15 2009 +0000

    Enhance "kind mismatch" message. If kind is ERROR or NOTICE, print the
    ERROR/NOTICE message to help users to find what's going on.
    For this pupose, add new function pool_extract_error_message() into
    pool_process_query.c.


pool.h | 1 + pool_process_query.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 121 insertions(+), 2 deletions(-) diff --git a/pool.h b/pool.h index 8e93b7640..d499835c2 100644 --- a/pool.h +++ b/pool.h @@ -668,6 +668,7 @@ extern void check_stop_request(void); void free_select_result(POOL_SELECT_RESULT *result); void reset_variables(void); void per_node_statement_log(POOL_CONNECTION_POOL *backend, int node_id, char *query); +POOL_STATUS pool_extract_error_message(POOL_CONNECTION *backend, int major, bool unread, char **message); /* pool_relcache.c */ POOL_RELCACHE *pool_create_relcache(int cachesize, char *sql, diff --git a/pool_process_query.c b/pool_process_query.c index ba94818bb..df0d387df 100644 --- a/pool_process_query.c +++ b/pool_process_query.c @@ -3321,8 +3321,29 @@ POOL_STATUS read_kind_from_backend(POOL_CONNECTION *frontend, POOL_CONNECTION_PO if (kind_list[i]) { - snprintf(buf, sizeof(buf), " %d[%c]", i, kind_list[i]); - string_append_char(msg, buf); + + if (kind_list[i] == 'E' || kind_list[i] == 'N') + { + char *m; + + 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) + { + string_append_char(msg, m); + string_append_char(msg, "]"); + } + else + { + string_append_char(msg, "unknown message]"); + } + } + else + { + snprintf(buf, sizeof(buf), " %d[%c]", i, kind_list[i]); + string_append_char(msg, buf); + } } } @@ -4016,6 +4037,103 @@ static int detect_error(POOL_CONNECTION *backend, char *error_code, int major, c return is_error; } +/* + * 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_STATUS pool_extract_error_message(POOL_CONNECTION *backend, int major, bool unread, char **message) +{ + int readlen = 0, len; + static char buf[8192]; /* unread buffer */ + static char message_buf[8192]; /* mesasge buffer */ + char *p, *str; + + p = buf; + + /* read actual message */ + if (major == PROTO_MAJOR_V3) + { + char *e; + + if (pool_read(backend, &len, sizeof(len)) < 0) + return POOL_END; + readlen += sizeof(len); + memcpy(p, &len, sizeof(len)); + p += sizeof(len); + + len = ntohl(len) - 4; + str = malloc(len); + if (!str) + { + pool_error("pool_extract_error_message: malloc failed"); + return POOL_END; + } + + pool_read(backend, str, len); + readlen += len; + + if (readlen >= sizeof(buf)) + { + pool_error("pool_extract_error_message: not enough buffer space"); + free(str); + return POOL_END; + } + + memcpy(p, str, len); + + /* + * Checks error code which is formatted 'Mxxxxxx' + * (xxxxxx is error message). + */ + e = str; + while (*e) + { + if (*e == 'M') + { + e++; + len = Max(sizeof(message_buf)-1, strlen(e)); + memcpy(message_buf, e, len); + message_buf[sizeof(message_buf)] = '\0'; + break; + } + else + e = e + strlen(e) + 1; + } + free(str); + } + else + { + str = pool_read_string(backend, &len, 0); + len = Max(sizeof(message_buf)-1, len); + readlen += len; + + if (readlen >= sizeof(buf)) + { + pool_error("pool_extract_error_message: not enough buffer space"); + return POOL_END; + } + + memcpy(p, str, len); + memcpy(message_buf, str, len); + message_buf[sizeof(message_buf)] = '\0'; + } + + if (unread) + { + /* Put the message to read buffer */ + if (pool_unread(backend, buf, readlen) != 0) + return POOL_END; + } + + *message = message_buf; + return POOL_CONTINUE; +} + /* * read message length and rest of the packet then discard it */ [parent: f6f643a8e21b]