*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.191 2002/08/15 02:56:19 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-connect.c,v 1.192 2002/08/17 12:33:17 momjian Exp $
*
*-------------------------------------------------------------------------
*/
{"password", "PGPASSWORD", DefaultPassword, NULL,
"Database-Password", "*", 20},
+ {"connect_timeout", "PGCONNECT_TIMEOUT", NULL, NULL,
+ "Connect-timeout", "", 10}, /* strlen( INT32_MAX) == 10 */
+
{"dbname", "PGDATABASE", NULL, NULL,
"Database-Name", "", 20},
conn->pguser = tmp ? strdup(tmp) : NULL;
tmp = conninfo_getval(connOptions, "password");
conn->pgpass = tmp ? strdup(tmp) : NULL;
+ tmp = conninfo_getval(connOptions, "connect_timeout");
+ conn->connect_timeout = tmp ? strdup(tmp) : NULL;
#ifdef USE_SSL
tmp = conninfo_getval(connOptions, "requiressl");
if (tmp && tmp[0] == '1')
{
PostgresPollingStatusType flag = PGRES_POLLING_WRITING;
+ struct timeval remains, *rp = NULL, finish_time, start_time;
+
if (conn == NULL || conn->status == CONNECTION_BAD)
return 0;
- for (;;)
+ /*
+ * Prepare to time calculations, if connect_timeout isn't zero.
+ */
+ if (conn->connect_timeout != NULL)
{
+ remains.tv_sec = atoi(conn->connect_timeout);
+ if (!remains.tv_sec)
+ {
+ conn->status = CONNECTION_BAD;
+ return 0;
+ }
+ remains.tv_usec = 0;
+ rp = &remains;
+ }
+
+
+ while (NULL == rp || remains.tv_sec > 0 || remains.tv_sec == 0 && remains.tv_usec > 0)
+ {
/*
+ * If connecting timeout is set, get current time.
+ */
+ if ( NULL != rp && -1 == gettimeofday(&start_time, NULL))
+ {
+ conn->status = CONNECTION_BAD;
+ return 0;
+ }
+
+ /*
* Wait, if necessary. Note that the initial state (just after
* PQconnectStart) is to wait for the socket to select for
* writing.
return 1; /* success! */
case PGRES_POLLING_READING:
- if (pqWait(1, 0, conn))
+ if (pqWaitTimed(1, 0, conn, rp))
{
conn->status = CONNECTION_BAD;
return 0;
break;
case PGRES_POLLING_WRITING:
- if (pqWait(0, 1, conn))
+ if (pqWaitTimed(0, 1, conn, rp))
{
conn->status = CONNECTION_BAD;
return 0;
* Now try to advance the state machine.
*/
flag = PQconnectPoll(conn);
+
+ /*
+ * If connecting timeout is set, calculate remain time.
+ */
+ if (NULL != rp) {
+ if (-1 == gettimeofday(&finish_time, NULL))
+ {
+ conn->status = CONNECTION_BAD;
+ return 0;
+ }
+ if (0 > (finish_time.tv_usec -= start_time.tv_usec))
+ {
+ remains.tv_sec++;
+ finish_time.tv_usec += 1000000;
+ }
+ if (0 > (remains.tv_usec -= finish_time.tv_usec))
+ {
+ remains.tv_sec--;
+ remains.tv_usec += 1000000;
+ }
+ remains.tv_sec -= finish_time.tv_sec - start_time.tv_sec;
+ }
}
+ conn->status = CONNECTION_BAD;
+ return 0;
}
/* ----------------
free(conn->pguser);
if (conn->pgpass)
free(conn->pgpass);
+ if (conn->connect_timeout)
+ free(conn->connect_timeout);
/* Note that conn->Pfdebug is not ours to close or free */
if (conn->notifyList)
DLFreeList(conn->notifyList);
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.76 2002/06/20 20:29:54 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/interfaces/libpq/fe-misc.c,v 1.77 2002/08/17 12:33:18 momjian Exp $
*
*-------------------------------------------------------------------------
*/
int
pqWait(int forRead, int forWrite, PGconn *conn)
{
+ return pqWaitTimed( forRead, forWrite, conn, (const struct timeval *) NULL);
+}
+
+int
+pqWaitTimed(int forRead, int forWrite, PGconn *conn, const struct timeval *timeout)
+{
fd_set input_mask;
fd_set output_mask;
fd_set except_mask;
+ struct timeval tmp_timeout;
+ struct timeval *ptmp_timeout = NULL;
+
if (conn->sock < 0)
{
printfPQExpBuffer(&conn->errorMessage,
if (forWrite)
FD_SET(conn->sock, &output_mask);
FD_SET(conn->sock, &except_mask);
- if (select(conn->sock + 1, &input_mask, &output_mask, &except_mask,
- (struct timeval *) NULL) < 0)
+
+ if (NULL != timeout)
{
+ /*
+ * select may modify timeout argument on some platforms use copy
+ */
+ tmp_timeout = *timeout;
+ ptmp_timeout = &tmp_timeout;
+ }
+ if (select(conn->sock + 1, &input_mask, &output_mask,
+ &except_mask, ptmp_timeout) < 0)
+ {
if (SOCK_ERRNO == EINTR)
goto retry5;
printfPQExpBuffer(&conn->errorMessage,
* Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $Id: libpq-int.h,v 1.52 2002/07/20 05:43:31 momjian Exp $
+ * $Id: libpq-int.h,v 1.53 2002/08/17 12:33:18 momjian Exp $
*
*-------------------------------------------------------------------------
*/
PQExpBufferData workBuffer; /* expansible string */
int client_encoding; /* encoding id */
+
+ char *connect_timeout;
};
/* String descriptions of the ExecStatusTypes.
extern int pqFlush(PGconn *conn);
extern int pqSendSome(PGconn *conn);
extern int pqWait(int forRead, int forWrite, PGconn *conn);
+extern int pqWaitTimed(int forRead, int forWrite, PGconn *conn, const struct timeval* timeout);
extern int pqReadReady(PGconn *conn);
extern int pqWriteReady(PGconn *conn);