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 */