pgpool2.git / summary / log / commit / refs
commit 320523979d33e05d733a63d43d402c5dea5b6ac2
Author: Tatsuo Ishii <ishii at sraoss.co.jp>
Date: Wed Nov 12 13:42:23 2008 +0000
Fix do_command in case of notice message sent right after Complete
command response. See threads in pgpool-general:
Subject: Re: [Pgpool-general] Pgpool-II - replication problems
From: "nir osovsky" <nosovsky1@gmail.com>
for more details.
pool_process_query.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 75 insertions(+), 3 deletions(-)
diff --git a/pool_process_query.c b/pool_process_query.c
index 0fd151a91..4841b75d9 100644
--- a/pool_process_query.c
+++ b/pool_process_query.c
@@ -376,6 +376,11 @@ POOL_STATUS pool_process_query(POOL_CONNECTION *frontend,
(*InRecovery && pool_config->client_idle_limit_in_recovery > 0)) && fds == 0)
{
frontend_idle_count++;
+
+ pool_debug("idle count:%d InRecovery:%d client_idle_limit:%d client_idle_limit_in_recovery:%d",
+ frontend_idle_count, pool_config->client_idle_limit,
+ pool_config->client_idle_limit_in_recovery);
+
if (*InRecovery == 0 && (frontend_idle_count > pool_config->client_idle_limit))
{
pool_log("pool_process_query: child connection forced to terminate due to client_idle_limit(%d) reached", pool_config->client_idle_limit);
@@ -4578,7 +4583,7 @@ void pool_send_readyforquery(POOL_CONNECTION *frontend)
}
/*
- * sends q query in sync manner.
+ * sends a query in sync manner.
* this function sends a query and wait for CommandComplete/ReadyForQuery.
* if an error occured, it returns with POOL_ERROR.
* this function does NOT handle SELECT/SHOW queries.
@@ -4610,6 +4615,67 @@ static POOL_STATUS do_command(POOL_CONNECTION *backend, char *query, int protoMa
if (deadlock_detected < 0)
return POOL_END;
+ /*
+ * Continue to read packets until we get ReadForQuery (Z).
+ * Until that we may recieve one of:
+ *
+ * N: Notice response
+ * E: Error response
+ * C: Comand complete
+ *
+ * XXX: we ignore Notice and Error here. Even notice/error
+ * messages are not sent to the frontend. May be it's ok since the
+ * error was caused by our internal use of SQL command (otherwise users
+ * will be confused).
+ */
+ for(;;)
+ {
+ status = pool_read(backend, &kind, sizeof(kind));
+ if (status < 0)
+ {
+ pool_error("do_command: error while reading message kind");
+ return POOL_END;
+ }
+
+ pool_debug("do_command: kind: %c", kind);
+
+ if (kind == 'Z') /* Ready for Query? */
+ break; /* get out the loop without reading message lenghth */
+
+ if (protoMajor == PROTO_MAJOR_V3)
+ {
+ if (pool_read(backend, &len, sizeof(len)) < 0)
+ {
+ pool_error("do_command: error while reading message length");
+ return POOL_END;
+ }
+ len = ntohl(len) - 4;
+ string = pool_read2(backend, len);
+ if (string == NULL)
+ {
+ pool_error("do_command: error while reading rest of message");
+ return POOL_END;
+ }
+ }
+ else
+ {
+ string = pool_read_string(backend, &len, 0);
+ if (string == NULL)
+ {
+ pool_error("do_command: error while reading rest of message");
+ return POOL_END;
+ }
+ }
+ }
+
+/*
+ * until 2008/11/12 we believed that we never had packets other than
+ * 'Z' after receiving 'C'. However a counter example was presented by
+ * a poor customer. So we replaced the whole thing with codes
+ * above. In a side effect we were be able to get ride of nasty
+ * "goto". Congratulations.
+ */
+#ifdef NOT_USED
/*
* Expecting CompleteCommand
*/
@@ -4664,15 +4730,21 @@ retry_read_packet:
pool_error("do_command: backend returns %c while expecting ReadyForQuery", kind);
return POOL_END;
}
+#endif
if (no_ready_for_query)
return POOL_CONTINUE;
if (protoMajor == PROTO_MAJOR_V3)
{
+ /* read packet lenghth for ready for query */
if (pool_read(backend, &len, sizeof(len)) < 0)
+ {
+ pool_error("do_command: error while reading message length");
return POOL_END;
+ }
+ /* read transaction state */
status = pool_read(backend, &kind, sizeof(kind));
if (status < 0)
{
@@ -4681,7 +4753,7 @@ retry_read_packet:
}
/* set transaction state */
- pool_debug("ReadyForQuery: transaction state: %c", kind);
+ pool_debug("do_command: transaction state: %c", kind);
backend->tstate = kind;
}
@@ -4765,7 +4837,7 @@ static POOL_STATUS do_error_execute_command(POOL_CONNECTION_POOL *backend, int n
status = pool_read(CONNECTION(backend, node_id), &kind, sizeof(kind));
if (status < 0)
{
- pool_error("do_command: error while reading message kind");
+ pool_error("do_error_execute_command: error while reading message kind");
return POOL_END;
}
[parent: 842e8093fcef]