pgpool2.git / summary / log / commit / refs

commit    535ded49ffd58ffaefde28d8a8e46e6012532c46
Author:   Tatsuo Ishii <ishii at sraoss.co.jp>
Date:     Tue Dec 30 00:59:35 2008 +0000

    Fix bug with query cancel. It seems this has not been working since
    pgpool-II was born.
    
    To fix this, now we have each connection's pid and cancel key in the
    shared memory area. If a cancel packet is sent, the table is searched
    by the pid and the cancel key. If found, the actual cancel key is
    sent to each backend.


child.c | 42 +++++++++++++++++++++++++++++++++++------- main.c | 10 ++++++++-- pool.h | 5 +++-- pool_auth.c | 6 ++++-- pool_type.h | 4 +++- 5 files changed, 53 insertions(+), 14 deletions(-) diff --git a/child.c b/child.c index 425afe583..ee9eda42f 100644 --- a/child.c +++ b/child.c @@ -62,7 +62,7 @@ void child_exit(int code); static POOL_CONNECTION *do_accept(int unix_fd, int inet_fd, struct timeval *timeout); static StartupPacket *read_startup_packet(POOL_CONNECTION *cp); static POOL_CONNECTION_POOL *connect_backend(StartupPacket *sp, POOL_CONNECTION *frontend); -static void cancel_request(CancelPacket *sp, int secondary_backend); +static void cancel_request(CancelPacket *sp); static RETSIGTYPE die(int sig); static RETSIGTYPE close_idle_connection(int sig); static RETSIGTYPE wakeup_handler(int sig); @@ -226,9 +226,8 @@ void do_child(int unix_fd, int inet_fd) /* cancel request? */ if (sp->major == 1234 && sp->minor == 5678) { - cancel_request((CancelPacket *)sp->startup_packet, 0); - if (DUAL_MODE) - cancel_request((CancelPacket *)sp->startup_packet, 1); + cancel_request((CancelPacket *)sp->startup_packet); + pool_close(frontend); pool_free_startup_packet(sp); connection_count_down(); @@ -1078,16 +1077,33 @@ int send_startup_packet(POOL_CONNECTION_POOL_SLOT *cp) /* * process cancel request */ -static void cancel_request(CancelPacket *sp, int backend_id) +static void cancel_request(CancelPacket *sp) { int len; int fd; POOL_CONNECTION *con; int i; + ConnectionInfo *c = NULL; + CancelPacket cp; pool_debug("Cancel request received"); - for (i=0;i<NUM_BACKENDS;i++) + /* look for cancel key from shmem info */ + for (i=0;i<pool_config->num_init_children*pool_config->max_pool;i++) + { + c = &con_info[i]; + + if (c->pid == sp->pid && c->key == sp->key) + { + pool_debug("found pid:%d key:%d i:%d",c->pid, c->key,i); + c = &con_info[i/pool_config->max_pool * pool_config->max_pool]; + break; + } + } + if (i == pool_config->num_init_children*pool_config->max_pool) + return; /* invalid key */ + + for (i=0;i<NUM_BACKENDS;i++,c++) { if (!VALID_BACKEND(i)) continue; @@ -1110,10 +1126,22 @@ static void cancel_request(CancelPacket *sp, int backend_id) len = htonl(sizeof(len) + sizeof(CancelPacket)); pool_write(con, &len, sizeof(len)); - if (pool_write_and_flush(con, sp, sizeof(CancelPacket)) < 0) + cp.protoVersion = sp->protoVersion; + cp.pid = c->pid; + cp.key = c->key; + + pool_debug("pid:%d key: %d",cp.pid,cp.key); + + if (pool_write_and_flush(con, &cp, sizeof(CancelPacket)) < 0) pool_error("Could not send cancel request packet for backend %d", i); pool_close(con); + + /* + * this is needed to enure that the next DB node executes the + * query supposed to be canceled. + */ + sleep(1); } } diff --git a/main.c b/main.c index 4ef3e264b..72a195571 100644 --- a/main.c +++ b/main.c @@ -114,7 +114,14 @@ static int trigger_failover_command(int node, const char *command_line); static struct sockaddr_un un_addr; /* unix domain socket path */ static struct sockaddr_un pcp_un_addr; /* unix domain socket path for PCP */ -ProcessInfo *pids; /* child pid table */ +ProcessInfo *pids; /* shmem child pid table */ + +/* + * shmem connection info table + * this is a two dimention array. i.e.: + * con_info[pool_config->num_init_children][pool_config->max_pool] + */ +ConnectionInfo *con_info; static int unix_fd; /* unix domain socket fd */ static int inet_fd; /* inet domain socket fd */ @@ -168,7 +175,6 @@ int main(int argc, char **argv) int i; int pid; int size; - ConnectionInfo *con_info = NULL; int retrycnt; int sys_retrycnt; diff --git a/pool.h b/pool.h index a88b4139c..42705e04b 100644 --- a/pool.h +++ b/pool.h @@ -269,7 +269,7 @@ typedef struct { } POOL_CONNECTION_POOL_SLOT; typedef struct { - ConnectionInfo *info; + ConnectionInfo *info; /* connection info on shmem */ POOL_CONNECTION_POOL_SLOT *slots[MAX_NUM_BACKENDS]; } POOL_CONNECTION_POOL; @@ -411,7 +411,8 @@ extern volatile sig_atomic_t backend_timer_expired; /* flag for connection close extern long int weight_master; /* normalized weight of master (0-RAND_MAX range) */ extern int my_proc_id; /* process table id (!= UNIX's PID) */ extern POOL_SYSTEMDB_CONNECTION_POOL *system_db_info; /* systemdb */ -extern ProcessInfo *pids; /* process information table */ +extern ProcessInfo *pids; /* shmem process information table */ +extern ConnectionInfo *con_info; /* shmem connection info table */ extern int in_load_balance; /* non 0 if in load balance mode */ extern int selected_slot; /* selected DB node for load balance */ extern int master_slave_dml; /* non 0 if master/slave mode is specified in config file */ diff --git a/pool_auth.c b/pool_auth.c index 8224ce573..e4f2f6add 100644 --- a/pool_auth.c +++ b/pool_auth.c @@ -327,7 +327,8 @@ from pool_read_message_length and recheck the pg_hba.conf settings."); pool_error("pool_do_auth: failed to read pid in slot %d", i); return -1; } - CONNECTION_SLOT(cp, i)->pid = pid; + + CONNECTION_SLOT(cp, i)->pid = cp->info[i].pid = pid; /* read key */ if (pool_read(CONNECTION(cp, i), &key, sizeof(key)) < 0) @@ -335,7 +336,8 @@ from pool_read_message_length and recheck the pg_hba.conf settings."); pool_error("pool_do_auth: failed to read key in slot %d", i); return -1; } - CONNECTION_SLOT(cp, i)->key = key; + CONNECTION_SLOT(cp, i)->key = cp->info[i].key = key; + } } diff --git a/pool_type.h b/pool_type.h index 654d58e04..f281376b5 100644 --- a/pool_type.h +++ b/pool_type.h @@ -108,6 +108,8 @@ typedef struct { char user[SM_USER]; /* User name */ int major; /* protocol major version */ int minor; /* protocol minor version */ + int pid; /* backend process id */ + int key; /* cancel key */ int counter; /* used counter */ time_t create_time; /* connection creation time */ int load_balancing_node; /* load balancing node */ @@ -121,7 +123,7 @@ typedef struct { typedef struct { pid_t pid; /* OS's process id */ time_t start_time; /* fork() time */ - ConnectionInfo *connection_info; /* connection information */ + ConnectionInfo *connection_info; /* head of the connection info for this process */ } ProcessInfo; /* [parent: 2f03396e91d2]