From 510783f84fce90238bac405a5e06d7e118037b3b Mon Sep 17 00:00:00 2001 From: Jason Petersen Date: Wed, 27 Apr 2016 21:04:17 -0700 Subject: [PATCH] Force bad connections in tests by closing sockets Based on Andres' suggestion, I removed SetConnectionStatus, moving its functionality directly into set_connection_status_bad, which now simply shuts down the socket underlying a particular connection. This keeps the functionality as-is while removing our questionable use of internal libpq headers. --- .../distributed/test/connection_cache.c | 20 ++++++++++-- .../distributed/test/connection_utils.c | 31 ------------------- 2 files changed, 17 insertions(+), 34 deletions(-) delete mode 100644 src/backend/distributed/test/connection_utils.c diff --git a/src/backend/distributed/test/connection_cache.c b/src/backend/distributed/test/connection_cache.c index 6fd63e46b..8ce7a2cce 100644 --- a/src/backend/distributed/test/connection_cache.c +++ b/src/backend/distributed/test/connection_cache.c @@ -18,6 +18,7 @@ #include #include +#include #include "catalog/pg_type.h" #include "distributed/connection_cache.h" @@ -129,13 +130,16 @@ get_and_purge_connection(PG_FUNCTION_ARGS) /* * set_connection_status_bad does not remove the given connection from the connection hash. - * It only sets its status to CONNECTION_BAD. On success, it returns true. + * It simply shuts down the underlying socket. On success, it returns true. */ Datum set_connection_status_bad(PG_FUNCTION_ARGS) { char *nodeName = PG_GETARG_CSTRING(0); int32 nodePort = PG_GETARG_INT32(1); + int socket = -1; + int shutdownStatus = 0; + int pqStatus PG_USED_FOR_ASSERTS_ONLY = 0; PGconn *connection = GetOrEstablishConnection(nodeName, nodePort); if (connection == NULL) @@ -143,8 +147,18 @@ set_connection_status_bad(PG_FUNCTION_ARGS) PG_RETURN_BOOL(false); } - /* set the connection status */ - SetConnectionStatus(connection, CONNECTION_BAD); + /* Prevent further reads/writes... */ + socket = PQsocket(connection); + shutdownStatus = shutdown(socket, SHUT_RDWR); + if (shutdownStatus != 0) + { + ereport(ERROR, (errcode_for_socket_access(), errmsg("shutdown failed"))); + } + + /* ... and make libpq notice by reading data. */ + pqStatus = PQconsumeInput(connection); + + Assert(pqStatus == 0); /* expect failure */ PG_RETURN_BOOL(true); } diff --git a/src/backend/distributed/test/connection_utils.c b/src/backend/distributed/test/connection_utils.c deleted file mode 100644 index e944c1f87..000000000 --- a/src/backend/distributed/test/connection_utils.c +++ /dev/null @@ -1,31 +0,0 @@ -/*------------------------------------------------------------------------- - * - * test/src/connection_utils.c - * - * This file isolates a test function which modifies private connection - * state, ensuring the correct ("internal") headers are included, rather - * than the version-specific server ones. Without this kludge, builds on - * certain platforms (those which install a single libpq version but can - * have multiple PostgreSQL server versions) will faile. - * - * Copyright (c) 2014-2016, Citus Data, Inc. - * - *------------------------------------------------------------------------- - */ - -#include "c.h" -#include "libpq-fe.h" -#include "libpq-int.h" - -#include "distributed/test_helper_functions.h" - -/* - * SetConnectionStatus simply uses the internal headers to access "private" - * fields of the connection struct in order to force a cache connection to a - * particular status. - */ -void -SetConnectionStatus(PGconn *connection, ConnStatusType status) -{ - connection->status = status; -}