/* * Discard connection and memory allocated by * make_persistent_db_connection(). */ void discard_persistent_db_connection(POOL_CONNECTION_POOL_SLOT *cp) { int len; if(cp == NULL) return; pool_write(cp->con, "X", 1); len = htonl(4); pool_write(cp->con, &len, sizeof(len)); /* * XXX we cannot call pool_flush() here since backend may already * close the socket and pool_flush() automatically invokes fail * over handler. This could happen in copy command (remember the * famous "lost synchronization with server, resetting * connection" message) */ pool_set_nonblock(cp->con->fd); pool_flush_it(cp->con); pool_unset_nonblock(cp->con->fd); pool_close(cp->con); free(cp->sp->startup_packet); free(cp->sp->database); free(cp->sp->user); free(cp->sp); free(cp); }
POOL_STATUS NotificationResponse(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend) { int pid, pid1; char *condition, *condition1 = NULL; int len, len1 = 0; int i; POOL_STATUS status; pool_write(frontend, "A", 1); for (i=0;i<NUM_BACKENDS;i++) { if (VALID_BACKEND(i)) { if (pool_read(CONNECTION(backend, i), &pid, sizeof(pid)) < 0) return POOL_ERROR; condition = pool_read_string(CONNECTION(backend, i), &len, 0); if (condition == NULL) return POOL_END; if (IS_MASTER_NODE_ID(i)) { pid1 = pid; len1 = len; condition1 = strdup(condition); } } } pool_write(frontend, &pid1, sizeof(pid1)); status = pool_write_and_flush(frontend, condition1, len1); free(condition1); return status; }
/* -------------------------------- * ForwardCacheToFrontend - simply forwards cached data to the frontend * * since the cached data passed from the caller is in escaped binary string * format, unescape it and send it to the frontend appending 'Z' at the end. * returns 0 on success, -1 otherwise. * -------------------------------- */ static int ForwardCacheToFrontend(POOL_CONNECTION *frontend, char *cache, char tstate) { int sendlen; size_t sz; char *binary_cache = NULL; binary_cache = (char *)PQunescapeBytea((unsigned char *)cache, &sz); sendlen = (int) sz; if (malloc_failed(binary_cache)) return -1; pool_debug("ForwardCacheToFrontend: query cache found (%d bytes)", sendlen); /* forward cache to the frontend */ pool_write(frontend, binary_cache, sendlen); /* send ReadyForQuery to the frontend*/ pool_write(frontend, "Z", 1); sendlen = htonl(5); pool_write(frontend, &sendlen, sizeof(int)); if (pool_write_and_flush(frontend, &tstate, 1) < 0) { pool_error("pool_query_cache_lookup: error while writing data to the frontend"); PQfreemem(binary_cache); return -1; } PQfreemem(binary_cache); return 0; }
POOL_STATUS CompletedResponse(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend) { int i; char *string = NULL; char *string1 = NULL; int len, len1 = 0; /* read command tag */ string = pool_read_string(MASTER(backend), &len, 0); if (string == NULL) return POOL_END; else if (!strncmp(string, "BEGIN", 5)) TSTATE(backend, MASTER_NODE_ID) = 'T'; else if (!strncmp(string, "COMMIT", 6) || !strncmp(string, "ROLLBACK", 8)) TSTATE(backend, MASTER_NODE_ID) = 'I'; len1 = len; string1 = strdup(string); for (i=0;i<NUM_BACKENDS;i++) { if (!VALID_BACKEND(i) || IS_MASTER_NODE_ID(i)) continue; /* read command tag */ string = pool_read_string(CONNECTION(backend, i), &len, 0); if (string == NULL) return POOL_END; else if (!strncmp(string, "BEGIN", 5)) TSTATE(backend, i) = 'T'; else if (!strncmp(string, "COMMIT", 6) || !strncmp(string, "ROLLBACK", 8)) TSTATE(backend, i) = 'I'; if (len != len1) { pool_debug("CompletedResponse: message length does not match between master(%d \"%s\",) and %d th server (%d \"%s\",)", len, string, i, len1, string1); /* we except INSERT, because INSERT response has OID */ if (strncmp(string1, "INSERT", 6)) { free(string1); return POOL_END; } } } /* forward to the frontend */ pool_write(frontend, "C", 1); pool_debug("CompletedResponse: string: \"%s\"", string1); if (pool_write(frontend, string1, len1) < 0) { free(string1); return POOL_END; } free(string1); return pool_flush(frontend); }
POOL_STATUS CursorResponse(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend) { char *string = NULL; char *string1 = NULL; int len, len1 = 0; int i; /* read cursor name */ string = pool_read_string(MASTER(backend), &len, 0); if (string == NULL) return POOL_END; len1 = len; string1 = strdup(string); for (i=0;i<NUM_BACKENDS;i++) { if (VALID_BACKEND(i) && !IS_MASTER_NODE_ID(i)) { /* read cursor name */ string = pool_read_string(CONNECTION(backend, i), &len, 0); if (string == NULL) return POOL_END; if (len != len1) { pool_error("CursorResponse: length does not match between master(%d) and %d th backend(%d)", len, i, len1); pool_error("CursorResponse: master(%s) %d th backend(%s)", string1, i, string); free(string1); return POOL_END; } } } /* forward to the frontend */ pool_write(frontend, "P", 1); if (pool_write(frontend, string1, len1) < 0) { free(string1); return POOL_END; } free(string1); if (pool_flush(frontend)) return POOL_END; return POOL_CONTINUE; }
POOL_STATUS NoticeResponse(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend) { char *string = NULL; int len; int i; for (i=0;i<NUM_BACKENDS;i++) { if (VALID_BACKEND(i)) { /* read notice message */ string = pool_read_string(CONNECTION(backend, i), &len, 0); if (string == NULL) return POOL_END; } } /* forward to the frontend */ pool_write(frontend, "N", 1); if (pool_write_and_flush(frontend, string, len) < 0) { return POOL_END; } return POOL_CONTINUE; }
bool pool_write_data(TDS_POOL_SOCKET *from, TDS_POOL_SOCKET *to) { int ret; TDSSOCKET *tds; tdsdump_log(TDS_DBG_INFO1, "trying to send\n"); tds = from->tds; tdsdump_log(TDS_DBG_INFO1, "sending %d bytes\n", tds->in_len); /* cf. net.c for better technique. */ ret = pool_write(tds_get_s(to->tds), tds->in_buf + tds->in_pos, tds->in_len - tds->in_pos); /* write failed, cleanup member */ if (ret < 0) return false; tds->in_pos += ret; if (tds->in_pos < tds->in_len) { /* partial write, schedule a future write */ to->poll_send = true; from->poll_recv = false; } else { to->poll_send = false; from->poll_recv = true; } return true; }
/* * send startup packet */ int send_startup_packet(POOL_CONNECTION_POOL_SLOT *cp) { int len; len = htonl(cp->sp->len + sizeof(len)); pool_write(cp->con, &len, sizeof(len)); return pool_write_and_flush(cp->con, cp->sp->startup_packet, cp->sp->len); }
void send_complete_and_ready(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, const int num_rows) { int len; int msg_len; char msg[16]; msg_len = snprintf(msg, 16, "SELECT %d", num_rows); /* if we had more than 16 bytes, including '\0', the string was truncatured * shouldn't happen though, as it would means more than "SELECT 99999999" */ if (msg_len > 15) msg_len = 15; /* complete command response */ pool_write(frontend, "C", 1); if (MAJOR(backend) == PROTO_MAJOR_V3) { len = htonl(4 + strlen(msg)+1); pool_write(frontend, &len, sizeof(len)); } pool_write(frontend, msg, strlen(msg)+1); /* ready for query */ pool_write(frontend, "Z", 1); if (MAJOR(backend) == PROTO_MAJOR_V3) { len = htonl(5); pool_write(frontend, &len, sizeof(len)); pool_write(frontend, "I", 1); } pool_flush(frontend); }
static void sendAuthRequest(POOL_CONNECTION *frontend, AuthRequest areq) { int wsize; /* number of bytes to write */ int areq_nbo; /* areq in network byte order */ /* * If AUTH_REQ_OK, then frontend is OK to connect __with_pgpool__. * Do not send 'R' to the frontend, he still needs to authenticate * himself with the backend. */ if (areq == AUTH_REQ_OK) return; /* request a password */ pool_write(frontend, "R", 1); if (frontend->protoVersion == PROTO_MAJOR_V3) { /* if (areq == AUTH_REQ_MD5) */ /* wsize = htonl(sizeof(int)*2+4); */ /* else if (areq == AUTH_REQ_CRYPT) */ /* wsize = htonl(sizeof(int)*2+2); */ /* else */ wsize = htonl(sizeof(int)*2); pool_write(frontend, &wsize, sizeof(int)); } areq_nbo = htonl(areq); pool_write(frontend, &areq_nbo, sizeof(int)); /* Add the salt for encrypted passwords. */ /* if (areq == AUTH_REQ_MD5) */ /* pq_sendbytes(&buf, port->md5Salt, 4); */ /* else if (areq == AUTH_REQ_CRYPT) */ /* pq_sendbytes(&buf, port->cryptSalt, 2); */ pool_flush(frontend); }
void version_reporting(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend) { static short num_fields = 1; static char *field_names[] = {"pool_version"}; short s; int len; int size; int hsize; static unsigned char nullmap[2] = {0xff, 0xff}; int nbytes = (num_fields + 7)/8; POOL_REPORT_VERSION *version = get_version(); send_row_description(frontend, backend, num_fields, field_names); if (MAJOR(backend) == PROTO_MAJOR_V2) { /* ascii row */ pool_write(frontend, "D", 1); pool_write_and_flush(frontend, nullmap, nbytes); size = strlen(version[0].version); hsize = htonl(size+4); pool_write(frontend, &hsize, sizeof(hsize)); pool_write(frontend, version[0].version, size); } else { /* data row */ pool_write(frontend, "D", 1); len = 6; /* int32 + int16; */ len += 4 + strlen(version[0].version); /* int32 + data */ len = htonl(len); pool_write(frontend, &len, sizeof(len)); s = htons(num_fields); pool_write(frontend, &s, sizeof(s)); len = htonl(strlen(version[0].version)); pool_write(frontend, &len, sizeof(len)); pool_write(frontend, version[0].version, strlen(version[0].version)); } send_complete_and_ready(frontend, backend, 1); free(version); }
static int send_params(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend) { int index; char *name, *value; int len, sendlen; index = 0; while (pool_get_param(&MASTER(backend)->params, index++, &name, &value) == 0) { pool_write(frontend, "S", 1); len = sizeof(sendlen) + strlen(name) + 1 + strlen(value) + 1; sendlen = htonl(len); pool_write(frontend, &sendlen, sizeof(sendlen)); pool_write(frontend, name, strlen(name) + 1); pool_write(frontend, value, strlen(value) + 1); } if (pool_flush(frontend)) { pool_error("pool_send_params: pool_flush() failed"); return -1; } return 0; }
POOL_STATUS EmptyQueryResponse(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend) { char c; int i; for (i=0;i<NUM_BACKENDS;i++) { if (VALID_BACKEND(i)) { if (pool_read(CONNECTION(backend, i), &c, sizeof(c)) < 0) return POOL_END; } } pool_write(frontend, "I", 1); return pool_write_and_flush(frontend, "", 1); }
POOL_STATUS ErrorResponse(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend) { char *string = NULL; int len; int i; POOL_STATUS ret = POOL_CONTINUE; for (i=0;i<NUM_BACKENDS;i++) { if (VALID_BACKEND(i)) { /* read error message */ string = pool_read_string(CONNECTION(backend, i), &len, 0); if (string == NULL) return POOL_END; } } /* forward to the frontend */ pool_write(frontend, "E", 1); if (pool_write_and_flush(frontend, string, len) < 0) return POOL_END; /* * check session context, because this function is called * by pool_do_auth too. */ if (pool_get_session_context()) ret = raise_intentional_error_if_need(backend); /* change transaction state */ for (i=0;i<NUM_BACKENDS;i++) { if (VALID_BACKEND(i)) { if (TSTATE(backend, i) == 'T') TSTATE(backend, i) = 'E'; } } return ret; }
static void write_pool_data_routine(void* data) { e_int32 ret,i; scan_data_t sdata; scan_pool_t *pool = (scan_pool_t *) data; DMSG((STDOUT,"scan job:write_data_routine start.\r\n")); //TODO:更详细的异常处理 for(i=0;i<DATA_NUMBER;i++) { sdata.h_angle = (e_float64)i; ret = pool_write(pool, &sdata); if (ret <= 0) { break; } } DMSG((STDOUT,"scan job:write_data_routine done.")); pool_disconnect(pool);//断开队列 // pool_cancle(pool);//比较两者的不同行为 count++; }
int RowDescription(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, short *result) { short num_fields, num_fields1 = 0; int oid, mod; int oid1, mod1; short size, size1; char *string; int len, len1; int i; pool_read(MASTER(backend), &num_fields, sizeof(short)); num_fields1 = num_fields; for (i=0;i<NUM_BACKENDS;i++) { if (VALID_BACKEND(i) && !IS_MASTER_NODE_ID(i)) { /* # of fields (could be 0) */ pool_read(CONNECTION(backend, i), &num_fields, sizeof(short)); if (num_fields != num_fields1) { pool_error("RowDescription: num_fields does not match between backends master(%d) and %d th backend(%d)", num_fields, i, num_fields1); return POOL_FATAL; } } } /* forward it to the frontend */ pool_write(frontend, "T", 1); pool_write(frontend, &num_fields, sizeof(short)); num_fields = ntohs(num_fields); for (i = 0;i<num_fields;i++) { int j; /* field name */ string = pool_read_string(MASTER(backend), &len, 0); if (string == NULL) return POOL_END; len1 = len; if (pool_write(frontend, string, len) < 0) return POOL_END; for (j=0;j<NUM_BACKENDS;j++) { if (VALID_BACKEND(j) && !IS_MASTER_NODE_ID(j)) { string = pool_read_string(CONNECTION(backend, j), &len, 0); if (string == NULL) return POOL_END; if (len != len1) { pool_error("RowDescription: field length does not match between backends master(%d) and %d th backend(%d)", ntohl(len), j, ntohl(len1)); return POOL_FATAL; } } } /* type oid */ pool_read(MASTER(backend), &oid, sizeof(int)); oid1 = oid; pool_debug("RowDescription: type oid: %d", ntohl(oid)); for (j=0;j<NUM_BACKENDS;j++) { if (VALID_BACKEND(j) && !IS_MASTER_NODE_ID(j)) { pool_read(CONNECTION(backend, j), &oid, sizeof(int)); /* we do not regard oid mismatch as fatal */ if (oid != oid1) { pool_debug("RowDescription: field oid does not match between backends master(%d) and %d th backend(%d)", ntohl(oid), j, ntohl(oid1)); } } } if (pool_write(frontend, &oid1, sizeof(int)) < 0) return POOL_END; /* size */ pool_read(MASTER(backend), &size, sizeof(short)); size1 = size; for (j=0;j<NUM_BACKENDS;j++) { if (VALID_BACKEND(j) && !IS_MASTER_NODE_ID(j)) { pool_read(CONNECTION(backend, j), &size, sizeof(short)); if (size1 != size1) { pool_error("RowDescription: field size does not match between backends master(%d) and %d th backend(%d)", ntohs(size), j, ntohs(size1)); return POOL_FATAL; } } } pool_debug("RowDescription: field size: %d", ntohs(size)); pool_write(frontend, &size1, sizeof(short)); /* modifier */ pool_read(MASTER(backend), &mod, sizeof(int)); pool_debug("RowDescription: modifier: %d", ntohs(mod)); mod1 = mod; for (j=0;j<NUM_BACKENDS;j++) { if (VALID_BACKEND(j) && !IS_MASTER_NODE_ID(j)) { pool_read(CONNECTION(backend, j), &mod, sizeof(int)); if (mod != mod1) { pool_debug("RowDescription: modifier does not match between backends master(%d) and %d th backend(%d)", ntohl(mod), j, ntohl(mod1)); } } } if (pool_write(frontend, &mod1, sizeof(int)) < 0) return POOL_END; } *result = num_fields; return pool_flush(frontend); }
void nodes_reporting(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend) { static short num_fields = 5; static char *field_names[] = {"node_id","hostname", "port", "status", "lb_weight"}; int i; short s; int len; int nrows; int size; int hsize; static unsigned char nullmap[2] = {0xff, 0xff}; int nbytes = (num_fields + 7)/8; POOL_REPORT_NODES* nodes = get_nodes(&nrows); send_row_description(frontend, backend, num_fields, field_names); if (MAJOR(backend) == PROTO_MAJOR_V2) { /* ascii row */ for (i=0;i<nrows;i++) { pool_write(frontend, "D", 1); pool_write_and_flush(frontend, nullmap, nbytes); size = strlen(nodes[i].node_id); hsize = htonl(size+4); pool_write(frontend, &hsize, sizeof(hsize)); pool_write(frontend, nodes[i].node_id, size); size = strlen(nodes[i].hostname); hsize = htonl(size+4); pool_write(frontend, &hsize, sizeof(hsize)); pool_write(frontend, nodes[i].hostname, size); size = strlen(nodes[i].port); hsize = htonl(size+4); pool_write(frontend, &hsize, sizeof(hsize)); pool_write(frontend, nodes[i].port, size); size = strlen(nodes[i].status); hsize = htonl(size+4); pool_write(frontend, &hsize, sizeof(hsize)); pool_write(frontend, nodes[i].status, size); size = strlen(nodes[i].lb_weight); hsize = htonl(size+4); pool_write(frontend, &hsize, sizeof(hsize)); pool_write(frontend, nodes[i].lb_weight, size); } } else { /* data row */ for (i=0;i<nrows;i++) { pool_write(frontend, "D", 1); len = 6; /* int32 + int16; */ len += 4 + strlen(nodes[i].node_id); /* int32 + data; */ len += 4 + strlen(nodes[i].hostname); /* int32 + data; */ len += 4 + strlen(nodes[i].port); /* int32 + data; */ len += 4 + strlen(nodes[i].status); /* int32 + data; */ len += 4 + strlen(nodes[i].lb_weight); /* int32 + data; */ len = htonl(len); pool_write(frontend, &len, sizeof(len)); s = htons(num_fields); pool_write(frontend, &s, sizeof(s)); len = htonl(strlen(nodes[i].node_id)); pool_write(frontend, &len, sizeof(len)); pool_write(frontend, nodes[i].node_id, strlen(nodes[i].node_id)); len = htonl(strlen(nodes[i].hostname)); pool_write(frontend, &len, sizeof(len)); pool_write(frontend, nodes[i].hostname, strlen(nodes[i].hostname)); len = htonl(strlen(nodes[i].port)); pool_write(frontend, &len, sizeof(len)); pool_write(frontend, nodes[i].port, strlen(nodes[i].port)); len = htonl(strlen(nodes[i].status)); pool_write(frontend, &len, sizeof(len)); pool_write(frontend, nodes[i].status, strlen(nodes[i].status)); len = htonl(strlen(nodes[i].lb_weight)); pool_write(frontend, &len, sizeof(len)); pool_write(frontend, nodes[i].lb_weight, strlen(nodes[i].lb_weight)); } } send_complete_and_ready(frontend, backend, nrows); free(nodes); }
void pools_reporting(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend) { static short num_fields = 12; static char *field_names[] = {"pool_pid", "start_time", "pool_id", "backend_id", "database", "username", "create_time", "majorversion", "minorversion", "pool_counter", "pool_backendpid", "pool_connected"}; short s; int len; int i; static unsigned char nullmap[2] = {0xff, 0xff}; int nbytes = (num_fields + 7)/8; int nrows; int size; int hsize; char proc_pid[16]; char pool_id[16]; char proc_start_time[20]; char proc_create_time[20]; char majorversion[5]; char minorversion[5]; char pool_counter[16]; char backend_id[16]; char backend_pid[16]; char connected[2]; POOL_REPORT_POOLS *pools = get_pools(&nrows); send_row_description(frontend, backend, num_fields, field_names); if (MAJOR(backend) == PROTO_MAJOR_V2) hsize = 4; else hsize = 0; /* ascii row */ for (i=0;i<nrows;i++) { snprintf(proc_pid, sizeof(proc_pid), "%d", pools[i].pool_pid); snprintf(pool_id, sizeof(pool_id), "%d", pools[i].pool_id); if (pools[i].start_time) strftime(proc_start_time, POOLCONFIG_MAXDATELEN, "%Y-%m-%d %H:%M:%S", localtime(&pools[i].start_time)); else *proc_start_time = '\0'; if (pools[i].create_time) strftime(proc_create_time, POOLCONFIG_MAXDATELEN, "%Y-%m-%d %H:%M:%S", localtime(&pools[i].create_time)); else *proc_create_time = '\0'; snprintf(majorversion, sizeof(majorversion), "%d", pools[i].pool_majorversion); snprintf(minorversion, sizeof(minorversion), "%d", pools[i].pool_minorversion); snprintf(pool_counter, sizeof(pool_counter), "%d", pools[i].pool_counter); snprintf(backend_id, sizeof(backend_pid), "%d", pools[i].backend_id); snprintf(backend_pid, sizeof(backend_pid), "%d", pools[i].pool_backendpid); snprintf(connected, sizeof(connected), "%d", pools[i].pool_connected); if (MAJOR(backend) == PROTO_MAJOR_V2) { pool_write(frontend, "D", 1); pool_write_and_flush(frontend, nullmap, nbytes); } else { pool_write(frontend, "D", 1); len = 6; /* int32 + int16; */ len += 4 + strlen(proc_pid); /* int32 + data */ len += 4 + strlen(proc_start_time); /* int32 + data */ len += 4 + strlen(pool_id); /* int32 + data */ len += 4 + strlen(backend_id); /* int32 + data */ len += 4 + strlen(pools[i].database); /* int32 + data */ len += 4 + strlen(pools[i].username); /* int32 + data */ len += 4 + strlen(proc_create_time); /* int32 + data */ len += 4 + strlen(majorversion); /* int32 + data */ len += 4 + strlen(minorversion); /* int32 + data */ len += 4 + strlen(pool_counter); /* int32 + data */ len += 4 + strlen(backend_pid); /* int32 + data */ len += 4 + strlen(connected); /* int32 + data */ len = htonl(len); pool_write(frontend, &len, sizeof(len)); s = htons(num_fields); pool_write(frontend, &s, sizeof(s)); } len = strlen(proc_pid); size = htonl(len+hsize); pool_write(frontend, &size, sizeof(size)); pool_write(frontend, proc_pid, len); len = strlen(proc_start_time); size = htonl(len+hsize); pool_write(frontend, &size, sizeof(size)); pool_write(frontend, proc_start_time, len); len = strlen(pool_id); size = htonl(len+hsize); pool_write(frontend, &size, sizeof(size)); pool_write(frontend, pool_id, len); len = strlen(backend_id); size = htonl(len+hsize); pool_write(frontend, &size, sizeof(size)); pool_write(frontend, backend_id, len); len = strlen(pools[i].database); size = htonl(len+hsize); pool_write(frontend, &size, sizeof(size)); pool_write(frontend, pools[i].database, len); len = strlen(pools[i].username); size = htonl(len+hsize); pool_write(frontend, &size, sizeof(size)); pool_write(frontend, pools[i].username, len); len = strlen(proc_create_time); size = htonl(len+hsize); pool_write(frontend, &size, sizeof(size)); pool_write(frontend, proc_create_time, len); len = strlen(majorversion); size = htonl(len+hsize); pool_write(frontend, &size, sizeof(size)); pool_write(frontend, majorversion, len); len = strlen(minorversion); size = htonl(len+hsize); pool_write(frontend, &size, sizeof(size)); pool_write(frontend, minorversion, len); len = strlen(pool_counter); size = htonl(len+hsize); pool_write(frontend, &size, sizeof(size)); pool_write(frontend, pool_counter, len); len = strlen(backend_pid); size = htonl(len+hsize); pool_write(frontend, &size, sizeof(size)); pool_write(frontend, backend_pid, len); len = strlen(connected); size = htonl(len+hsize); pool_write(frontend, &size, sizeof(size)); pool_write(frontend, connected, len); } send_complete_and_ready(frontend, backend, nrows); free(pools); }
void send_row_description(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, short num_fields, char **field_names) { static char *cursorname = "blank"; static int oid = 0; static short fsize = -1; static int mod = 0; short n; int i; short s; int len; short colnum; if (MAJOR(backend) == PROTO_MAJOR_V2) { /* cursor response */ pool_write(frontend, "P", 1); pool_write(frontend, cursorname, strlen(cursorname)+1); } /* row description */ pool_write(frontend, "T", 1); if (MAJOR(backend) == PROTO_MAJOR_V3) { /* information about computed byte in section "RowDescription (B)" here: * http://www.postgresql.org/docs/current/static/protocol-message-formats.html */ len = 6; /* int32 + int16 */ for (i=0;i<num_fields;i++) { /* String + '\0' + 3* int32 + 3* int16 */ len += strlen(field_names[i]) +1 +18; } len = htonl(len); pool_write(frontend, &len, sizeof(len)); } n = htons(num_fields); pool_write(frontend, &n, sizeof(short)); for (i=0;i<num_fields;i++) { pool_write(frontend, field_names[i], strlen(field_names[i])+1); /* field name */ if (MAJOR(backend) == PROTO_MAJOR_V3) { pool_write(frontend, &oid, sizeof(oid)); /* table oid */ colnum = htons(i); pool_write(frontend, &colnum, sizeof(colnum)); /* column number */ } pool_write(frontend, &oid, sizeof(oid)); /* data type oid */ s = htons(fsize); pool_write(frontend, &s, sizeof(fsize)); /* field size */ pool_write(frontend, &mod, sizeof(mod)); /* modifier */ if (MAJOR(backend) == PROTO_MAJOR_V3) { s = htons(0); pool_write(frontend, &s, sizeof(fsize)); /* field format (text) */ } } pool_flush(frontend); }
void config_reporting(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend) { static char *field_names[] = {"item", "value", "description"}; static unsigned char nullmap[2] = {0xff, 0xff}; static short num_fields = 3; short s; int nbytes = (num_fields + 7)/8; int len; int nrows; int size; int hsize; int i; POOL_REPORT_CONFIG *status = get_config(&nrows); send_row_description(frontend, backend, num_fields, field_names); if (MAJOR(backend) == PROTO_MAJOR_V2) { /* ascii row */ for (i=0;i<nrows;i++) { pool_write(frontend, "D", 1); pool_write_and_flush(frontend, nullmap, nbytes); size = strlen(status[i].name); hsize = htonl(size+4); pool_write(frontend, &hsize, sizeof(hsize)); pool_write(frontend, status[i].name, size); size = strlen(status[i].value); hsize = htonl(size+4); pool_write(frontend, &hsize, sizeof(hsize)); pool_write(frontend, status[i].value, size); size = strlen(status[i].desc); hsize = htonl(size+4); pool_write(frontend, &hsize, sizeof(hsize)); pool_write(frontend, status[i].desc, size); } } else { /* data row */ for (i=0;i<nrows;i++) { pool_write(frontend, "D", 1); len = 6; /* int32 + int16; */ len += 4 + strlen(status[i].name); /* int32 + data; */ len += 4 + strlen(status[i].value); /* int32 + data; */ len += 4 + strlen(status[i].desc); /* int32 + data; */ len = htonl(len); pool_write(frontend, &len, sizeof(len)); s = htons(num_fields); pool_write(frontend, &s, sizeof(s)); len = htonl(strlen(status[i].name)); pool_write(frontend, &len, sizeof(len)); pool_write(frontend, status[i].name, strlen(status[i].name)); len = htonl(strlen(status[i].value)); pool_write(frontend, &len, sizeof(len)); pool_write(frontend, status[i].value, strlen(status[i].value)); len = htonl(strlen(status[i].desc)); pool_write(frontend, &len, sizeof(len)); pool_write(frontend, status[i].desc, strlen(status[i].desc)); } } send_complete_and_ready(frontend, backend, nrows); free(status); }
void processes_reporting(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend) { static short num_fields = 6; static char *field_names[] = {"pool_pid", "start_time", "database", "username", "create_time", "pool_counter"}; short s; int len; int nrows; int size; int hsize; int i; static unsigned char nullmap[2] = {0xff, 0xff}; int nbytes = (num_fields + 7)/8; POOL_REPORT_PROCESSES *processes = get_processes(&nrows); send_row_description(frontend, backend, num_fields, field_names); if (MAJOR(backend) == PROTO_MAJOR_V2) { /* ascii row */ for (i=0;i<nrows;i++) { pool_write(frontend, "D", 1); pool_write_and_flush(frontend, nullmap, nbytes); size = strlen(processes[i].pool_pid); hsize = htonl(size+4); pool_write(frontend, &hsize, sizeof(hsize)); pool_write(frontend, processes[i].pool_pid, size); size = strlen(processes[i].start_time); hsize = htonl(size+4); pool_write(frontend, &hsize, sizeof(hsize)); pool_write(frontend, processes[i].start_time, size); size = strlen(processes[i].database); hsize = htonl(size+4); pool_write(frontend, &hsize, sizeof(hsize)); pool_write(frontend, processes[i].database, size); size = strlen(processes[i].username); hsize = htonl(size+4); pool_write(frontend, &hsize, sizeof(hsize)); pool_write(frontend, processes[i].username, size); size = strlen(processes[i].create_time); hsize = htonl(size+4); pool_write(frontend, &hsize, sizeof(hsize)); pool_write(frontend, processes[i].create_time, size); size = strlen(processes[i].pool_counter); hsize = htonl(size+4); pool_write(frontend, &hsize, sizeof(hsize)); pool_write(frontend, processes[i].pool_counter, size); } } else { /* data row */ for (i=0;i<nrows;i++) { pool_write(frontend, "D", 1); len = 6; /* int32 + int16; */ len += 4 + strlen(processes[i].pool_pid); /* int32 + data */ len += 4 + strlen(processes[i].start_time); /* int32 + data */ len += 4 + strlen(processes[i].database); /* int32 + data */ len += 4 + strlen(processes[i].username); /* int32 + data */ len += 4 + strlen(processes[i].create_time); /* int32 + data */ len += 4 + strlen(processes[i].pool_counter); /* int32 + data */ len = htonl(len); pool_write(frontend, &len, sizeof(len)); s = htons(num_fields); pool_write(frontend, &s, sizeof(s)); len = htonl(strlen(processes[i].pool_pid)); pool_write(frontend, &len, sizeof(len)); pool_write(frontend, processes[i].pool_pid, strlen(processes[i].pool_pid)); len = htonl(strlen(processes[i].start_time)); pool_write(frontend, &len, sizeof(len)); pool_write(frontend, processes[i].start_time, strlen(processes[i].start_time)); len = htonl(strlen(processes[i].database)); pool_write(frontend, &len, sizeof(len)); pool_write(frontend, processes[i].database, strlen(processes[i].database)); len = htonl(strlen(processes[i].username)); pool_write(frontend, &len, sizeof(len)); pool_write(frontend, processes[i].username, strlen(processes[i].username)); len = htonl(strlen(processes[i].create_time)); pool_write(frontend, &len, sizeof(len)); pool_write(frontend, processes[i].create_time, strlen(processes[i].create_time)); len = htonl(strlen(processes[i].pool_counter)); pool_write(frontend, &len, sizeof(len)); pool_write(frontend, processes[i].pool_counter, strlen(processes[i].pool_counter)); } } send_complete_and_ready(frontend, backend, nrows); free(processes); }
/* * combo of pool_write and pool_flush */ int pool_write_and_flush(POOL_CONNECTION *cp, void *buf, int len) { if (pool_write(cp, buf, len)) return -1; return pool_flush(cp); }
/* * Do authentication. Assuming the only caller is * *make_persistent_db_connection(). */ static int s_do_auth(POOL_CONNECTION_POOL_SLOT *cp, char *password) { char kind; int status; int length; int auth_kind; char state; char *p; int pid, key; bool keydata_done; /* * read kind expecting 'R' packet (authentication response) */ status = pool_read(cp->con, &kind, sizeof(kind)); if (status < 0) { pool_error("s_do_auth: error while reading message kind"); return -1; } if (kind != 'R') { pool_error("s_do_auth: expecting R got %c", kind); return -1; } /* read message length */ status = pool_read(cp->con, &length, sizeof(length)); if (status < 0) { pool_error("s_do_auth: error while reading message length"); return -1; } length = ntohl(length); /* read auth kind */ status = pool_read(cp->con, &auth_kind, sizeof(auth_kind)); if (status < 0) { pool_error("s_do_auth: error while reading auth kind"); return -1; } auth_kind = ntohl(auth_kind); pool_debug("s_do_auth: auth kind: %d", auth_kind); if (auth_kind == 0) /* trust authentication? */ { cp->con->auth_kind = 0; } else if (auth_kind == 3) /* clear text password? */ { int size = htonl(strlen(password) + 5); pool_write(cp->con, "p", 1); pool_write(cp->con, &size, sizeof(size)); pool_write_and_flush(cp->con, password, strlen(password) + 1); status = pool_flush(cp->con); if (status > 0) { pool_error("s_do_auth: error while sending clear text password"); return -1; } return s_do_auth(cp, password); } else if (auth_kind == 4) /* crypt password? */ { int size; char salt[3]; char *crypt_password; status = pool_read(cp->con, &salt, 2); if (status > 0) { pool_error("s_do_auth: error while reading crypt salt"); return -1; } salt[2] = '\0'; crypt_password = crypt(password, salt); size = htonl(strlen(crypt_password) + 5); pool_write(cp->con, "p", 1); pool_write(cp->con, &size, sizeof(size)); pool_write_and_flush(cp->con, crypt_password, strlen(crypt_password) + 1); status = pool_flush(cp->con); if (status > 0) { pool_error("s_do_auth: error while sending crypt password"); return -1; } return s_do_auth(cp, password); } else if (auth_kind == 5) /* md5 password? */ { char salt[4]; char *buf, *buf1; int size; status = pool_read(cp->con, &salt, 4); if (status > 0) { pool_error("s_do_auth: error while reading md5 salt"); return -1; } buf = malloc(2 * (MD5_PASSWD_LEN + 4)); /* hash + "md5" + '\0' */ if (buf == NULL) { pool_error("s_do_auth(): malloc failed: %s", strerror(errno)); return -1; } memset(buf, 0, 2 * (MD5_PASSWD_LEN + 4)); /* build md5 password */ buf1 = buf + MD5_PASSWD_LEN + 4; pool_md5_encrypt(password, cp->sp->user, strlen(cp->sp->user), buf1); pool_md5_encrypt(buf1, salt, 4, buf + 3); memcpy(buf, "md5", 3); size = htonl(strlen(buf) + 5); pool_write(cp->con, "p", 1); pool_write(cp->con, &size, sizeof(size)); pool_write_and_flush(cp->con, buf, strlen(buf) + 1); status = pool_flush(cp->con); if (status > 0) { pool_error("s_do_auth: error while sending md5 password"); return -1; } status = s_do_auth(cp, password); free(buf); return status; } else { pool_error("s_do_auth: auth kind %d not supported yet", auth_kind); return -1; } /* * Read backend key data and wait until Ready for query arriving or * error happens. */ keydata_done = false; for (;;) { status = pool_read(cp->con, &kind, sizeof(kind)); if (status < 0) { pool_error("s_do_auth: error while reading message kind"); return -1; } switch (kind) { case 'K': /* backend key data */ keydata_done = true; pool_debug("s_do_auth: backend key data received"); /* read message length */ status = pool_read(cp->con, &length, sizeof(length)); if (status < 0) { pool_error("s_do_auth: error while reading message length"); return -1; } if (ntohl(length) != 12) { pool_error("s_do_auth: backend key data length is not 12 (%d)", ntohl(length)); } /* read pid */ if (pool_read(cp->con, &pid, sizeof(pid)) < 0) { pool_error("s_do_auth: failed to read pid"); return -1; } cp->pid = pid; /* read key */ if (pool_read(cp->con, &key, sizeof(key)) < 0) { pool_error("s_do_auth: failed to read key"); return -1; } cp->key = key; break; case 'Z': /* Ready for query */ /* read message length */ status = pool_read(cp->con, &length, sizeof(length)); if (status < 0) { pool_error("s_do_auth: error while reading message length"); return -1; } length = ntohl(length); /* read transaction state */ status = pool_read(cp->con, &state, sizeof(state)); if (status < 0) { pool_error("s_do_auth: error while reading transaction state"); return -1; } pool_debug("s_do_auth: transaction state: %c", state); cp->con->tstate = state; if (!keydata_done) { pool_error("s_do_auth: ready for query arrived before receiving keydata"); } return 0; break; case 'S': /* parameter status */ case 'N': /* notice response */ case 'E': /* error response */ /* Just throw away data */ status = pool_read(cp->con, &length, sizeof(length)); if (status < 0) { pool_error("s_do_auth: error while reading message length. kind:%c", kind); return -1; } length = ntohl(length); length -= 4; p = pool_read2(cp->con, length); if (p == NULL) return -1; break; default: pool_error("s_do_auth: unknown response \"%c\" while processing BackendKeyData", kind); break; } } return -1; }
POOL_STATUS AsciiRow(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, short num_fields) { static char nullmap[8192], nullmap1[8192]; int nbytes; int i, j; unsigned char mask; int size, size1 = 0; char *buf = NULL, *sendbuf = NULL; char msgbuf[1024]; pool_write(frontend, "D", 1); nbytes = (num_fields + 7)/8; if (nbytes <= 0) return POOL_CONTINUE; /* NULL map */ pool_read(MASTER(backend), nullmap, nbytes); memcpy(nullmap1, nullmap, nbytes); for (i=0;i<NUM_BACKENDS;i++) { if (VALID_BACKEND(i) && !IS_MASTER_NODE_ID(i)) { pool_read(CONNECTION(backend, i), nullmap, nbytes); if (memcmp(nullmap, nullmap1, nbytes)) { /* XXX: NULLMAP maybe different among backends. If we were a paranoid, we have to treat this as a fatal error. However in the real world we'd better to adapt this situation. Just throw a log... */ pool_debug("AsciiRow: NULLMAP differ between master and %d th backend", i); } } } if (pool_write(frontend, nullmap1, nbytes) < 0) return POOL_END; mask = 0; for (i = 0;i<num_fields;i++) { if (mask == 0) mask = 0x80; /* NOT NULL? */ if (mask & nullmap[i/8]) { /* field size */ if (pool_read(MASTER(backend), &size, sizeof(int)) < 0) return POOL_END; size1 = ntohl(size) - 4; /* read and send actual data only when size > 0 */ if (size1 > 0) { sendbuf = pool_read2(MASTER(backend), size1); if (sendbuf == NULL) return POOL_END; } /* forward to frontend */ pool_write(frontend, &size, sizeof(int)); pool_write(frontend, sendbuf, size1); snprintf(msgbuf, Min(sizeof(msgbuf), size1+1), "%s", sendbuf); pool_debug("AsciiRow: len: %d data: %s", size1, msgbuf); for (j=0;j<NUM_BACKENDS;j++) { if (VALID_BACKEND(j) && !IS_MASTER_NODE_ID(j)) { /* field size */ if (pool_read(CONNECTION(backend, j), &size, sizeof(int)) < 0) return POOL_END; buf = NULL; size = ntohl(size) - 4; /* XXX: field size maybe different among backends. If we were a paranoid, we have to treat this as a fatal error. However in the real world we'd better to adapt this situation. Just throw a log... */ if (size != size1) pool_debug("AsciiRow: %d th field size does not match between master(%d) and %d th backend(%d)", i, ntohl(size), j, ntohl(size1)); /* read and send actual data only when size > 0 */ if (size > 0) { buf = pool_read2(CONNECTION(backend, j), size); if (buf == NULL) return POOL_END; } } } } mask >>= 1; } if (pool_flush(frontend)) return POOL_END; return POOL_CONTINUE; }
POOL_STATUS FunctionResultResponse(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend) { char dummy; int len; char *result = 0; int i; pool_write(frontend, "V", 1); for (i=0;i<NUM_BACKENDS;i++) { if (VALID_BACKEND(i)) { if (pool_read(CONNECTION(backend, i), &dummy, 1) < 0) return POOL_ERROR; } } pool_write(frontend, &dummy, 1); /* non empty result? */ if (dummy == 'G') { for (i=0;i<NUM_BACKENDS;i++) { if (VALID_BACKEND(i)) { /* length of result in bytes */ if (pool_read(CONNECTION(backend, i), &len, sizeof(len)) < 0) return POOL_ERROR; } } pool_write(frontend, &len, sizeof(len)); len = ntohl(len); for (i=0;i<NUM_BACKENDS;i++) { if (VALID_BACKEND(i)) { /* result value itself */ if ((result = pool_read2(MASTER(backend), len)) == NULL) return POOL_ERROR; } } pool_write(frontend, result, len); } for (i=0;i<NUM_BACKENDS;i++) { if (VALID_BACKEND(i)) { /* unused ('0') */ if (pool_read(MASTER(backend), &dummy, 1) < 0) return POOL_ERROR; } } pool_write(frontend, "0", 1); return pool_flush(frontend); }
/* -------------------------------- * search_system_db_for_cache - search for query cache in libpq protocol level * * sends a cache searching query string using libpq protocol to the SystemDB. * if the SystemDB returns cache, forward the data to the frontend, and return * CACHE_FOUND. if cache was not found, silently discards the remaining data * returned by the SystemDB, and return CACHE_NOT_FOUND. returns CACHE_ERROR * if an error was encountered. * -------------------------------- */ static CACHE_STATUS search_system_db_for_cache(POOL_CONNECTION *frontend, char *sql, int sql_len, struct timeval *t, char tstate) { fd_set readmask; int fds; int num_fds; struct timeval *timeout = NULL; char kind; int readlen; char *data = NULL; CACHE_STATUS return_value = CACHE_ERROR; int cache_found = 0; pool_debug("pool_query_cache_lookup: executing query: \"%s\"", sql); pool_write(SYSDB_CON, "Q", 1); if (SYSDB_MAJOR == PROTO_MAJOR_V3) { int sendlen = htonl(sql_len + 4); pool_write(SYSDB_CON, &sendlen, sizeof(sendlen)); } if (pool_write_and_flush(SYSDB_CON, sql, sql_len) < 0) { pool_error("pool_query_cache_lookup: error while sending data to the SystemDB"); return CACHE_ERROR; } if ((t->tv_sec + t->tv_usec) == 0) timeout = NULL; else timeout = t; /* don't really need select() or for(;;) here, but we may need it someday... or not */ for (;;) { FD_ZERO(&readmask); num_fds = 0; num_fds = SYSDB_CON->fd + 1; FD_SET(SYSDB_CON->fd, &readmask); fds = select(num_fds, &readmask, NULL, NULL, timeout); if (fds == -1) { if (errno == EINTR) continue; pool_error("pool_query_cache_lookup: select() failed. reason: %s", strerror(errno)); return CACHE_ERROR; } /* select() timeout */ if (fds == 0) return CACHE_ERROR; for (;;) { if (! FD_ISSET(SYSDB_CON->fd, &readmask)) { pool_error("pool_query_cache_lookup: select() failed"); return CACHE_ERROR; } /* read kind */ if (pool_read(SYSDB_CON, &kind, sizeof(kind)) < 0) { pool_error("pool_query_cache_lookup: error while reading message kind"); return CACHE_ERROR; } pool_debug("pool_query_cache_lookup: received %c from systemdb", kind); /* just do the routine work of reading data in. data won't be used */ if (kind == 'T') { if (SYSDB_MAJOR == PROTO_MAJOR_V3) { if (pool_read(SYSDB_CON, &readlen, sizeof(int)) < 0) { pool_error("pool_query_cache_lookup: error while reading message length"); return CACHE_ERROR; } readlen = ntohl(readlen) - sizeof(int); data = pool_read2(SYSDB_CON, readlen); } else { data = pool_read_string(SYSDB_CON, &readlen, 0); } } else if (kind == 'D') /* cache found! forward it to the frontend */ { char *cache; int status; cache_found = 1; if (SYSDB_MAJOR == PROTO_MAJOR_V3) { if (pool_read(SYSDB_CON, &readlen, sizeof(readlen)) < 0) { pool_error("pool_query_cache_lookup: error while reading message length"); return CACHE_ERROR; } readlen = ntohl(readlen) - sizeof(int); cache = pool_read2(SYSDB_CON, readlen); } else { cache = pool_read_string(SYSDB_CON, &readlen, 0); } if (cache == NULL) { pool_error("pool_query_cache_lookup: error while reading message body"); return CACHE_ERROR; } cache[readlen] = '\0'; cache += sizeof(short); /* number of columns in 'D' (we know it's always going to be 1, so skip) */ cache += sizeof(int); /* length of escaped bytea cache in string format. don't need the length */ status = ForwardCacheToFrontend(frontend, cache, tstate); if (status < 0) { /* fatal error has occured while forwarding cache */ pool_error("pool_query_cache_lookup: query cache forwarding failed"); return_value = CACHE_ERROR; } } else if (kind == 'C') /* see if 'D' was received */ { if (cache_found) return_value = CACHE_FOUND; else return_value = CACHE_NOT_FOUND; /* must discard the remaining data */ if (SYSDB_MAJOR == PROTO_MAJOR_V3) { if (pool_read(SYSDB_CON, &readlen, sizeof(int)) < 0) { pool_error("pool_query_cache_lookup: error while reading message length"); return CACHE_ERROR; } readlen = ntohl(readlen) - sizeof(int); data = pool_read2(SYSDB_CON, readlen); } else { data = pool_read_string(SYSDB_CON, &readlen, 0); } } else if (kind == 'Z') { /* must discard the remaining data */ if (SYSDB_MAJOR == PROTO_MAJOR_V3) { if (pool_read(SYSDB_CON, &readlen, sizeof(int)) < 0) { pool_error("pool_query_cache_lookup: error while reading message length"); return CACHE_ERROR; } readlen = ntohl(readlen) - sizeof(int); data = pool_read2(SYSDB_CON, readlen); } else { data = pool_read_string(SYSDB_CON, &readlen, 0); } break; } else if (kind == 'E') { /* must discard the remaining data */ if (SYSDB_MAJOR == PROTO_MAJOR_V3) { if (pool_read(SYSDB_CON, &readlen, sizeof(int)) < 0) { pool_error("pool_query_cache_lookup: error while reading message length"); return CACHE_ERROR; } readlen = ntohl(readlen) - sizeof(int); data = pool_read2(SYSDB_CON, readlen); } else { data = pool_read_string(SYSDB_CON, &readlen, 0); } return_value = CACHE_ERROR; } else { /* shouldn't get here, but just in case */ return CACHE_ERROR; } } break; } return return_value; }
/* * 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); } }
/* * Reuse existing connection */ static bool connect_using_existing_connection(POOL_CONNECTION *frontend, POOL_CONNECTION_POOL *backend, StartupPacket *sp) { int i, freed = 0; /* * Save startup packet info */ for (i = 0; i < NUM_BACKENDS; i++) { if (VALID_BACKEND(i)) { if (!freed) { pool_free_startup_packet(backend->slots[i]->sp); freed = 1; } backend->slots[i]->sp = sp; } } /* Reuse existing connection to backend */ if (pool_do_reauth(frontend, backend)) { pool_close(frontend); connection_count_down(); return false; } if (MAJOR(backend) == 3) { char command_buf[1024]; /* If we have received application_name in the start up * packet, we send SET command to backend. Also we add or * replace existing application_name data. */ if (sp->application_name) { snprintf(command_buf, sizeof(command_buf), "SET application_name TO '%s'", sp->application_name); for (i=0;i<NUM_BACKENDS;i++) { if (VALID_BACKEND(i)) if (do_command(frontend, CONNECTION(backend, i), command_buf, MAJOR(backend), MASTER_CONNECTION(backend)->pid, MASTER_CONNECTION(backend)->key, 0) != POOL_CONTINUE) { pool_error("connect_using_existing_connection: do_command failed. command: %s", command_buf); return false; } } pool_add_param(&MASTER(backend)->params, "application_name", sp->application_name); } if (send_params(frontend, backend)) { pool_close(frontend); connection_count_down(); return false; } } /* Send ReadyForQuery to frontend */ pool_write(frontend, "Z", 1); if (MAJOR(backend) == 3) { int len; char tstate; len = htonl(5); pool_write(frontend, &len, sizeof(len)); tstate = TSTATE(backend, MASTER_NODE_ID); pool_write(frontend, &tstate, 1); } if (pool_flush(frontend) < 0) { pool_close(frontend); connection_count_down(); return false; } return true; }
static void write_pool_data_routine(laser_sick_t *ls) { e_int32 ret, first_time = 1, delay, profile_number; e_float64 angle_dif, started_angle, before_angle; //记录起始位置,保证180度是对齐的 scan_data_t sdata = { 0 }; #if DEBUG_TIME e_uint32 start_time; #endif DMSG((STDOUT,"scan job:write_data_routine start.\r\n")); angle_dif = ls->angle_dif_per_cloumn; delay = ANGLE_TO_STEP(angle_dif) * PULSE_SPEED_TO_STEP_TIME(ls->speed_h) / 1e3; before_angle = STEP_TO_ANGLE((630000.0/PULSE_SPEED_TO_STEP_TIME(ls->speed_h))); ret = sld_set_sensor_mode_to_rotate(ls->sick); e_assert(ret>0); DMSG((STDOUT,"control trun to start angle...\n")); //等待扫描仪就位,会有准备工作开始 do { sdata.h_angle = lm_turntable_get_angle() - ls->pre_scan_angle + ls->start_angle_h; if (sdata.h_angle > ls->start_angle_h - before_angle) { break; } Delay(delay); } while (ls->state == STATE_WORK); DMSG((STDOUT,"control now on start angle.start to get data...\n")); ret = sld_set_sensor_mode_to_measure_ex(ls->sick); e_assert(ret>0); ret = lm_start_record_angle(ls->writer); e_assert(ret>0); while (ls->state == STATE_WORK) { #if DEBUG_TIME start_time = GetTickCount(); #endif ret = sld_get_measurements_ex(ls->sick, &sdata); // DMSG((STDOUT,"profile_counter=%d profile_number=%d\n",sdata.profile_counter,sdata.profile_number)); if (!first_time) { if (profile_number != sdata.profile_number) DMSG( (STDOUT,"lost a data layer_num=%d profile_number=%d\n",sdata.layer_num,profile_number)); } profile_number = sdata.profile_number + 1; if (ret == E_ERROR_TIME_OUT) { DMSG((STDOUT,"sld_get_measurements ERROR: RETRY.\r\n")); Delay(10); continue; } else if (ret <= 0) { DMSG( (STDOUT,"sld_get_measurements sickld is down?ret=%d Out.\r\n",(int)ret)); break; } #if DEBUG_TIME DMSG((STDOUT,"Get use %u\n",GetTickCount()-start_time)); #endif // print_sdata(ls,&sdata); ret = pool_write(&ls->pool, &sdata); if (ret < 0) DMSG( (STDOUT,"data pool disconnected,write data routine now stop.\n")); // DMSG((STDOUT,"[%d] %f end: %f\n",sdata.profile_number, sdata.h_angle,ls->end_angle_h)); first_time = 0; } lm_stop_record_angle(); sld_set_sensor_mode_to_idle(ls->sick); DMSG((STDOUT,"scan job:write_data_routine done.\n")); }