aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bin/psql/command.c4
-rw-r--r--src/interfaces/libpq/exports.txt1
-rw-r--r--src/interfaces/libpq/fe-connect.c23
-rw-r--r--src/interfaces/libpq/fe-misc.c69
-rw-r--r--src/interfaces/libpq/libpq-fe.h10
-rw-r--r--src/interfaces/libpq/libpq-int.h2
-rw-r--r--src/tools/pgindent/typedefs.list1
7 files changed, 69 insertions, 41 deletions
diff --git a/src/bin/psql/command.c b/src/bin/psql/command.c
index fae5940b54e..180781ecd05 100644
--- a/src/bin/psql/command.c
+++ b/src/bin/psql/command.c
@@ -3764,7 +3764,7 @@ wait_until_connected(PGconn *conn)
{
int rc;
int sock;
- time_t end_time;
+ pg_usec_time_t end_time;
/*
* On every iteration of the connection sequence, let's check if the
@@ -3795,7 +3795,7 @@ wait_until_connected(PGconn *conn)
* solution happens to just be adding a timeout, so let's wait for 1
* second and check cancel_pressed again.
*/
- end_time = time(NULL) + 1;
+ end_time = PQgetCurrentTimeUSec() + 1000000;
rc = PQsocketPoll(sock, forRead, !forRead, end_time);
if (rc == -1)
return;
diff --git a/src/interfaces/libpq/exports.txt b/src/interfaces/libpq/exports.txt
index 8ee08115100..5d8213e0b57 100644
--- a/src/interfaces/libpq/exports.txt
+++ b/src/interfaces/libpq/exports.txt
@@ -204,3 +204,4 @@ PQcancelReset 201
PQcancelFinish 202
PQsocketPoll 203
PQsetChunkedRowsMode 204
+PQgetCurrentTimeUSec 205
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 90f259fc706..071b1b34aa1 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -2470,7 +2470,7 @@ int
pqConnectDBComplete(PGconn *conn)
{
PostgresPollingStatusType flag = PGRES_POLLING_WRITING;
- time_t finish_time = ((time_t) -1);
+ pg_usec_time_t end_time = -1;
int timeout = 0;
int last_whichhost = -2; /* certainly different from whichhost */
int last_whichaddr = -2; /* certainly different from whichaddr */
@@ -2479,7 +2479,7 @@ pqConnectDBComplete(PGconn *conn)
return 0;
/*
- * Set up a time limit, if connect_timeout isn't zero.
+ * Set up a time limit, if connect_timeout is greater than zero.
*/
if (conn->connect_timeout != NULL)
{
@@ -2490,19 +2490,6 @@ pqConnectDBComplete(PGconn *conn)
conn->status = CONNECTION_BAD;
return 0;
}
-
- if (timeout > 0)
- {
- /*
- * Rounding could cause connection to fail unexpectedly quickly;
- * to prevent possibly waiting hardly-at-all, insist on at least
- * two seconds.
- */
- if (timeout < 2)
- timeout = 2;
- }
- else /* negative means 0 */
- timeout = 0;
}
for (;;)
@@ -2519,7 +2506,7 @@ pqConnectDBComplete(PGconn *conn)
(conn->whichhost != last_whichhost ||
conn->whichaddr != last_whichaddr))
{
- finish_time = time(NULL) + timeout;
+ end_time = PQgetCurrentTimeUSec() + (pg_usec_time_t) timeout * 1000000;
last_whichhost = conn->whichhost;
last_whichaddr = conn->whichaddr;
}
@@ -2534,7 +2521,7 @@ pqConnectDBComplete(PGconn *conn)
return 1; /* success! */
case PGRES_POLLING_READING:
- ret = pqWaitTimed(1, 0, conn, finish_time);
+ ret = pqWaitTimed(1, 0, conn, end_time);
if (ret == -1)
{
/* hard failure, eg select() problem, aborts everything */
@@ -2544,7 +2531,7 @@ pqConnectDBComplete(PGconn *conn)
break;
case PGRES_POLLING_WRITING:
- ret = pqWaitTimed(0, 1, conn, finish_time);
+ ret = pqWaitTimed(0, 1, conn, end_time);
if (ret == -1)
{
/* hard failure, eg select() problem, aborts everything */
diff --git a/src/interfaces/libpq/fe-misc.c b/src/interfaces/libpq/fe-misc.c
index f562cd8d344..f235bfbb41f 100644
--- a/src/interfaces/libpq/fe-misc.c
+++ b/src/interfaces/libpq/fe-misc.c
@@ -54,7 +54,7 @@
static int pqPutMsgBytes(const void *buf, size_t len, PGconn *conn);
static int pqSendSome(PGconn *conn, int len);
static int pqSocketCheck(PGconn *conn, int forRead, int forWrite,
- time_t end_time);
+ pg_usec_time_t end_time);
/*
* PQlibVersion: return the libpq version number
@@ -977,22 +977,25 @@ pqFlush(PGconn *conn)
int
pqWait(int forRead, int forWrite, PGconn *conn)
{
- return pqWaitTimed(forRead, forWrite, conn, (time_t) -1);
+ return pqWaitTimed(forRead, forWrite, conn, -1);
}
/*
- * pqWaitTimed: wait, but not past finish_time.
- *
- * finish_time = ((time_t) -1) disables the wait limit.
+ * pqWaitTimed: wait, but not past end_time.
*
* Returns -1 on failure, 0 if the socket is readable/writable, 1 if it timed out.
+ *
+ * The timeout is specified by end_time, which is the int64 number of
+ * microseconds since the Unix epoch (that is, time_t times 1 million).
+ * Timeout is infinite if end_time is -1. Timeout is immediate (no blocking)
+ * if end_time is 0 (or indeed, any time before now).
*/
int
-pqWaitTimed(int forRead, int forWrite, PGconn *conn, time_t finish_time)
+pqWaitTimed(int forRead, int forWrite, PGconn *conn, pg_usec_time_t end_time)
{
int result;
- result = pqSocketCheck(conn, forRead, forWrite, finish_time);
+ result = pqSocketCheck(conn, forRead, forWrite, end_time);
if (result < 0)
return -1; /* errorMessage is already set */
@@ -1013,7 +1016,7 @@ pqWaitTimed(int forRead, int forWrite, PGconn *conn, time_t finish_time)
int
pqReadReady(PGconn *conn)
{
- return pqSocketCheck(conn, 1, 0, (time_t) 0);
+ return pqSocketCheck(conn, 1, 0, 0);
}
/*
@@ -1023,7 +1026,7 @@ pqReadReady(PGconn *conn)
int
pqWriteReady(PGconn *conn)
{
- return pqSocketCheck(conn, 0, 1, (time_t) 0);
+ return pqSocketCheck(conn, 0, 1, 0);
}
/*
@@ -1035,7 +1038,7 @@ pqWriteReady(PGconn *conn)
* for read data directly.
*/
static int
-pqSocketCheck(PGconn *conn, int forRead, int forWrite, time_t end_time)
+pqSocketCheck(PGconn *conn, int forRead, int forWrite, pg_usec_time_t end_time)
{
int result;
@@ -1079,11 +1082,13 @@ pqSocketCheck(PGconn *conn, int forRead, int forWrite, time_t end_time)
* condition (without waiting). Return >0 if condition is met, 0
* if a timeout occurred, -1 if an error or interrupt occurred.
*
+ * The timeout is specified by end_time, which is the int64 number of
+ * microseconds since the Unix epoch (that is, time_t times 1 million).
* Timeout is infinite if end_time is -1. Timeout is immediate (no blocking)
* if end_time is 0 (or indeed, any time before now).
*/
int
-PQsocketPoll(int sock, int forRead, int forWrite, time_t end_time)
+PQsocketPoll(int sock, int forRead, int forWrite, pg_usec_time_t end_time)
{
/* We use poll(2) if available, otherwise select(2) */
#ifdef HAVE_POLL
@@ -1103,14 +1108,16 @@ PQsocketPoll(int sock, int forRead, int forWrite, time_t end_time)
input_fd.events |= POLLOUT;
/* Compute appropriate timeout interval */
- if (end_time == ((time_t) -1))
+ if (end_time == -1)
timeout_ms = -1;
+ else if (end_time == 0)
+ timeout_ms = 0;
else
{
- time_t now = time(NULL);
+ pg_usec_time_t now = PQgetCurrentTimeUSec();
if (end_time > now)
- timeout_ms = (end_time - now) * 1000;
+ timeout_ms = (end_time - now) / 1000;
else
timeout_ms = 0;
}
@@ -1138,17 +1145,28 @@ PQsocketPoll(int sock, int forRead, int forWrite, time_t end_time)
FD_SET(sock, &except_mask);
/* Compute appropriate timeout interval */
- if (end_time == ((time_t) -1))
+ if (end_time == -1)
ptr_timeout = NULL;
+ else if (end_time == 0)
+ {
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 0;
+ ptr_timeout = &timeout;
+ }
else
{
- time_t now = time(NULL);
+ pg_usec_time_t now = PQgetCurrentTimeUSec();
if (end_time > now)
- timeout.tv_sec = end_time - now;
+ {
+ timeout.tv_sec = (end_time - now) / 1000000;
+ timeout.tv_usec = (end_time - now) % 1000000;
+ }
else
+ {
timeout.tv_sec = 0;
- timeout.tv_usec = 0;
+ timeout.tv_usec = 0;
+ }
ptr_timeout = &timeout;
}
@@ -1157,6 +1175,21 @@ PQsocketPoll(int sock, int forRead, int forWrite, time_t end_time)
#endif /* HAVE_POLL */
}
+/*
+ * PQgetCurrentTimeUSec: get current time with microsecond precision
+ *
+ * This provides a platform-independent way of producing a reference
+ * value for PQsocketPoll's timeout parameter.
+ */
+pg_usec_time_t
+PQgetCurrentTimeUSec(void)
+{
+ struct timeval tval;
+
+ gettimeofday(&tval, NULL);
+ return (pg_usec_time_t) tval.tv_sec * 1000000 + tval.tv_usec;
+}
+
/*
* A couple of "miscellaneous" multibyte related functions. They used
diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h
index 73f6e65ae55..87a6f3df074 100644
--- a/src/interfaces/libpq/libpq-fe.h
+++ b/src/interfaces/libpq/libpq-fe.h
@@ -21,7 +21,6 @@ extern "C"
#endif
#include <stdio.h>
-#include <time.h>
/*
* postgres_ext.h defines the backend's externally visible types,
@@ -202,6 +201,9 @@ typedef struct pgNotify
struct pgNotify *next; /* list link */
} PGnotify;
+/* pg_usec_time_t is like time_t, but with microsecond resolution */
+typedef pg_int64 pg_usec_time_t;
+
/* Function types for notice-handling callbacks */
typedef void (*PQnoticeReceiver) (void *arg, const PGresult *res);
typedef void (*PQnoticeProcessor) (void *arg, const char *message);
@@ -673,7 +675,11 @@ extern int lo_export(PGconn *conn, Oid lobjId, const char *filename);
extern int PQlibVersion(void);
/* Poll a socket for reading and/or writing with an optional timeout */
-extern int PQsocketPoll(int sock, int forRead, int forWrite, time_t end_time);
+extern int PQsocketPoll(int sock, int forRead, int forWrite,
+ pg_usec_time_t end_time);
+
+/* Get current time in the form PQsocketPoll wants */
+extern pg_usec_time_t PQgetCurrentTimeUSec(void);
/* Determine length of multibyte encoded char at *s */
extern int PQmblen(const char *s, int encoding);
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 3886204c708..f36d76bf3fe 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -755,7 +755,7 @@ extern int pqReadData(PGconn *conn);
extern int pqFlush(PGconn *conn);
extern int pqWait(int forRead, int forWrite, PGconn *conn);
extern int pqWaitTimed(int forRead, int forWrite, PGconn *conn,
- time_t finish_time);
+ pg_usec_time_t end_time);
extern int pqReadReady(PGconn *conn);
extern int pqWriteReady(PGconn *conn);
diff --git a/src/tools/pgindent/typedefs.list b/src/tools/pgindent/typedefs.list
index 4f57078d133..61ad417cde6 100644
--- a/src/tools/pgindent/typedefs.list
+++ b/src/tools/pgindent/typedefs.list
@@ -3717,6 +3717,7 @@ pg_unicode_normprops
pg_unicode_properties
pg_unicode_range
pg_unicode_recompinfo
+pg_usec_time_t
pg_utf_to_local_combined
pg_uuid_t
pg_wc_probefunc