aboutsummaryrefslogtreecommitdiff
path: root/src/interfaces/libpq/fe-misc.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2003-04-22 00:08:07 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2003-04-22 00:08:07 +0000
commit5ed27e35f35f6c354b1a7120ec3a3ce57f93e73e (patch)
tree9ed912fbf02c36160a88881764735f8eab6103b9 /src/interfaces/libpq/fe-misc.c
parentca944bd2d41814712cb4a4810ab4aa490f23a853 (diff)
downloadpostgresql-5ed27e35f35f6c354b1a7120ec3a3ce57f93e73e.tar.gz
postgresql-5ed27e35f35f6c354b1a7120ec3a3ce57f93e73e.zip
Another round of protocol changes. Backend-to-frontend messages now all
have length words. COPY OUT reimplemented per new protocol: it doesn't need \. anymore, thank goodness. COPY BINARY to/from frontend works, at least as far as the backend is concerned --- libpq's PQgetline API is not up to snuff, and will have to be replaced with something that is null-safe. libpq uses message length words for performance improvement (no cycles wasted rescanning long messages), but not yet for error recovery.
Diffstat (limited to 'src/interfaces/libpq/fe-misc.c')
-rw-r--r--src/interfaces/libpq/fe-misc.c84
1 files changed, 72 insertions, 12 deletions
diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c
index dfc46fdf598..76de4a87086 100644
--- a/src/interfaces/libpq/fe-misc.c
+++ b/src/interfaces/libpq/fe-misc.c
@@ -23,7 +23,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.89 2003/04/19 00:02:30 tgl Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.90 2003/04/22 00:08:07 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -277,12 +277,12 @@ pqPutInt(int value, size_t bytes, PGconn *conn)
/*
* Make sure conn's output buffer can hold bytes_needed bytes (caller must
- * include existing outCount into the value!)
+ * include already-stored data into the value!)
*
- * Returns 0 on success, EOF on error
+ * Returns 0 on success, EOF if failed to enlarge buffer
*/
static int
-checkOutBufferSpace(int bytes_needed, PGconn *conn)
+pqCheckOutBufferSpace(int bytes_needed, PGconn *conn)
{
int newsize = conn->outBufSize;
char *newbuf;
@@ -336,6 +336,66 @@ checkOutBufferSpace(int bytes_needed, PGconn *conn)
}
/*
+ * Make sure conn's input buffer can hold bytes_needed bytes (caller must
+ * include already-stored data into the value!)
+ *
+ * Returns 0 on success, EOF if failed to enlarge buffer
+ */
+int
+pqCheckInBufferSpace(int bytes_needed, PGconn *conn)
+{
+ int newsize = conn->inBufSize;
+ char *newbuf;
+
+ if (bytes_needed <= newsize)
+ return 0;
+ /*
+ * If we need to enlarge the buffer, we first try to double it in size;
+ * if that doesn't work, enlarge in multiples of 8K. This avoids
+ * thrashing the malloc pool by repeated small enlargements.
+ *
+ * Note: tests for newsize > 0 are to catch integer overflow.
+ */
+ do {
+ newsize *= 2;
+ } while (bytes_needed > newsize && newsize > 0);
+
+ if (bytes_needed <= newsize)
+ {
+ newbuf = realloc(conn->inBuffer, newsize);
+ if (newbuf)
+ {
+ /* realloc succeeded */
+ conn->inBuffer = newbuf;
+ conn->inBufSize = newsize;
+ return 0;
+ }
+ }
+
+ newsize = conn->inBufSize;
+ do {
+ newsize += 8192;
+ } while (bytes_needed > newsize && newsize > 0);
+
+ if (bytes_needed <= newsize)
+ {
+ newbuf = realloc(conn->inBuffer, newsize);
+ if (newbuf)
+ {
+ /* realloc succeeded */
+ conn->inBuffer = newbuf;
+ conn->inBufSize = newsize;
+ return 0;
+ }
+ }
+
+ /* realloc failed. Probably out of memory */
+ printfPQExpBuffer(&conn->errorMessage,
+ "cannot allocate memory for input buffer\n");
+ return EOF;
+}
+
+/*
* pqPutMsgStart: begin construction of a message to the server
*
* msg_type is the message type byte, or 0 for a message without type byte
@@ -364,7 +424,7 @@ pqPutMsgStart(char msg_type, PGconn *conn)
else
lenPos = conn->outCount;
/* make sure there is room for it */
- if (checkOutBufferSpace(lenPos + 4, conn))
+ if (pqCheckOutBufferSpace(lenPos + 4, conn))
return EOF;
/* okay, save the message type byte if any */
if (msg_type)
@@ -390,7 +450,7 @@ static int
pqPutMsgBytes(const void *buf, size_t len, PGconn *conn)
{
/* make sure there is room for it */
- if (checkOutBufferSpace(conn->outMsgEnd + len, conn))
+ if (pqCheckOutBufferSpace(conn->outMsgEnd + len, conn))
return EOF;
/* okay, save the data */
memcpy(conn->outBuffer + conn->outMsgEnd, buf, len);
@@ -486,13 +546,13 @@ pqReadData(PGconn *conn)
*/
if (conn->inBufSize - conn->inEnd < 8192)
{
- int newSize = conn->inBufSize * 2;
- char *newBuf = (char *) realloc(conn->inBuffer, newSize);
-
- if (newBuf)
+ if (pqCheckInBufferSpace(conn->inEnd + 8192, conn))
{
- conn->inBuffer = newBuf;
- conn->inBufSize = newSize;
+ /*
+ * We don't insist that the enlarge worked, but we need some room
+ */
+ if (conn->inBufSize - conn->inEnd < 100)
+ return -1; /* errorMessage already set */
}
}