Fix bug with query cache.
authorTatsuo Ishii <ishii@sraoss.co.jp>
Tue, 31 Mar 2020 07:58:01 +0000 (16:58 +0900)
committerTatsuo Ishii <ishii@sraoss.co.jp>
Tue, 31 Mar 2020 07:58:01 +0000 (16:58 +0900)
If an execute message is issued right after Sync message and query
cache hits, Pgpool-II hangs in inject_cached_message() because there's
no data to be read from backend. Fix is, change the code block which
checks the data availability in backend to the beginning of the loop
from the end of the loop. Also teach is_cache_empty() to call
pool_is_suspend_reading_from_frontend() so that if we suspend reading
from frontend. If so, return that cache is empty even if there's data
in frontend cache to receive a ready for query message from backend.

src/protocol/pool_process_query.c
src/query_cache/pool_memqcache.c

index 4498dce06dd95237bcad0d8d01b2eda32ab8139f..78a1a191adb10d35033eac028aed3aa402a6041b 100644 (file)
@@ -3,7 +3,7 @@
  * pgpool: a language independent connection pool server for PostgreSQL
  * written by Tatsuo Ishii
  *
- * Copyright (c) 2003-2019     PgPool Global Development Group
+ * Copyright (c) 2003-2020     PgPool Global Development Group
  *
  * Permission to use, copy, modify, and distribute this software and
  * its documentation for any purpose and without fee is hereby
@@ -3017,16 +3017,19 @@ is_backend_cache_empty(POOL_CONNECTION_POOL * backend)
 static bool
 is_cache_empty(POOL_CONNECTION * frontend, POOL_CONNECTION_POOL * backend)
 {
-       /*
-        * If SSL is enabled, we need to check SSL internal buffer is empty or not
-        * first.
-        */
-       if (pool_ssl_pending(frontend))
-               return false;
-
-       if (!pool_read_buffer_is_empty(frontend))
-               return false;
+       /* Are we suspending reading from frontend? */
+       if (!pool_is_suspend_reading_from_frontend())
+       {
+               /*
+                * If SSL is enabled, we need to check SSL internal buffer is empty or not
+                * first.
+                */
+               if (pool_ssl_pending(frontend))
+                       return false;
 
+               if (!pool_read_buffer_is_empty(frontend))
+                       return false;
+       }
        return is_backend_cache_empty(backend);
 }
 
index ef84cdc03c1f34e7e5674641195ef7b061ab44cf..c8dae7576b2e3e07d2d3d4c5f4d3bac580712262 100644 (file)
@@ -3,7 +3,7 @@
  * pgpool: a language independent connection pool server for PostgreSQL
  * written by Tatsuo Ishii
  *
- * Copyright (c) 2003-2019     PgPool Global Development Group
+ * Copyright (c) 2003-2020     PgPool Global Development Group
  *
  * Permission to use, copy, modify, and distribute this software and
  * its documentation for any purpose and without fee is hereby
@@ -4262,6 +4262,20 @@ inject_cached_message(POOL_CONNECTION * backend, char *qcache, int qcachelen)
         */
        for (;;)
        {
+               /* check if there's any pending data */
+               if (!pool_ssl_pending(backend) && pool_read_buffer_is_empty(backend))
+               {
+                       pool_set_timeout(timeout);
+                       if (pool_check_fd(backend) != 0)
+                       {
+                               ereport(DEBUG1,
+                                               (errmsg("inject_cached_message: select shows no pending data")));
+                               pool_set_timeout(-1);
+                               break;
+                       }
+                       pool_set_timeout(-1);
+               }
+
                pool_read(backend, &kind, 1);
                ereport(DEBUG1,
                                (errmsg("inject_cached_message: push message kind: '%c'", kind)));
@@ -4280,20 +4294,6 @@ inject_cached_message(POOL_CONNECTION * backend, char *qcache, int qcachelen)
                        buf = pool_read2(backend, ntohl(len) - sizeof(len));
                        pool_push(backend, buf, ntohl(len) - sizeof(len));
                }
-
-               /* check if there's any pending data */
-               if (!pool_ssl_pending(backend) && pool_read_buffer_is_empty(backend))
-               {
-                       pool_set_timeout(timeout);
-                       if (pool_check_fd(backend) != 0)
-                       {
-                               ereport(DEBUG1,
-                                               (errmsg("inject_cached_message: select shows no pending data")));
-                               pool_set_timeout(-1);
-                               break;
-                       }
-                       pool_set_timeout(-1);
-               }
        }
 
        /*