static POOL_CONNECTION_POOL_SLOT *create_cp(POOL_CONNECTION_POOL_SLOT *cp, int secondary_backend) { int fd; if (secondary_backend) { if (*pool_config.secondary_backend_host_name == '\0') fd = connect_unix_domain_socket(1); else fd = connect_inet_domain_socket(1); } else { if (*pool_config.current_backend_host_name == '\0') fd = connect_unix_domain_socket(0); else fd = connect_inet_domain_socket(0); } if (fd < 0) { /* fatal error, notice to parent and exit */ notice_backend_error(!secondary_backend); exit(1); } cp->con = pool_open(fd); cp->closetime = 0; return cp; }
/* * create connection pool */ static POOL_CONNECTION_POOL_SLOT *create_cp(POOL_CONNECTION_POOL_SLOT *cp, int slot) { BackendInfo *b = &pool_config->backend_desc->backend_info[slot]; int fd; if (*b->backend_hostname == '/') { fd = connect_unix_domain_socket(slot, TRUE); } else { fd = connect_inet_domain_socket(slot, TRUE); } if (fd < 0) { pool_error("connection to %s(%d) failed", b->backend_hostname, b->backend_port); return NULL; } cp->sp = NULL; cp->con = pool_open(fd); cp->closetime = 0; return cp; }
gpointer idle_thread_func(gpointer user_data) { PluginOption *option = ((ThreadData *)user_data)->option; int thread_index = ((ThreadData *)user_data)->index; int sock_type = SOCK_STREAM; if (sock_type_d) sock_type = SOCK_DGRAM; if (sock_type_s) sock_type = SOCK_STREAM; int fd; if (unix_socket_x) fd = connect_unix_domain_socket(sock_type, option->target); else fd = connect_ip_socket(sock_type, option->target, option->port, option->use_ipv6); if (fd<0) { ERROR("can not connect to %s:%s (%p)\n",option->target, option->port,g_thread_self()); } else { DEBUG("(%d) connected to server on socket %d (%p)\n",thread_index,fd,g_thread_self()); } g_mutex_lock(thread_lock); connect_finished++; if (connect_finished == active_thread_count + idle_thread_count) g_cond_broadcast(thread_connected); g_mutex_unlock(thread_lock); DEBUG("thread (%s,%p) created. wait for start ...\n",loggen_plugin_info.name,g_thread_self()); g_mutex_lock(thread_lock); while (!thread_run) { g_cond_wait(thread_start,thread_lock); } g_mutex_unlock(thread_lock); DEBUG("thread (%s,%p) started. (r=%d,c=%d)\n",loggen_plugin_info.name,g_thread_self(),option->rate, option->number_of_messages); while (fd > 0 && thread_run && active_thread_count>0) { g_usleep(10*1000); } g_mutex_lock(thread_lock); idle_thread_count--; g_mutex_unlock(thread_lock); close(fd); g_thread_exit(NULL); return NULL; }
/* * process cancel request */ void cancel_request(CancelPacket *sp) { int len; int fd; POOL_CONNECTION *con; int i,j,k; ConnectionInfo *c = NULL; CancelPacket cp; bool found = false; pool_debug("Cancel request received"); /* look for cancel key from shmem info */ for (i=0;i<pool_config->num_init_children;i++) { for (j=0;j<pool_config->max_pool;j++) { for (k=0;k<NUM_BACKENDS;k++) { c = pool_coninfo(i, j, k); pool_debug("con_info: address:%p database:%s user:%s pid:%d key:%d i:%d", c, c->database, c->user, ntohl(c->pid), ntohl(c->key),i); if (c->pid == sp->pid && c->key == sp->key) { pool_debug("found pid:%d key:%d i:%d",ntohl(c->pid), ntohl(c->key),i); c = pool_coninfo(i, j, 0); found = true; goto found; } } } } found: if (!found) { pool_error("cancel_request: invalid cancel key: pid:%d key:%d",ntohl(sp->pid), ntohl(sp->key)); return; /* invalid key */ } for (i=0;i<NUM_BACKENDS;i++,c++) { if (!VALID_BACKEND(i)) continue; if (*(BACKEND_INFO(i).backend_hostname) == '/') fd = connect_unix_domain_socket(i, TRUE); else fd = connect_inet_domain_socket(i, TRUE); if (fd < 0) { pool_error("Could not create socket for sending cancel request for backend %d", i); return; } con = pool_open(fd); if (con == NULL) return; len = htonl(sizeof(len) + sizeof(CancelPacket)); pool_write(con, &len, sizeof(len)); cp.protoVersion = sp->protoVersion; cp.pid = c->pid; cp.key = c->key; pool_log("cancel_request: canceling backend pid:%d key: %d", ntohl(cp.pid),ntohl(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 ensure that the next DB node executes the * query supposed to be canceled. */ sleep(1); } }
/* * check if we can connect to the backend * returns 0 for ok. otherwise returns backend id + 1 */ int health_check(void) { int fd; int sts; /* V2 startup packet */ typedef struct { int len; /* startup packet length */ StartupPacket_v2 sp; } MySp; MySp mysp; char kind; int i; if (*InRecovery) return 0; memset(&mysp, 0, sizeof(mysp)); mysp.len = htonl(296); mysp.sp.protoVersion = htonl(PROTO_MAJOR_V2 << 16); strcpy(mysp.sp.database, "template1"); strncpy(mysp.sp.user, pool_config->health_check_user, sizeof(mysp.sp.user) - 1); *mysp.sp.options = '\0'; *mysp.sp.unused = '\0'; *mysp.sp.tty = '\0'; for (i=0;i<pool_config->backend_desc->num_backends;i++) { pool_debug("health_check: %d th DB node status: %d", i, BACKEND_INFO(i).backend_status); if (BACKEND_INFO(i).backend_status == CON_UNUSED || BACKEND_INFO(i).backend_status == CON_DOWN) continue; if (*(BACKEND_INFO(i).backend_hostname) == '\0') fd = connect_unix_domain_socket(i); else fd = connect_inet_domain_socket(i); if (fd < 0) { pool_error("health check failed. %d th host %s at port %d is down", i, BACKEND_INFO(i).backend_hostname, BACKEND_INFO(i).backend_port); return i+1; } if (write(fd, &mysp, sizeof(mysp)) < 0) { pool_error("health check failed during write. host %s at port %d is down. reason: %s", BACKEND_INFO(i).backend_hostname, BACKEND_INFO(i).backend_port, strerror(errno)); close(fd); return i+1; } /* * Don't bother to be blocked by read(2). It will be * interrupted by ALRAM anyway. */ sts = read(fd, &kind, 1); if (sts == -1) { pool_error("health check failed during read. host %s at port %d is down. reason: %s", BACKEND_INFO(i).backend_hostname, BACKEND_INFO(i).backend_port, strerror(errno)); close(fd); return i+1; } else if (sts == 0) { pool_error("health check failed. EOF encountered. host %s at port %d is down", BACKEND_INFO(i).backend_hostname, BACKEND_INFO(i).backend_port); close(fd); return i+1; } /* * If a backend raised a FATAL error(max connections error or * starting up error?), do not send a Terminate message. */ if ((kind != 'E') && (write(fd, "X", 1) < 0)) { pool_error("health check failed during write. host %s at port %d is down. reason: %s. Perhaps wrong health check user?", BACKEND_INFO(i).backend_hostname, BACKEND_INFO(i).backend_port, strerror(errno)); close(fd); return i+1; } close(fd); } return 0; }
gpointer active_thread_func(gpointer user_data) { ThreadData *thread_context = (ThreadData *)user_data; PluginOption *option = thread_context->option; int sock_type = SOCK_STREAM; if (sock_type_d) sock_type = SOCK_DGRAM; if (sock_type_s) sock_type = SOCK_STREAM; char *message = g_malloc0(MAX_MESSAGE_LENGTH+1); int fd; if (unix_socket_x) fd = connect_unix_domain_socket(sock_type, option->target); else fd = connect_ip_socket(sock_type, option->target, option->port, option->use_ipv6); if (fd<0) { ERROR("can not connect to %s:%s (%p)\n",option->target, option->port,g_thread_self()); } else { DEBUG("(%d) connected to server on socket %d (%p)\n",thread_context->index,fd,g_thread_self()); } g_mutex_lock(thread_lock); connect_finished++; if (connect_finished == active_thread_count + idle_thread_count) g_cond_broadcast(thread_connected); g_mutex_unlock(thread_lock); DEBUG("thread (%s,%p) created. wait for start ...\n",loggen_plugin_info.name,g_thread_self()); g_mutex_lock(thread_lock); while (!thread_run) { g_cond_wait(thread_start,thread_lock); } g_mutex_unlock(thread_lock); DEBUG("thread (%s,%p) started. (r=%d,c=%d)\n",loggen_plugin_info.name,g_thread_self(),option->rate, option->number_of_messages); unsigned long count = 0; thread_context->buckets = thread_context->option->rate - (thread_context->option->rate / 10); gettimeofday(&thread_context->last_throttle_check, NULL); gettimeofday(&thread_context->start_time, NULL); gboolean connection_error = FALSE; while (fd>0 && thread_run && !connection_error) { if (thread_check_exit_criteria(thread_context)) break; if (thread_check_time_bucket(thread_context)) continue; if (!generate_message) { ERROR("generate_message not yet set up(%p)\n",g_thread_self()); break; } int str_len = generate_message(message, MAX_MESSAGE_LENGTH, thread_context->index, count++); if (str_len < 0) { ERROR("can't generate more log lines. end of input file?\n"); break; } ssize_t sent = 0; while (sent < strlen(message)) { ssize_t rc = send_plain(fd, message + sent, strlen(message) - sent); if (rc < 0) { ERROR("error sending buffer on %d (rc=%zd)\n",fd,rc); errno = ECONNABORTED; connection_error = TRUE; break; } sent += rc; } thread_context->sent_messages++; thread_context->buckets--; } DEBUG("thread (%s,%p) finished\n",loggen_plugin_info.name,g_thread_self()); g_free((gpointer)message); g_mutex_lock(thread_lock); active_thread_count--; g_mutex_unlock(thread_lock); close(fd); g_thread_exit(NULL); return NULL; }