/* -------------------------------- * pcp_read - read 'len' bytes from 'pc' * * return 0 on success, -1 otherwise * -------------------------------- */ int pcp_read(PCP_CONNECTION *pc, void *buf, int len) { static char readbuf[READBUFSZ]; int consume_size; int readlen; int notimeout = 0; consume_size = consume_pending_data(pc, buf, len); len -= consume_size; buf += consume_size; while (len > 0) { if (pcp_check_fd(pc, notimeout)) { errorcode = TIMEOUTERR; return -1; } readlen = read(pc->fd, readbuf, READBUFSZ); if (readlen == -1) { if (errno == EAGAIN || errno == EINTR) continue; errorcode = READERR; return -1; } else if (readlen == 0) { errorcode = EOFERR; return -1; } if (len < readlen) { /* overrun. we need to save remaining data to pending buffer */ if (save_pending_data(pc, readbuf+len, readlen-len)) { errorcode = NOMEMERR; return -1; } memmove(buf, readbuf, len); break; } memmove(buf, readbuf, readlen); buf += readlen; len -= readlen; } return 0; }
/* * read a string until EOF or NULL is encountered. * if line is not 0, read until new line is encountered. */ char *pool_read_string(POOL_CONNECTION *cp, int *len, int line) { int readp; int readsize; int readlen; int strlength; int flag; int consume_size; #ifdef DEBUG static char pbuf[READBUFSZ]; #endif *len = 0; readp = 0; /* initialize read buffer */ if (cp->sbufsz == 0) { cp->sbuf = malloc(READBUFSZ); if (cp->sbuf == NULL) { pool_error("pool_read_string: malloc failed"); return NULL; } cp->sbufsz = READBUFSZ; *cp->sbuf = '\0'; } /* any pending data? */ if (cp->len) { if (line) strlength = mystrlinelen(cp->hp+cp->po, cp->len, &flag); else strlength = mystrlen(cp->hp+cp->po, cp->len, &flag); /* buffer is too small? */ if ((strlength + 1) > cp->sbufsz) { cp->sbufsz = ((strlength+1)/READBUFSZ+1)*READBUFSZ; cp->sbuf = realloc(cp->sbuf, cp->sbufsz); if (cp->sbuf == NULL) { pool_error("pool_read_string: realloc failed"); return NULL; } } /* consume pending and save to read string buffer */ consume_size = consume_pending_data(cp, cp->sbuf, strlength); *len = strlength; /* is the string null terminated? */ if (consume_size == strlength && !flag) { /* not null or line terminated. * we need to read more since we have not encountered NULL or new line yet */ readsize = cp->sbufsz - strlength; readp = strlength; } else { pool_debug("pool_read_string: read all from pending data. po:%d len:%d", cp->po, cp->len); return cp->sbuf; } } else { readsize = cp->sbufsz; } for (;;) { if (pool_check_fd(cp)) { if (!IS_MASTER_NODE_ID(cp->db_node_id)) { pool_log("pool_read_string: data is not ready in DB node:%d. abort this session", cp->db_node_id); exit(1); } else { pool_error("pool_read_string: pool_check_fd failed (%s)", strerror(errno)); return NULL; } } if (cp->ssl_active > 0) { readlen = pool_ssl_read(cp, cp->sbuf+readp, readsize); } else { readlen = read(cp->fd, cp->sbuf+readp, readsize); } if (readlen == -1) { pool_error("pool_read_string: read() failed. reason:%s", strerror(errno)); if (cp->isbackend) { notice_backend_error(cp->db_node_id); child_exit(1); } else { return NULL; } } else if (readlen == 0) /* EOF detected */ { /* * just returns an error, not trigger failover or degeneration */ pool_error("pool_read_string: read () EOF detected"); return NULL; } /* check overrun */ if (line) strlength = mystrlinelen(cp->sbuf+readp, readlen, &flag); else strlength = mystrlen(cp->sbuf+readp, readlen, &flag); if (strlength < readlen) { save_pending_data(cp, cp->sbuf+readp+strlength, readlen-strlength); *len += strlength; pool_debug("pool_read_string: total result %d with pending data po:%d len:%d", *len, cp->po, cp->len); return cp->sbuf; } *len += readlen; /* encountered null or newline? */ if (flag) { /* ok we have read all data */ pool_debug("pool_read_string: total result %d ", *len); break; } readp += readlen; readsize = READBUFSZ; if ((*len+readsize) > cp->sbufsz) { cp->sbufsz += READBUFSZ; cp->sbuf = realloc(cp->sbuf, cp->sbufsz); if (cp->sbuf == NULL) { pool_error("pool_read_string: realloc failed"); return NULL; } } } return cp->sbuf; }
/* * read len bytes from cp * returns 0 on success otherwise -1. */ int pool_read(POOL_CONNECTION *cp, void *buf, int len) { static char readbuf[READBUFSZ]; int consume_size; int readlen; consume_size = consume_pending_data(cp, buf, len); len -= consume_size; buf += consume_size; while (len > 0) { if (pool_check_fd(cp)) { if (!IS_MASTER_NODE_ID(cp->db_node_id)) { pool_log("pool_read: data is not ready in DB node: %d. abort this session", cp->db_node_id); exit(1); } else { pool_error("pool_read: pool_check_fd failed (%s)", strerror(errno)); return -1; } } if (cp->ssl_active > 0) { readlen = pool_ssl_read(cp, readbuf, READBUFSZ); } else { readlen = read(cp->fd, readbuf, READBUFSZ); } if (readlen == -1) { if (errno == EINTR || errno == EAGAIN) { pool_debug("pool_read: retrying due to %s", strerror(errno)); continue; } pool_error("pool_read: read failed (%s)", strerror(errno)); if (cp->isbackend) { /* fatal error, notice to parent and exit */ notice_backend_error(cp->db_node_id); child_exit(1); } else { return -1; } } else if (readlen == 0) { if (cp->isbackend) { pool_error("pool_read: EOF encountered with backend"); return -1; #ifdef NOT_USED /* fatal error, notice to parent and exit */ notice_backend_error(IS_MASTER_NODE_ID(cp->db_node_id)); child_exit(1); #endif } else { /* * if backend offers authentication method, frontend could close connection */ return -1; } } if (len < readlen) { /* overrun. we need to save remaining data to pending buffer */ if (save_pending_data(cp, readbuf+len, readlen-len)) return -1; memmove(buf, readbuf, len); break; } memmove(buf, readbuf, readlen); buf += readlen; len -= readlen; } return 0; }