From a30a93319d5ada7928603553a1d82bb1f8409647 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Sat, 8 Feb 2020 09:01:19 +1300
Subject: [PATCH 4/5] libpq: Add PQsocketChangeCount to advertise socket
 changes.

Users of PQsocket() sometimes wish they could know when the
socket changes between calls, to allow for reuse of wait
event sets.  Provide a new function PQsocketChangeCount()
that advances whenever libpq opens or closes a socket.
---
 doc/src/sgml/libpq.sgml           | 17 +++++++++++++++++
 src/interfaces/libpq/exports.txt  |  1 +
 src/interfaces/libpq/fe-connect.c | 10 ++++++++++
 src/interfaces/libpq/libpq-fe.h   |  1 +
 src/interfaces/libpq/libpq-int.h  |  1 +
 5 files changed, 30 insertions(+)

diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml
index 9a24c19ccb..14f0d998b6 100644
--- a/doc/src/sgml/libpq.sgml
+++ b/doc/src/sgml/libpq.sgml
@@ -2280,6 +2280,23 @@ int PQsocket(const PGconn *conn);
      </listitem>
     </varlistentry>
 
+    <varlistentry id="libpq-PQsocketChangeCount">
+     <term><function>PQsocketChangeCount</function><indexterm><primary>PQsocketChangeCount</primary></indexterm></term>
+     <listitem>
+      <para>
+       Returns a counter that increases whenever the socket has changed.
+       This can be used to know when the value returned by
+       <xref linkend="libpq-PQsocket"/> represents a different socket, even
+       if it happens to have the same file descriptor number.
+
+<synopsis>
+pg_int64 PQsocketChangeCount(const PGconn *conn);
+</synopsis>
+
+      </para>
+     </listitem>
+    </varlistentry>
+
     <varlistentry id="libpq-PQbackendPID">
      <term><function>PQbackendPID</function><indexterm><primary>PQbackendPID</primary></indexterm></term>
      <listitem>
diff --git a/src/interfaces/libpq/exports.txt b/src/interfaces/libpq/exports.txt
index 5fc1e5d289..e925ea320f 100644
--- a/src/interfaces/libpq/exports.txt
+++ b/src/interfaces/libpq/exports.txt
@@ -179,3 +179,4 @@ PQgetgssctx               176
 PQsetSSLKeyPassHook		  177
 PQgetSSLKeyPassHook		  178
 PQdefaultSSLKeyPassHook	  179
+PQsocketChangeCount       180
diff --git a/src/interfaces/libpq/fe-connect.c b/src/interfaces/libpq/fe-connect.c
index 408000af83..dff73f1784 100644
--- a/src/interfaces/libpq/fe-connect.c
+++ b/src/interfaces/libpq/fe-connect.c
@@ -464,6 +464,7 @@ pqDropConnection(PGconn *conn, bool flushInput)
 	if (conn->sock != PGINVALID_SOCKET)
 		closesocket(conn->sock);
 	conn->sock = PGINVALID_SOCKET;
+	conn->sockChangeCount++;
 
 	/* Optionally discard any unread data */
 	if (flushInput)
@@ -2538,6 +2539,7 @@ keep_going:						/* We will come back to here until there is
 					 */
 
 					conn->sock = socket(addr_cur->ai_family, SOCK_STREAM, 0);
+					conn->sockChangeCount++;
 					if (conn->sock == PGINVALID_SOCKET)
 					{
 						/*
@@ -6706,6 +6708,14 @@ PQsocket(const PGconn *conn)
 	return (conn->sock != PGINVALID_SOCKET) ? conn->sock : -1;
 }
 
+pg_int64
+PQsocketChangeCount(const PGconn *conn)
+{
+	if (!conn)
+		return -1;
+	return conn->sockChangeCount;
+}
+
 int
 PQbackendPID(const PGconn *conn)
 {
diff --git a/src/interfaces/libpq/libpq-fe.h b/src/interfaces/libpq/libpq-fe.h
index c9e6ac2b76..8b21373e4d 100644
--- a/src/interfaces/libpq/libpq-fe.h
+++ b/src/interfaces/libpq/libpq-fe.h
@@ -327,6 +327,7 @@ extern int	PQprotocolVersion(const PGconn *conn);
 extern int	PQserverVersion(const PGconn *conn);
 extern char *PQerrorMessage(const PGconn *conn);
 extern int	PQsocket(const PGconn *conn);
+extern pg_int64 PQsocketChangeCount(const PGconn *conn);
 extern int	PQbackendPID(const PGconn *conn);
 extern int	PQconnectionNeedsPassword(const PGconn *conn);
 extern int	PQconnectionUsedPassword(const PGconn *conn);
diff --git a/src/interfaces/libpq/libpq-int.h b/src/interfaces/libpq/libpq-int.h
index 72931e6019..91b190f078 100644
--- a/src/interfaces/libpq/libpq-int.h
+++ b/src/interfaces/libpq/libpq-int.h
@@ -409,6 +409,7 @@ struct pg_conn
 	/* Connection data */
 	pgsocket	sock;			/* FD for socket, PGINVALID_SOCKET if
 								 * unconnected */
+	pg_int64	sockChangeCount;	/* advances when socket is opened/closed */
 	SockAddr	laddr;			/* Local address */
 	SockAddr	raddr;			/* Remote address */
 	ProtocolVersion pversion;	/* FE/BE protocol version in use */
-- 
2.23.0

