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]