📄 pqcomm.c
字号:
(struct sockaddr *) & port->raddr, &addrlen)) < 0) { perror("postmaster: StreamConnection: accept"); return STATUS_ERROR; } /* fill in the server (local) address */ addrlen = sizeof(port->laddr); if (getsockname(port->sock, (struct sockaddr *) & port->laddr, &addrlen) < 0) { perror("postmaster: StreamConnection: getsockname"); return STATUS_ERROR; } /* select TCP_NODELAY option if it's a TCP connection */ if (port->laddr.sa.sa_family == AF_INET) { struct protoent *pe; int on = 1; pe = getprotobyname("TCP"); if (pe == NULL) { perror("postmaster: StreamConnection: getprotobyname"); return STATUS_ERROR; } if (setsockopt(port->sock, pe->p_proto, TCP_NODELAY, &on, sizeof(on)) < 0) { perror("postmaster: StreamConnection: setsockopt"); return STATUS_ERROR; } } /* reset to non-blocking */ fcntl(port->sock, F_SETFL, 1); return STATUS_OK;}/* * StreamClose -- close a client/backend connection */voidStreamClose(int sock){ close(sock);}/* -------------------------------- * Low-level I/O routines begin here. * * These routines communicate with a frontend client across a connection * already established by the preceding routines. * -------------------------------- *//* -------------------------------- * pq_recvbuf - load some bytes into the input buffer * * returns 0 if OK, EOF if trouble * -------------------------------- */static intpq_recvbuf(void){ if (PqRecvPointer > 0) { if (PqRecvLength > PqRecvPointer) { /* still some unread data, left-justify it in the buffer */ memmove(PqRecvBuffer, PqRecvBuffer + PqRecvPointer, PqRecvLength - PqRecvPointer); PqRecvLength -= PqRecvPointer; PqRecvPointer = 0; } else PqRecvLength = PqRecvPointer = 0; } /* Can fill buffer from PqRecvLength and upwards */ for (;;) { int r = recv(MyProcPort->sock, PqRecvBuffer + PqRecvLength, PQ_BUFFER_SIZE - PqRecvLength, 0); if (r < 0) { if (errno == EINTR) continue; /* Ok if interrupted */ /* * We would like to use elog() here, but dare not because elog * tries to write to the client, which will cause problems if * we have a hard communications failure ... So just write the * message to the postmaster log. */ fprintf(stderr, "pq_recvbuf: recv() failed: %s\n", strerror(errno)); return EOF; } if (r == 0) { /* as above, elog not safe */ fprintf(stderr, "pq_recvbuf: unexpected EOF on client connection\n"); return EOF; } /* r contains number of bytes read, so just incr length */ PqRecvLength += r; return 0; }}/* -------------------------------- * pq_getbyte - get a single byte from connection, or return EOF * -------------------------------- */static intpq_getbyte(void){ while (PqRecvPointer >= PqRecvLength) { if (pq_recvbuf()) /* If nothing in buffer, then recv some */ return EOF; /* Failed to recv data */ } return PqRecvBuffer[PqRecvPointer++];}/* -------------------------------- * pq_peekbyte - peek at next byte from connection * * Same as pq_getbyte() except we don't advance the pointer. * -------------------------------- */intpq_peekbyte(void){ while (PqRecvPointer >= PqRecvLength) { if (pq_recvbuf()) /* If nothing in buffer, then recv some */ return EOF; /* Failed to recv data */ } return PqRecvBuffer[PqRecvPointer];}/* -------------------------------- * pq_getbytes - get a known number of bytes from connection * * returns 0 if OK, EOF if trouble * -------------------------------- */intpq_getbytes(char *s, size_t len){ size_t amount; while (len > 0) { while (PqRecvPointer >= PqRecvLength) { if (pq_recvbuf()) /* If nothing in buffer, then recv some */ return EOF; /* Failed to recv data */ } amount = PqRecvLength - PqRecvPointer; if (amount > len) amount = len; memcpy(s, PqRecvBuffer + PqRecvPointer, amount); PqRecvPointer += amount; s += amount; len -= amount; } return 0;}/* -------------------------------- * pq_getstring - get a null terminated string from connection * * NOTE: this routine does not do any MULTIBYTE conversion, * even though it is presumably useful only for text, because * no code in this module should depend on MULTIBYTE mode. * See pq_getstr in pqformat.c for that. * * FIXME: we ought to use an expansible StringInfo buffer, * rather than dropping data if the message is too long. * * returns 0 if OK, EOF if trouble * -------------------------------- */intpq_getstring(char *s, size_t len){ int c; /* * Keep on reading until we get the terminating '\0', discarding any * bytes we don't have room for. */ while ((c = pq_getbyte()) != EOF && c != '\0') { if (len > 1) { *s++ = c; len--; } } *s = '\0'; if (c == EOF) return EOF; return 0;}/* -------------------------------- * pq_putbytes - send bytes to connection (not flushed until pq_flush) * * returns 0 if OK, EOF if trouble * -------------------------------- */intpq_putbytes(const char *s, size_t len){ size_t amount; while (len > 0) { if (PqSendPointer >= PQ_BUFFER_SIZE) if (pq_flush()) /* If buffer is full, then flush it out */ return EOF; amount = PQ_BUFFER_SIZE - PqSendPointer; if (amount > len) amount = len; memcpy(PqSendBuffer + PqSendPointer, s, amount); PqSendPointer += amount; s += amount; len -= amount; } return 0;}/* -------------------------------- * pq_flush - flush pending output * * returns 0 if OK, EOF if trouble * -------------------------------- */intpq_flush(void){ unsigned char *bufptr = PqSendBuffer; unsigned char *bufend = PqSendBuffer + PqSendPointer; while (bufptr < bufend) { int r = send(MyProcPort->sock, bufptr, bufend - bufptr, 0); if (r <= 0) { if (errno == EINTR) continue; /* Ok if we were interrupted */ /* * We would like to use elog() here, but cannot because elog * tries to write to the client, which would cause a recursive * flush attempt! So just write it out to the postmaster log. */ fprintf(stderr, "pq_flush: send() failed: %s\n", strerror(errno)); /* * We drop the buffered data anyway so that processing can * continue, even though we'll probably quit soon. */ PqSendPointer = 0; return EOF; } bufptr += r; } PqSendPointer = 0; return 0;}/* -------------------------------- * Message-level I/O routines begin here. * * These routines understand about COPY OUT protocol. * -------------------------------- *//* -------------------------------- * pq_putmessage - send a normal message (suppressed in COPY OUT mode) * * If msgtype is not '\0', it is a message type code to place before * the message body (len counts only the body size!). * If msgtype is '\0', then the buffer already includes the type code. * * All normal messages are suppressed while COPY OUT is in progress. * (In practice only NOTICE messages might get emitted then; dropping * them is annoying, but at least they will still appear in the * postmaster log.) * * returns 0 if OK, EOF if trouble * -------------------------------- */intpq_putmessage(char msgtype, const char *s, size_t len){ if (DoingCopyOut) return 0; if (msgtype) if (pq_putbytes(&msgtype, 1)) return EOF; return pq_putbytes(s, len);}/* -------------------------------- * pq_startcopyout - inform libpq that a COPY OUT transfer is beginning * -------------------------------- */voidpq_startcopyout(void){ DoingCopyOut = true;}/* -------------------------------- * pq_endcopyout - end a COPY OUT transfer * * If errorAbort is indicated, we are aborting a COPY OUT due to an error, * and must send a terminator line. Since a partial data line might have * been emitted, send a couple of newlines first (the first one could * get absorbed by a backslash...) * -------------------------------- */voidpq_endcopyout(bool errorAbort){ if (!DoingCopyOut) return; if (errorAbort) pq_putbytes("\n\n\\.\n", 5); /* in non-error case, copy.c will have emitted the terminator line */ DoingCopyOut = false;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -