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; }
/* * Collect password response packet from frontend. * * Returns NULL if couldn't get password, else malloc'd string. */ static char *recv_password_packet(POOL_CONNECTION *frontend) { int rsize; char *passwd; char *returnVal; if (frontend->protoVersion == PROTO_MAJOR_V3) { /* Expect 'p' message type */ char kind; if (pool_read(frontend, &kind, 1) < 0) return NULL; if (kind != 'p') { pool_error("expected password response, got message type %c", kind); return NULL; /* bad message type */ } } /* pre-3.0 protocol does not send a message type */ if (pool_read(frontend, &rsize, sizeof(int)) < 0) return NULL; rsize = ntohl(rsize) - 4; passwd = pool_read2(frontend, rsize); /* retrieve password */ if (passwd == NULL) return NULL; /* Do not echo password to logs, for security. */ pool_debug("received password packet from frontend for pgpool's HBA"); /* * Return the received string. Note we do not attempt to do any * character-set conversion on it; since we don't yet know the * client's encoding, there wouldn't be much point. */ returnVal = strdup(passwd); if (returnVal == NULL) { pool_error("recv_password_packet: strdup failed: %s", strerror(errno)); exit(1); } return returnVal; }
/* attempt to negotiate a secure connection */ void pool_ssl_negotiate_clientserver(POOL_CONNECTION *cp) { int ssl_packet[2] = { htonl(sizeof(int)*2), htonl(NEGOTIATE_SSL_CODE) }; char server_response; cp->ssl_active = -1; if ( (!pool_config->ssl) || init_ssl_ctx(cp, ssl_conn_clientserver)) return; ereport(DEBUG1, (errmsg("attempting to negotiate a secure connection"), errdetail("sending client->server SSL request"))); pool_write_and_flush(cp, ssl_packet, sizeof(int)*2); if (pool_read(cp, &server_response, 1) < 0) { ereport(WARNING, (errmsg("error while attempting to negotiate a secure connection, pool_read failed"))); return; } ereport(DEBUG1, (errmsg("attempting to negotiate a secure connection"), errdetail("client->server SSL response: %c", server_response))); switch (server_response) { case 'S': SSL_set_fd(cp->ssl, cp->fd); SSL_RETURN_VOID_IF( (SSL_connect(cp->ssl) < 0), "SSL_connect"); cp->ssl_active = 1; break; case 'N': /* * If backend does not support SSL but pgpool does, we get this. * i.e. This is normal. */ ereport(DEBUG1, (errmsg("attempting to negotiate a secure connection"), errdetail("server doesn't want to talk SSL"))); break; default: ereport(WARNING, (errmsg("error while attempting to negotiate a secure connection, unhandled response: %c", server_response))); break; } }
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_get_first_valid_btt -- return offset to first valid BTT Info * * - Return offset to valid BTT Info header in pool file. * - Start looking from given offset. * - Convert BTT Info header to host endianness. * - Return the BTT Info header by pointer. * - If zeroed pointer provided would check if all checked BTT Info are zeroed * which is useful for BLK pools */ uint64_t pool_get_first_valid_btt(struct pool_data *pool, struct btt_info *infop, uint64_t offset, bool *zeroed) { /* if we have valid arena get BTT Info header from it */ if (pool->narenas != 0) { struct arena *arenap = TAILQ_FIRST(&pool->arenas); memcpy(infop, &arenap->btt_info, sizeof(*infop)); return arenap->offset; } const size_t info_size = sizeof(*infop); /* theoretical offsets to BTT Info header and backup */ uint64_t offsets[2] = {offset, 0}; while (offsets[0] < pool->set_file->size) { /* calculate backup offset */ offsets[1] = pool_next_arena_offset(pool, offsets[0]) - info_size; /* check both offsets: header and backup */ for (int i = 0; i < 2; ++i) { if (pool_read(pool, infop, info_size, offsets[i])) continue; /* check if all possible BTT Info are zeroed */ if (zeroed) *zeroed &= util_is_zeroed((const void *)infop, info_size); /* check if read BTT Info is valid */ if (pool_btt_info_valid(infop)) { btt_info_convert2h(infop); return offsets[i]; } } /* jump to next arena */ offsets[0] += BTT_MAX_ARENA; } return 0; }
static void read_pool_data_routine(void* data) { e_int32 ret,i=0; scan_data_t sdata; scan_pool_t *pool = (scan_pool_t *) data; DMSG((STDOUT,"scan job:read_data_routine start.\r\n")); //TODO:更详细的异常处理 while (1) { ret = pool_read(pool, &sdata); if (ret <= 0) { break; } DMSG((STDOUT,"read_data_routine write data at angle: %f.\r\n",(float)sdata.h_angle)); usleep(100000); //模拟费时的操作100ms } DMSG((STDOUT,"scan job:write_data_routine done.\r\n")); count++; }
static void read_pool_data_routine(laser_sick_t *ls) { e_int32 ret; scan_data_t sdata; #if DEBUG_TIME e_uint32 start_time; #endif DMSG((STDOUT,"scan job:read_data_routine start.\r\n")); //创建数据交错缓冲区 if (ls->interlace_v > 1) ls->scan_data_buf = (scan_data_t*) malloc( sizeof(scan_data_t) * ls->interlace_v); //TODO:更详细的异常处理 while (ls->state == STATE_WORK) { ret = pool_read(&ls->pool, &sdata); if (ret <= 0) { DMSG((STDOUT,"pool has been cleared, leave!\r\n")); break; } #if DEBUG_TIME start_time = GetTickCount(); #endif // DMSG((STDOUT,"read_data_routine read data at angle: %f.\r\n", sdata.h_angle)); filter_data(ls, &sdata); #if DEBUG_TIME DMSG((STDOUT,"[%d] Phrase data use:%u\n",sdata.layer_num,GetTickCount()-start_time)); #endif } free(ls->scan_data_buf); if (e_check(ls->slip_idx != ls->width, "#ERROR# 列数与要求的不一致!\n")) { DMSG( (STDOUT, "ls->slip_idx = %u, ls->width = %u \n", (unsigned int)ls->slip_idx,(unsigned int)ls->width)); ls->width = ls->slip_idx; //TODO:修复这里,不允许简单丢掉!! } pool_cancle(&ls->pool); DMSG((STDOUT,"scan job:read_data_routine done.\r\n")); }
/* * cto_read -- (internal) read pmemcto header */ static int cto_read(PMEMpoolcheck *ppc) { /* * Here we want to read the pmemcto header without the pool_hdr as we've * already done it before. * * Take the pointer to fields right after pool_hdr, compute the size and * offset of remaining fields. */ uint8_t *ptr = (uint8_t *)&ppc->pool->hdr.cto; ptr += sizeof(ppc->pool->hdr.cto.hdr); size_t size = sizeof(ppc->pool->hdr.cto) - sizeof(ppc->pool->hdr.cto.hdr); uint64_t offset = sizeof(ppc->pool->hdr.log.hdr); if (pool_read(ppc->pool, ptr, size, offset)) return CHECK_ERR(ppc, "cannot read pmemcto structure"); return 0; }
/* * Read startup packet * * Read the startup packet and parse the contents. */ static StartupPacket *read_startup_packet(POOL_CONNECTION *cp) { StartupPacket *sp; StartupPacket_v2 *sp2; int protov; int len; char *p; sp = (StartupPacket *)calloc(sizeof(*sp), 1); if (!sp) { pool_error("read_startup_packet: out of memory"); return NULL; } if (pool_config->authentication_timeout > 0) { pool_signal(SIGALRM, authentication_timeout); alarm(pool_config->authentication_timeout); } /* read startup packet length */ if (pool_read(cp, &len, sizeof(len))) { pool_error("read_startup_packet: incorrect packet length (%d)", len); pool_free_startup_packet(sp); alarm(0); pool_signal(SIGALRM, SIG_IGN); return NULL; } len = ntohl(len); len -= sizeof(len); if (len <= 0 || len >= MAX_STARTUP_PACKET_LENGTH) { pool_error("read_startup_packet: incorrect packet length (%d)", len); pool_free_startup_packet(sp); alarm(0); pool_signal(SIGALRM, SIG_IGN); return NULL; } sp->startup_packet = calloc(len, 1); if (!sp->startup_packet) { pool_error("read_startup_packet: out of memory"); pool_free_startup_packet(sp); alarm(0); pool_signal(SIGALRM, SIG_IGN); return NULL; } /* read startup packet */ if (pool_read(cp, sp->startup_packet, len)) { pool_free_startup_packet(sp); alarm(0); pool_signal(SIGALRM, SIG_IGN); return NULL; } sp->len = len; memcpy(&protov, sp->startup_packet, sizeof(protov)); sp->major = ntohl(protov)>>16; sp->minor = ntohl(protov) & 0x0000ffff; p = sp->startup_packet; switch(sp->major) { case PROTO_MAJOR_V2: /* V2 */ sp2 = (StartupPacket_v2 *)(sp->startup_packet); sp->database = calloc(SM_DATABASE+1, 1); if (!sp->database) { pool_error("read_startup_packet: out of memory"); pool_free_startup_packet(sp); alarm(0); pool_signal(SIGALRM, SIG_IGN); return NULL; } strncpy(sp->database, sp2->database, SM_DATABASE); sp->user = calloc(SM_USER+1, 1); if (!sp->user) { pool_error("read_startup_packet: out of memory"); pool_free_startup_packet(sp); alarm(0); pool_signal(SIGALRM, SIG_IGN); return NULL; } strncpy(sp->user, sp2->user, SM_USER); break; case PROTO_MAJOR_V3: /* V3 */ p += sizeof(int); /* skip protocol version info */ while(*p) { if (!strcmp("user", p)) { p += (strlen(p) + 1); sp->user = strdup(p); if (!sp->user) { pool_error("read_startup_packet: out of memory"); pool_free_startup_packet(sp); alarm(0); pool_signal(SIGALRM, SIG_IGN); return NULL; } } else if (!strcmp("database", p)) { p += (strlen(p) + 1); sp->database = strdup(p); if (!sp->database) { pool_error("read_startup_packet: out of memory"); pool_free_startup_packet(sp); alarm(0); pool_signal(SIGALRM, SIG_IGN); return NULL; } } /* * From 9.0, the start up packet may include * application name. After receiving such that packet, * backend sends parameter status of application_name. * Upon reusing connection to backend, we need to * emulate this behavior of backend. So we remember * this and send parameter status packet to frontend * instead of backend in * connect_using_existing_connection(). */ else if (!strcmp("application_name", p)) { p += (strlen(p) + 1); sp->application_name = p; pool_debug("read_startup_packet: application_name: %s", p); } p += (strlen(p) + 1); } break; case 1234: /* cancel or SSL request */ /* set dummy database, user info */ sp->database = calloc(1, 1); if (!sp->database) { pool_error("read_startup_packet: out of memory"); pool_free_startup_packet(sp); alarm(0); pool_signal(SIGALRM, SIG_IGN); return NULL; } sp->user = calloc(1, 1); if (!sp->user) { pool_error("read_startup_packet: out of memory"); pool_free_startup_packet(sp); alarm(0); pool_signal(SIGALRM, SIG_IGN); return NULL; } break; default: pool_error("read_startup_packet: invalid major no: %d", sp->major); pool_free_startup_packet(sp); alarm(0); pool_signal(SIGALRM, SIG_IGN); return NULL; } pool_debug("Protocol Major: %d Minor: %d database: %s user: %s", sp->major, sp->minor, sp->database, sp->user); alarm(0); pool_signal(SIGALRM, SIG_IGN); return sp; }
/* * 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; }
/* -------------------------------- * 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; }
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); }
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); }
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; }