On Thu, Jan 11, 2018 at 3:01 PM Thomas Munro
<thomas.mu...@enterprisedb.com> wrote:
> So I agree with Tom's suggestion:
>
> On Wed, Oct 4, 2017 at 2:29 PM, Tom Lane <t...@sss.pgh.pa.us> wrote:
> > Perhaps serialize the contents into an array in DSM, then rebuild a hash
> > table from that in the worker.  Robert might have a better idea though.
>
> I'd happily volunteer to write or review a patch to do that.  Is there
> a rebase of the stuff that got reverted, to build on?

Here is a draft patch showing the approach discussed for transmitting
enum_blacklist in parallel workers.  This should be useful for
reviving the code reverted by 93a1af0b.

--
Thomas Munro
http://www.enterprisedb.com
diff --git a/src/backend/access/transam/parallel.c b/src/backend/access/transam/parallel.c
index c168118467..c95caee017 100644
--- a/src/backend/access/transam/parallel.c
+++ b/src/backend/access/transam/parallel.c
@@ -19,6 +19,7 @@
 #include "access/session.h"
 #include "access/xact.h"
 #include "access/xlog.h"
+#include "catalog/pg_enum.h"
 #include "catalog/index.h"
 #include "catalog/namespace.h"
 #include "commands/async.h"
@@ -71,6 +72,7 @@
 #define PARALLEL_KEY_SESSION_DSM			UINT64CONST(0xFFFFFFFFFFFF000A)
 #define PARALLEL_KEY_REINDEX_STATE			UINT64CONST(0xFFFFFFFFFFFF000B)
 #define PARALLEL_KEY_RELMAPPER_STATE		UINT64CONST(0xFFFFFFFFFFFF000C)
+#define PARALLEL_KEY_ENUMBLACKLIST			UINT64CONST(0xFFFFFFFFFFFF000D)
 
 /* Fixed-size parallel state. */
 typedef struct FixedParallelState
@@ -208,6 +210,7 @@ InitializeParallelDSM(ParallelContext *pcxt)
 	Size		tstatelen = 0;
 	Size		reindexlen = 0;
 	Size		relmapperlen = 0;
+	Size		enumblacklistlen = 0;
 	Size		segsize = 0;
 	int			i;
 	FixedParallelState *fps;
@@ -261,8 +264,10 @@ InitializeParallelDSM(ParallelContext *pcxt)
 		shm_toc_estimate_chunk(&pcxt->estimator, reindexlen);
 		relmapperlen = EstimateRelationMapSpace();
 		shm_toc_estimate_chunk(&pcxt->estimator, relmapperlen);
+		enumblacklistlen = EstimateEnumBlacklistSpace();
+		shm_toc_estimate_chunk(&pcxt->estimator, enumblacklistlen);
 		/* If you add more chunks here, you probably need to add keys. */
-		shm_toc_estimate_keys(&pcxt->estimator, 9);
+		shm_toc_estimate_keys(&pcxt->estimator, 10);
 
 		/* Estimate space need for error queues. */
 		StaticAssertStmt(BUFFERALIGN(PARALLEL_ERROR_QUEUE_SIZE) ==
@@ -336,6 +341,7 @@ InitializeParallelDSM(ParallelContext *pcxt)
 		char	   *error_queue_space;
 		char	   *session_dsm_handle_space;
 		char	   *entrypointstate;
+		char	   *enumblacklistspace;
 		Size		lnamelen;
 
 		/* Serialize shared libraries we have loaded. */
@@ -385,6 +391,12 @@ InitializeParallelDSM(ParallelContext *pcxt)
 		shm_toc_insert(pcxt->toc, PARALLEL_KEY_RELMAPPER_STATE,
 					   relmapperspace);
 
+		/* Serialize enum blacklist state. */
+		enumblacklistspace = shm_toc_allocate(pcxt->toc, enumblacklistlen);
+		SerializeEnumBlacklist(enumblacklistspace);
+		shm_toc_insert(pcxt->toc, PARALLEL_KEY_ENUMBLACKLIST,
+					   enumblacklistspace);
+
 		/* Allocate space for worker information. */
 		pcxt->worker = palloc0(sizeof(ParallelWorkerInfo) * pcxt->nworkers);
 
@@ -1218,6 +1230,7 @@ ParallelWorkerMain(Datum main_arg)
 	char	   *tstatespace;
 	char	   *reindexspace;
 	char	   *relmapperspace;
+	char	   *enumblacklistspace;
 	StringInfoData msgbuf;
 	char	   *session_dsm_handle_space;
 
@@ -1397,6 +1410,11 @@ ParallelWorkerMain(Datum main_arg)
 	relmapperspace = shm_toc_lookup(toc, PARALLEL_KEY_RELMAPPER_STATE, false);
 	RestoreRelationMap(relmapperspace);
 
+	/* Restore enum blacklist. */
+	enumblacklistspace = shm_toc_lookup(toc, PARALLEL_KEY_ENUMBLACKLIST,
+										false);
+	RestoreEnumBlacklist(enumblacklistspace);
+
 	/*
 	 * We've initialized all of our state now; nothing should change
 	 * hereafter.
diff --git a/src/backend/catalog/pg_enum.c b/src/backend/catalog/pg_enum.c
index fde361f367..87a12996c7 100644
--- a/src/backend/catalog/pg_enum.c
+++ b/src/backend/catalog/pg_enum.c
@@ -28,6 +28,7 @@
 #include "utils/builtins.h"
 #include "utils/catcache.h"
 #include "utils/fmgroids.h"
+#include "utils/memutils.h"
 #include "utils/syscache.h"
 #include "utils/tqual.h"
 
@@ -38,6 +39,7 @@ Oid			binary_upgrade_next_pg_enum_oid = InvalidOid;
 static void RenumberEnumType(Relation pg_enum, HeapTuple *existing, int nelems);
 static int	sort_order_cmp(const void *p1, const void *p2);
 
+static HTAB *enum_blacklist = NULL;
 
 /*
  * EnumValuesCreate
@@ -620,3 +622,56 @@ sort_order_cmp(const void *p1, const void *p2)
 	else
 		return 0;
 }
+
+Size
+EstimateEnumBlacklistSpace(void)
+{
+	if (!enum_blacklist)
+		return sizeof(Oid);
+	return sizeof(Oid) + sizeof(Oid) * hash_get_num_entries(enum_blacklist);
+}
+
+void
+SerializeEnumBlacklist(void *space)
+{
+	Oid *serialized = (Oid *) space;
+	HASH_SEQ_STATUS status;
+	Oid *value;
+
+	if (!enum_blacklist)
+	{
+		*serialized = 0;
+		return;
+	}
+
+	*serialized = hash_get_num_entries(enum_blacklist);
+	hash_seq_init(&status, enum_blacklist);
+	while ((value = (Oid *) hash_seq_search(&status)))
+		*serialized++ = *value;
+}
+
+void
+RestoreEnumBlacklist(void *space)
+{
+	Oid *serialized = (Oid *) space;
+	HASHCTL     hash_ctl;
+	int			num_elements;
+
+	Assert(!enum_blacklist);
+
+	num_elements = *serialized++;
+	if (num_elements == 0)
+		return;
+
+	memset(&hash_ctl, 0, sizeof(hash_ctl));
+	hash_ctl.keysize = sizeof(Oid);
+	hash_ctl.entrysize = sizeof(Oid);
+	hash_ctl.hcxt = TopTransactionContext;
+	enum_blacklist = hash_create("Enum value blacklist",
+								 32,
+								 &hash_ctl,
+								 HASH_ELEM | HASH_BLOBS | HASH_CONTEXT);
+
+	while (num_elements-- > 0)
+		hash_search(enum_blacklist, serialized++, HASH_ENTER, NULL);
+}
diff --git a/src/include/catalog/pg_enum.h b/src/include/catalog/pg_enum.h
index e6fd41e5b2..f5a71921a3 100644
--- a/src/include/catalog/pg_enum.h
+++ b/src/include/catalog/pg_enum.h
@@ -52,5 +52,8 @@ extern void AddEnumLabel(Oid enumTypeOid, const char *newVal,
 			 bool skipIfExists);
 extern void RenameEnumLabel(Oid enumTypeOid,
 				const char *oldVal, const char *newVal);
+extern Size EstimateEnumBlacklistSpace(void);
+extern void SerializeEnumBlacklist(void *space);
+extern void RestoreEnumBlacklist(void *space);
 
 #endif							/* PG_ENUM_H */

Reply via email to