pgpool2.git / summary / log / commit / refs
commit a536699c5ee4693c07c5779d0d4eeb76c9e826d2
Author: Tatsuo Ishii <ishii at sraoss.co.jp>
Date: Mon Jul 20 12:06:25 2009 +0000
Add pool_set_timeout() to control pool_check_fd()'s behavior.
This can be used for various places.
The first user is reset_backend() to fix following scenario:
Do COPY_FROM(for example pgbench -i)
Cancel pgbench
pgpool waits for response from backend while sending reset queries and
hang.
Backend waits for data coming from pgpool forever.
BTW, I don't think PostgreSQL's befaviro for COPY_FROM is quite
correct since the doc stats:"Receipt of any other non-copy message
type constitutes an error that will abort the copy-in state as
described above"
If my understanding correct, COPY_FROM should abort copy-in state
if it receives ABORT (issued in reset_backend).
It seems PostgreSQL is not implemented as stated in the doc...
pool.h | 1 +
pool_process_query.c | 38 +++++++++++++++++++++++++++++++++++---
2 files changed, 36 insertions(+), 3 deletions(-)
diff --git a/pool.h b/pool.h
index a286d4613..57b767e63 100644
--- a/pool.h
+++ b/pool.h
@@ -483,6 +483,7 @@ extern int connect_unix_domain_socket(int secondary_backend);
extern int connect_inet_domain_socket_by_port(char *host, int port);
extern int connect_unix_domain_socket_by_port(int port, char *socket_dir);
+extern void pool_set_timeout(int timeoutval);
extern int pool_check_fd(POOL_CONNECTION *cp);
extern void pool_send_frontend_exits(POOL_CONNECTION_POOL *backend);
diff --git a/pool_process_query.c b/pool_process_query.c
index d8ef5f12b..252e559df 100644
--- a/pool_process_query.c
+++ b/pool_process_query.c
@@ -74,6 +74,9 @@ static void free_select_result(POOL_SELECT_RESULT *result);
static bool is_internal_transaction_needed(Node *node);
static int compare(const void *p1, const void *p2);
+/* timeout sec for pool_check_fd */
+static int timeoutsec;
+
int in_load_balance; /* non 0 if in load balance mode */
int selected_slot; /* selected DB node */
int master_slave_dml; /* non 0 if master/slave mode is specified in config file */
@@ -873,9 +876,20 @@ int synchronize(POOL_CONNECTION *cp)
return pool_check_fd(cp);
}
+/*
+ * set timeout in seconds for pool_check_fd
+ * if timeoutval < 0, we assume no timeout(wait forever).
+ */
+void pool_set_timeout(int timeoutval)
+{
+ if (timeoutval > 0)
+ timeoutsec = timeoutval;
+ else
+ timeoutsec = 0;
+}
+
/*
* wait until read data is ready
- * if notimeout is non 0, wait forever.
*/
int pool_check_fd(POOL_CONNECTION *cp)
{
@@ -883,9 +897,20 @@ int pool_check_fd(POOL_CONNECTION *cp)
fd_set exceptmask;
int fd;
int fds;
+ struct timeval timeout;
+ struct timeval *timeoutp;
fd = cp->fd;
+ if (timeoutsec > 0)
+ {
+ timeout.tv_sec = timeoutsec;
+ timeout.tv_usec = 0;
+ timeoutp = &timeout;
+ }
+ else
+ timeoutp = NULL;
+
for (;;)
{
FD_ZERO(&readmask);
@@ -893,8 +918,7 @@ int pool_check_fd(POOL_CONNECTION *cp)
FD_SET(fd, &readmask);
FD_SET(fd, &exceptmask);
- /* no timeout */
- fds = select(fd+1, &readmask, NULL, &exceptmask, NULL);
+ fds = select(fd+1, &readmask, NULL, &exceptmask, timeoutp);
if (fds == -1)
{
if (errno == EAGAIN || errno == EINTR)
@@ -903,6 +927,8 @@ int pool_check_fd(POOL_CONNECTION *cp)
pool_error("pool_check_fd: select() failed. reason %s", strerror(errno));
break;
}
+ else if (fds == 0) /* timeout */
+ break;
if (FD_ISSET(fd, &exceptmask))
{
@@ -2067,9 +2093,15 @@ static int reset_backend(POOL_CONNECTION_POOL *backend, int qcnt)
/* if transaction state is idle, we don't need to issue ABORT */
if (TSTATE(backend) == 'I' && !strcmp("ABORT", query))
+ pool_set_timeout(10);
+
return 0;
+ {
+ pool_set_timeout(0);
+ }
if (SimpleQuery(NULL, backend, query) != POOL_CONTINUE)
+ pool_set_timeout(0);
return -1;
return 1;
[parent: cbb414b93a31]