Expose PQsocketPoll via libpq
authorRobert Haas
Tue, 2 Apr 2024 14:15:56 +0000 (10:15 -0400)
committerRobert Haas
Tue, 2 Apr 2024 14:15:56 +0000 (10:15 -0400)
This is useful when connecting to a database asynchronously via
PQconnectStart(), since it handles deciding between poll() and
select(), and some of the required boilerplate.

Tristan Partin, reviewed by Gurjeet Singh, Heikki Linnakangas, Jelte
Fennema-Nio, and me.

Discussion: http://postgr.es/m/[email protected]

doc/src/sgml/libpq.sgml
src/interfaces/libpq/exports.txt
src/interfaces/libpq/fe-misc.c
src/interfaces/libpq/libpq-fe.h

index d3e87056f2cb05946361b55638808517b9f52688..e69feacfe6a6b8186fec2fdc8a30b52e33b496d1 100644 (file)
@@ -262,6 +262,41 @@ PGconn *PQsetdb(char *pghost,
      
     
 
+    
+     PQsocketPollPQsocketPoll
+     
+      
+       nonblocking connection
+       Poll a connection's underlying socket descriptor retrieved with .
+
+int PQsocketPoll(int sock, int forRead, int forWrite, time_t end_time);
+
+      
+
+      
+       This function sets up polling of a file descriptor. The underlying function is either
+       poll(2) or select(2), depending on platform
+       support. The primary use of this function is iterating through the connection sequence
+       described in the documentation of . If
+       forRead is specified, the function waits for the socket to be ready
+       for reading. If forWrite is specified, the function waits for the
+       socket to be ready for write. See POLLIN and POLLOUT
+       from poll(2), or readfds and
+       writefds from select(2) for more information. If
+       end_time is not -1, it specifies the time at which
+       this function should stop waiting for the condition to be met.
+      
+
+      
+       The function returns a value greater than 0 if the specified condition
+       is met, 0 if a timeout occurred, or -1 if an error
+       occurred. The error can be retrieved by checking the errno(3) value. In
+       the event forRead and forWrite are not set, the
+       function immediately returns a timeout condition.
+      
+     
+    
+
     
      PQconnectStartParamsPQconnectStartParams
      PQconnectStartPQconnectStart
@@ -358,7 +393,10 @@ PostgresPollingStatusType PQconnectPoll(PGconn *conn);
        Loop thus: If PQconnectPoll(conn) last returned
        PGRES_POLLING_READING, wait until the socket is ready to
        read (as indicated by select()poll(), or
-       similar system function).
+       similar system function).  Note that PQsocketPoll
+       can help reduce boilerplate by abstracting the setup of
+       select(2) or poll(2) if it is
+       available on your system.
        Then call PQconnectPoll(conn) again.
        Conversely, if PQconnectPoll(conn) last returned
        PGRES_POLLING_WRITING, wait until the socket is ready
index 9fbd3d34074f5201baa9632b51c91d948286dd1a..1e48d37677d71a86e4dfae56a314c7d7020ef579 100644 (file)
@@ -202,3 +202,4 @@ PQcancelSocket            199
 PQcancelErrorMessage      200
 PQcancelReset             201
 PQcancelFinish            202
+PQsocketPoll              203
index f2fc78a481c766956027db0ee889a44fd23441f9..f562cd8d34441465fa5d0ab7e4e985c2e468999e 100644 (file)
@@ -55,7 +55,6 @@ 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);
-static int pqSocketPoll(int sock, int forRead, int forWrite, time_t end_time);
 
 /*
  * PQlibVersion: return the libpq version number
@@ -1059,7 +1058,7 @@ pqSocketCheck(PGconn *conn, int forRead, int forWrite, time_t end_time)
 
    /* We will retry as long as we get EINTR */
    do
-       result = pqSocketPoll(conn->sock, forRead, forWrite, end_time);
+       result = PQsocketPoll(conn->sock, forRead, forWrite, end_time);
    while (result < 0 && SOCK_ERRNO == EINTR);
 
    if (result < 0)
@@ -1083,8 +1082,8 @@ pqSocketCheck(PGconn *conn, int forRead, int forWrite, time_t end_time)
  * Timeout is infinite if end_time is -1.  Timeout is immediate (no blocking)
  * if end_time is 0 (or indeed, any time before now).
  */
-static int
-pqSocketPoll(int sock, int forRead, int forWrite, time_t end_time)
+int
+PQsocketPoll(int sock, int forRead, int forWrite, time_t end_time)
 {
    /* We use poll(2) if available, otherwise select(2) */
 #ifdef HAVE_POLL
index 09b485bd2bc7f7c32065a67ec391c2a2de750945..8d3c5c6f66211dc359f110534efa88079b59e951 100644 (file)
@@ -21,6 +21,7 @@ extern "C"
 #endif
 
 #include 
+#include 
 
 /*
  * postgres_ext.h defines the backend's externally visible types,
@@ -670,6 +671,9 @@ extern int  lo_export(PGconn *conn, Oid lobjId, const char *filename);
 /* Get the version of the libpq library in use */
 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);
+
 /* Determine length of multibyte encoded char at *s */
 extern int PQmblen(const char *s, int encoding);