On Thu, Jan 11, 2018 at 3:01 PM Thomas Munro
<[email protected]> wrote:
> So I agree with Tom's suggestion:
>
> On Wed, Oct 4, 2017 at 2:29 PM, Tom Lane <[email protected]> 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 */