From f6e864733760e54e51005acf95114f2f39b73ee5 Mon Sep 17 00:00:00 2001 From: Andres Freund Date: Mon, 9 Jan 2017 17:56:41 -0800 Subject: [PATCH] Split DistTableCacheEntry() into separate functions. Previously the function was getting too large. Thus this splits the function into separate parts for looking up the cache entry and building the cache contents. --- .../distributed/utils/metadata_cache.c | 275 ++++++++++-------- 1 file changed, 153 insertions(+), 122 deletions(-) diff --git a/src/backend/distributed/utils/metadata_cache.c b/src/backend/distributed/utils/metadata_cache.c index 55b5329c1..190c66946 100644 --- a/src/backend/distributed/utils/metadata_cache.c +++ b/src/backend/distributed/utils/metadata_cache.c @@ -90,6 +90,8 @@ static ScanKeyData DistShardScanKey[1]; /* local function forward declarations */ static DistTableCacheEntry * LookupDistTableCacheEntry(Oid relationId); +static void BuildDistTableCacheEntry(DistTableCacheEntry *cacheEntry); +static void BuildCachedShardList(DistTableCacheEntry *cacheEntry); static FmgrInfo * ShardIntervalCompareFunction(ShardInterval **shardIntervalArray, char partitionMethod); static ShardInterval ** SortShardIntervalArray(ShardInterval **shardIntervalArray, @@ -276,99 +278,171 @@ LookupDistTableCacheEntry(Oid relationId) { DistTableCacheEntry *cacheEntry = NULL; bool foundInCache = false; - HeapTuple distPartitionTuple = NULL; - char *partitionKeyString = NULL; - char partitionMethod = 0; - uint32 colocationId = INVALID_COLOCATION_ID; - char replicationModel = 0; - List *distShardTupleList = NIL; - int shardIntervalArrayLength = 0; - ShardInterval **shardIntervalArray = NULL; - ShardInterval **sortedShardIntervalArray = NULL; - FmgrInfo *shardIntervalCompareFunction = NULL; - FmgrInfo *hashFunction = NULL; - bool hasUninitializedShardInterval = false; - bool hasUniformHashDistribution = false; void *hashKey = (void *) &relationId; - Relation pgDistPartition = NULL; if (DistTableCacheHash == NULL) { InitializeDistTableCache(); } - cacheEntry = hash_search(DistTableCacheHash, hashKey, HASH_FIND, &foundInCache); + cacheEntry = hash_search(DistTableCacheHash, hashKey, HASH_ENTER, &foundInCache); /* return valid matches */ - if ((cacheEntry != NULL) && (cacheEntry->isValid)) + if (foundInCache) { - return cacheEntry; - } + if (cacheEntry->isValid) + { + return cacheEntry; + } - /* free the content of old, invalid, entries */ - if (cacheEntry != NULL) - { + /* free the content of old, invalid, entries */ ResetDistTableCacheEntry(cacheEntry); } + /* zero out entry, but not the key part */ + memset(((char *) cacheEntry) + sizeof(Oid), 0, + sizeof(DistTableCacheEntry) - sizeof(Oid)); + + /* actually fill out entry */ + BuildDistTableCacheEntry(cacheEntry); + + /* and finally mark as valid */ + cacheEntry->isValid = true; + + return cacheEntry; +} + + +/* + * BuildDistTableCacheEntry is a helper routine for + * LookupDistTableCacheEntry() for building the cache contents. + */ +static void +BuildDistTableCacheEntry(DistTableCacheEntry *cacheEntry) +{ + HeapTuple distPartitionTuple = NULL; + Relation pgDistPartition = NULL; + Form_pg_dist_partition partitionForm = NULL; + Datum partitionKeyDatum = 0; + Datum replicationModelDatum = 0; + MemoryContext oldContext = NULL; + TupleDesc tupleDescriptor = NULL; + bool isNull = false; + bool partitionKeyIsNull = false; + pgDistPartition = heap_open(DistPartitionRelationId(), AccessShareLock); - distPartitionTuple = LookupDistPartitionTuple(pgDistPartition, relationId); - if (distPartitionTuple != NULL) + distPartitionTuple = + LookupDistPartitionTuple(pgDistPartition, cacheEntry->relationId); + + /* not a distributed table, done */ + if (distPartitionTuple == NULL) { - Form_pg_dist_partition partitionForm = - (Form_pg_dist_partition) GETSTRUCT(distPartitionTuple); - Datum partitionKeyDatum = 0; - Datum replicationModelDatum = 0; - MemoryContext oldContext = NULL; - TupleDesc tupleDescriptor = RelationGetDescr(pgDistPartition); - bool isNull = false; - bool partitionKeyIsNull = false; + cacheEntry->isDistributedTable = false; + heap_close(pgDistPartition, NoLock); + return; + } - partitionKeyDatum = heap_getattr(distPartitionTuple, - Anum_pg_dist_partition_partkey, - tupleDescriptor, - &partitionKeyIsNull); + cacheEntry->isDistributedTable = true; - colocationId = heap_getattr(distPartitionTuple, - Anum_pg_dist_partition_colocationid, tupleDescriptor, - &isNull); - if (isNull) - { - colocationId = INVALID_COLOCATION_ID; - } + tupleDescriptor = RelationGetDescr(pgDistPartition); + partitionForm = (Form_pg_dist_partition) GETSTRUCT(distPartitionTuple); - replicationModelDatum = heap_getattr(distPartitionTuple, - Anum_pg_dist_partition_repmodel, - tupleDescriptor, - &isNull); + cacheEntry->partitionMethod = partitionForm->partmethod; - if (isNull) - { - /* - * repmodel is NOT NULL but before ALTER EXTENSION citus UPGRADE the column - * doesn't exist - */ - replicationModelDatum = CharGetDatum('c'); - } + partitionKeyDatum = heap_getattr(distPartitionTuple, + Anum_pg_dist_partition_partkey, + tupleDescriptor, + &partitionKeyIsNull); + /* note that for reference tables partitionKeyisNull is true */ + if (!partitionKeyIsNull) + { oldContext = MemoryContextSwitchTo(CacheMemoryContext); - partitionMethod = partitionForm->partmethod; - replicationModel = DatumGetChar(replicationModelDatum); - - /* note that for reference tables isNull becomes true */ - if (!partitionKeyIsNull) - { - partitionKeyString = TextDatumGetCString(partitionKeyDatum); - } - + cacheEntry->partitionKeyString = TextDatumGetCString(partitionKeyDatum); MemoryContextSwitchTo(oldContext); + } + else + { + cacheEntry->partitionKeyString = NULL; + } - heap_freetuple(distPartitionTuple); + cacheEntry->colocationId = heap_getattr(distPartitionTuple, + Anum_pg_dist_partition_colocationid, + tupleDescriptor, + &isNull); + if (isNull) + { + cacheEntry->colocationId = INVALID_COLOCATION_ID; + } + + replicationModelDatum = heap_getattr(distPartitionTuple, + Anum_pg_dist_partition_repmodel, + tupleDescriptor, + &isNull); + if (isNull) + { + /* + * repmodel is NOT NULL but before ALTER EXTENSION citus UPGRADE the column + * doesn't exist + */ + cacheEntry->replicationModel = 'c'; + } + else + { + cacheEntry->replicationModel = DatumGetChar(replicationModelDatum); + } + + heap_freetuple(distPartitionTuple); + + BuildCachedShardList(cacheEntry); + + /* we only need hash functions for hash distributed tables */ + if (cacheEntry->partitionMethod == DISTRIBUTE_BY_HASH) + { + TypeCacheEntry *typeEntry = NULL; + Node *partitionNode = stringToNode(cacheEntry->partitionKeyString); + Var *partitionColumn = (Var *) partitionNode; + FmgrInfo *hashFunction = NULL; + + Assert(IsA(partitionNode, Var)); + typeEntry = lookup_type_cache(partitionColumn->vartype, + TYPECACHE_HASH_PROC_FINFO); + + hashFunction = MemoryContextAllocZero(CacheMemoryContext, + sizeof(FmgrInfo)); + + fmgr_info_copy(hashFunction, &(typeEntry->hash_proc_finfo), CacheMemoryContext); + + cacheEntry->hashFunction = hashFunction; + + /* check the shard distribution for hash partitioned tables */ + cacheEntry->hasUniformHashDistribution = + HasUniformHashDistribution(cacheEntry->sortedShardIntervalArray, + cacheEntry->shardIntervalArrayLength); + } + else + { + cacheEntry->hashFunction = NULL; } heap_close(pgDistPartition, NoLock); +} - distShardTupleList = LookupDistShardTuples(relationId); + +/* + * BuildCachedShardList() is a helper routine for BuildDistTableCacheEntry() + * building up the list of shards in a distributed relation. + */ +static void +BuildCachedShardList(DistTableCacheEntry *cacheEntry) +{ + ShardInterval **shardIntervalArray = NULL; + ShardInterval **sortedShardIntervalArray = NULL; + FmgrInfo *shardIntervalCompareFunction = NULL; + List *distShardTupleList = NIL; + int shardIntervalArrayLength = 0; + + distShardTupleList = LookupDistShardTuples(cacheEntry->relationId); shardIntervalArrayLength = list_length(distShardTupleList); if (shardIntervalArrayLength > 0) { @@ -379,7 +453,9 @@ LookupDistTableCacheEntry(Oid relationId) Oid intervalTypeId = InvalidOid; int32 intervalTypeMod = -1; - GetPartitionTypeInputInfo(partitionKeyString, partitionMethod, &intervalTypeId, + GetPartitionTypeInputInfo(cacheEntry->partitionKeyString, + cacheEntry->partitionMethod, + &intervalTypeId, &intervalTypeMod); shardIntervalArray = MemoryContextAllocZero(CacheMemoryContext, @@ -411,7 +487,7 @@ LookupDistTableCacheEntry(Oid relationId) } /* decide and allocate interval comparison function */ - if (partitionMethod == DISTRIBUTE_BY_NONE) + if (cacheEntry->partitionMethod == DISTRIBUTE_BY_NONE) { shardIntervalCompareFunction = NULL; } @@ -422,16 +498,17 @@ LookupDistTableCacheEntry(Oid relationId) /* allocate the comparison function in the cache context */ oldContext = MemoryContextSwitchTo(CacheMemoryContext); - shardIntervalCompareFunction = ShardIntervalCompareFunction(shardIntervalArray, - partitionMethod); + shardIntervalCompareFunction = + ShardIntervalCompareFunction(shardIntervalArray, + cacheEntry->partitionMethod); MemoryContextSwitchTo(oldContext); } /* reference tables has a single shard which is not initialized */ - if (partitionMethod == DISTRIBUTE_BY_NONE) + if (cacheEntry->partitionMethod == DISTRIBUTE_BY_NONE) { - hasUninitializedShardInterval = true; + cacheEntry->hasUninitializedShardInterval = true; /* * Note that during create_reference_table() call, @@ -439,7 +516,7 @@ LookupDistTableCacheEntry(Oid relationId) */ if (shardIntervalArrayLength > 1) { - char *relationName = get_rel_name(relationId); + char *relationName = get_rel_name(cacheEntry->relationId); ereport(ERROR, (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), errmsg("reference table \"%s\" has more than 1 shard", @@ -457,60 +534,14 @@ LookupDistTableCacheEntry(Oid relationId) shardIntervalCompareFunction); /* check if there exists any shard intervals with no min/max values */ - hasUninitializedShardInterval = + cacheEntry->hasUninitializedShardInterval = HasUninitializedShardInterval(sortedShardIntervalArray, shardIntervalArrayLength); } - /* we only need hash functions for hash distributed tables */ - if (partitionMethod == DISTRIBUTE_BY_HASH) - { - TypeCacheEntry *typeEntry = NULL; - Node *partitionNode = stringToNode(partitionKeyString); - Var *partitionColumn = (Var *) partitionNode; - Assert(IsA(partitionNode, Var)); - typeEntry = lookup_type_cache(partitionColumn->vartype, - TYPECACHE_HASH_PROC_FINFO); - - hashFunction = MemoryContextAllocZero(CacheMemoryContext, - sizeof(FmgrInfo)); - - fmgr_info_copy(hashFunction, &(typeEntry->hash_proc_finfo), CacheMemoryContext); - - /* check the shard distribution for hash partitioned tables */ - hasUniformHashDistribution = - HasUniformHashDistribution(sortedShardIntervalArray, - shardIntervalArrayLength); - } - - cacheEntry = hash_search(DistTableCacheHash, hashKey, HASH_ENTER, NULL); - - /* zero out entry, but not the key part */ - memset(((char *) cacheEntry) + sizeof(Oid), 0, - sizeof(DistTableCacheEntry) - sizeof(Oid)); - - if (distPartitionTuple == NULL) - { - cacheEntry->isValid = true; - cacheEntry->isDistributedTable = false; - } - else - { - cacheEntry->isValid = true; - cacheEntry->isDistributedTable = true; - cacheEntry->partitionKeyString = partitionKeyString; - cacheEntry->partitionMethod = partitionMethod; - cacheEntry->colocationId = colocationId; - cacheEntry->replicationModel = replicationModel; - cacheEntry->shardIntervalArrayLength = shardIntervalArrayLength; - cacheEntry->sortedShardIntervalArray = sortedShardIntervalArray; - cacheEntry->shardIntervalCompareFunction = shardIntervalCompareFunction; - cacheEntry->hashFunction = hashFunction; - cacheEntry->hasUninitializedShardInterval = hasUninitializedShardInterval; - cacheEntry->hasUniformHashDistribution = hasUniformHashDistribution; - } - - return cacheEntry; + cacheEntry->shardIntervalArrayLength = shardIntervalArrayLength; + cacheEntry->sortedShardIntervalArray = sortedShardIntervalArray; + cacheEntry->shardIntervalCompareFunction = shardIntervalCompareFunction; }