📄 fe-connect.c
字号:
* PQrequestCancel: attempt to request cancellation of the current operation. * * The return value is TRUE if the cancel request was successfully * dispatched, FALSE if not (in which case errorMessage is set). * Note: successful dispatch is no guarantee that there will be any effect at * the backend. The application must read the operation result as usual. * * CAUTION: we want this routine to be safely callable from a signal handler * (for example, an application might want to call it in a SIGINT handler). * This means we cannot use any C library routine that might be non-reentrant. * malloc/free are often non-reentrant, and anything that might call them is * just as dangerous. We avoid sprintf here for that reason. Building up * error messages with strcpy/strcat is tedious but should be quite safe. */intPQrequestCancel(PGconn *conn){ int tmpsock = -1; struct { uint32 packetlen; CancelRequestPacket cp; } crp; /* Check we have an open connection */ if (!conn) return FALSE; if (conn->sock < 0) { strcpy(conn->errorMessage, "PQrequestCancel() -- connection is not open\n"); return FALSE; } /* * We need to open a temporary connection to the postmaster. Use the * information saved by connectDB to do this with only kernel calls. */ if ((tmpsock = socket(conn->raddr.sa.sa_family, SOCK_STREAM, 0)) < 0) { strcpy(conn->errorMessage, "PQrequestCancel() -- socket() failed: "); goto cancel_errReturn; } if (connect(tmpsock, &conn->raddr.sa, conn->raddr_len) < 0) { strcpy(conn->errorMessage, "PQrequestCancel() -- connect() failed: "); goto cancel_errReturn; } /* * We needn't set nonblocking I/O or NODELAY options here. */ /* Create and send the cancel request packet. */ crp.packetlen = htonl((uint32) sizeof(crp)); crp.cp.cancelRequestCode = (MsgType) htonl(CANCEL_REQUEST_CODE); crp.cp.backendPID = htonl(conn->be_pid); crp.cp.cancelAuthCode = htonl(conn->be_key); if (send(tmpsock, (char *) &crp, sizeof(crp), 0) != (int) sizeof(crp)) { strcpy(conn->errorMessage, "PQrequestCancel() -- send() failed: "); goto cancel_errReturn; } /* Sent it, done */#ifdef WIN32 closesocket(tmpsock);#else close(tmpsock);#endif return TRUE;cancel_errReturn: strcat(conn->errorMessage, strerror(errno)); strcat(conn->errorMessage, "\n"); if (tmpsock >= 0) {#ifdef WIN32 closesocket(tmpsock);#else close(tmpsock);#endif } return FALSE;}/* * pqPacketSend() -- send a single-packet message. * this is like PacketSend(), defined in backend/libpq/pqpacket.c * * RETURNS: STATUS_ERROR if the write fails, STATUS_OK otherwise. * SIDE_EFFECTS: may block.*/intpqPacketSend(PGconn *conn, const char *buf, size_t len){ /* Send the total packet size. */ if (pqPutInt(4 + len, 4, conn)) return STATUS_ERROR; /* Send the packet itself. */ if (pqPutnchar(buf, len, conn)) return STATUS_ERROR; if (pqFlush(conn)) return STATUS_ERROR; return STATUS_OK;}/* ---------------- * Conninfo parser routine * ---------------- */static intconninfo_parse(const char *conninfo, char *errorMessage){ char *pname; char *pval; char *buf; char *tmp; char *cp; char *cp2; PQconninfoOption *option; char errortmp[ERROR_MSG_LENGTH]; conninfo_free(); if ((buf = strdup(conninfo)) == NULL) { strcpy(errorMessage, "FATAL: cannot allocate memory for copy of conninfo string\n"); return -1; } cp = buf; while (*cp) { /* Skip blanks before the parameter name */ if (isspace(*cp)) { cp++; continue; } /* Get the parameter name */ pname = cp; while (*cp) { if (*cp == '=') break; if (isspace(*cp)) { *cp++ = '\0'; while (*cp) { if (!isspace(*cp)) break; cp++; } break; } cp++; } /* Check that there is a following '=' */ if (*cp != '=') { sprintf(errorMessage, "ERROR: PQconnectdb() - Missing '=' after '%s' in conninfo\n", pname); free(buf); return -1; } *cp++ = '\0'; /* Skip blanks after the '=' */ while (*cp) { if (!isspace(*cp)) break; cp++; } pval = cp; if (*cp != '\'') { cp2 = pval; while (*cp) { if (isspace(*cp)) { *cp++ = '\0'; break; } if (*cp == '\\') { cp++; if (*cp != '\0') *cp2++ = *cp++; } else *cp2++ = *cp++; } *cp2 = '\0'; } else { cp2 = pval; cp++; for (;;) { if (*cp == '\0') { sprintf(errorMessage, "ERROR: PQconnectdb() - unterminated quoted string in conninfo\n"); free(buf); return -1; } if (*cp == '\\') { cp++; if (*cp != '\0') *cp2++ = *cp++; continue; } if (*cp == '\'') { *cp2 = '\0'; cp++; break; } *cp2++ = *cp++; } } /* ---------- * Now we have the name and the value. Search * for the param record. * ---------- */ for (option = PQconninfoOptions; option->keyword != NULL; option++) { if (!strcmp(option->keyword, pname)) break; } if (option->keyword == NULL) { sprintf(errorMessage, "ERROR: PQconnectdb() - unknown option '%s'\n", pname); free(buf); return -1; } /* ---------- * Store the value * ---------- */ option->val = strdup(pval); } free(buf); /* ---------- * Get the fallback resources for parameters not specified * in the conninfo string. * ---------- */ for (option = PQconninfoOptions; option->keyword != NULL; option++) { if (option->val != NULL) continue; /* Value was in conninfo */ /* ---------- * Try to get the environment variable fallback * ---------- */ if (option->envvar != NULL) { if ((tmp = getenv(option->envvar)) != NULL) { option->val = strdup(tmp); continue; } } /* ---------- * No environment variable specified or this one isn't set - * try compiled in * ---------- */ if (option->compiled != NULL) { option->val = strdup(option->compiled); continue; } /* ---------- * Special handling for user * ---------- */ if (!strcmp(option->keyword, "user")) { option->val = fe_getauthname(errortmp); continue; } /* ---------- * Special handling for dbname * ---------- */ if (!strcmp(option->keyword, "dbname")) { tmp = conninfo_getval("user"); if (tmp) option->val = strdup(tmp); continue; } } return 0;}static char *conninfo_getval(char *keyword){ PQconninfoOption *option; for (option = PQconninfoOptions; option->keyword != NULL; option++) { if (!strcmp(option->keyword, keyword)) return option->val; } return NULL;}static voidconninfo_free(){ PQconninfoOption *option; for (option = PQconninfoOptions; option->keyword != NULL; option++) { if (option->val != NULL) { free(option->val); option->val = NULL; } }}/* =========== accessor functions for PGconn ========= */char *PQdb(PGconn *conn){ if (!conn) return (char *) NULL; return conn->dbName;}char *PQuser(PGconn *conn){ if (!conn) return (char *) NULL; return conn->pguser;}char *PQpass(PGconn *conn){ if (!conn) return (char *) NULL; return conn->pgpass;}char *PQhost(PGconn *conn){ if (!conn) return (char *) NULL; return conn->pghost;}char *PQport(PGconn *conn){ if (!conn) return (char *) NULL; return conn->pgport;}char *PQtty(PGconn *conn){ if (!conn) return (char *) NULL; return conn->pgtty;}char *PQoptions(PGconn *conn){ if (!conn) return (char *) NULL; return conn->pgoptions;}ConnStatusTypePQstatus(PGconn *conn){ if (!conn) return CONNECTION_BAD; return conn->status;}char *PQerrorMessage(PGconn *conn){ static char noConn[] = "PQerrorMessage: conn pointer is NULL\n"; if (!conn) return noConn; return conn->errorMessage;}intPQsocket(PGconn *conn){ if (!conn) return -1; return conn->sock;}intPQbackendPID(PGconn *conn){ if (!conn || conn->status != CONNECTION_OK) return 0; return conn->be_pid;}voidPQtrace(PGconn *conn, FILE *debug_port){ if (conn == NULL || conn->status == CONNECTION_BAD) return; PQuntrace(conn); conn->Pfdebug = debug_port;}voidPQuntrace(PGconn *conn){ /* note: better allow untrace even when connection bad */ if (conn == NULL) return; if (conn->Pfdebug) { fflush(conn->Pfdebug); conn->Pfdebug = NULL; }}voidPQsetNoticeProcessor(PGconn *conn, PQnoticeProcessor proc, void *arg){ if (conn == NULL) return; conn->noticeHook = proc; conn->noticeArg = arg;}/* * The default notice/error message processor just prints the * message on stderr. Applications can override this if they * want the messages to go elsewhere (a window, for example). * Note that simply discarding notices is probably a bad idea. */static voiddefaultNoticeProcessor(void *arg, const char *message){ /* Note: we expect the supplied string to end with a newline already. */ fprintf(stderr, "%s", message);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -