From 6eeeecb060d3d75644946dc9404a3a65f8928813 Mon Sep 17 00:00:00 2001 From: Alexander Korotkov Date: Wed, 7 Jun 2023 13:04:58 +0300 Subject: [PATCH 03/13] Allow table AM to store complex data structures in rd_amcache New table AM method free_rd_amcache is responsible for freeing the rd_amcache. --- src/backend/access/heap/heapam_handler.c | 1 + src/backend/utils/cache/relcache.c | 18 +++++++------ src/include/access/tableam.h | 33 ++++++++++++++++++++++++ src/include/utils/rel.h | 10 ++++--- 4 files changed, 50 insertions(+), 12 deletions(-) diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c index 7c7204a2422..da86ca5c31a 100644 --- a/src/backend/access/heap/heapam_handler.c +++ b/src/backend/access/heap/heapam_handler.c @@ -2640,6 +2640,7 @@ static const TableAmRoutine heapam_methods = { .index_build_range_scan = heapam_index_build_range_scan, .index_validate_scan = heapam_index_validate_scan, + .free_rd_amcache = NULL, .relation_size = table_block_relation_size, .relation_needs_toast_table = heapam_relation_needs_toast_table, .relation_toast_am = heapam_relation_toast_am, diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 2cd19d603fb..6d98bdfba06 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -318,6 +318,7 @@ static OpClassCacheEnt *LookupOpclassInfo(Oid operatorClassOid, StrategyNumber numSupport); static void RelationCacheInitFileRemoveInDir(const char *tblspcpath); static void unlink_initfile(const char *initfilename, int elevel); +static void release_rd_amcache(Relation rel); /* @@ -2262,9 +2263,7 @@ RelationReloadIndexInfo(Relation relation) RelationCloseSmgr(relation); /* Must free any AM cached data upon relcache flush */ - if (relation->rd_amcache) - pfree(relation->rd_amcache); - relation->rd_amcache = NULL; + release_rd_amcache(relation); /* * If it's a shared index, we might be called before backend startup has @@ -2484,8 +2483,7 @@ RelationDestroyRelation(Relation relation, bool remember_tupdesc) pfree(relation->rd_options); if (relation->rd_indextuple) pfree(relation->rd_indextuple); - if (relation->rd_amcache) - pfree(relation->rd_amcache); + release_rd_amcache(relation); if (relation->rd_fdwroutine) pfree(relation->rd_fdwroutine); if (relation->rd_indexcxt) @@ -2547,9 +2545,7 @@ RelationClearRelation(Relation relation, bool rebuild) RelationCloseSmgr(relation); /* Free AM cached data, if any */ - if (relation->rd_amcache) - pfree(relation->rd_amcache); - relation->rd_amcache = NULL; + release_rd_amcache(relation); /* * Treat nailed-in system relations separately, they always need to be @@ -6868,3 +6864,9 @@ ResOwnerReleaseRelation(Datum res) RelationCloseCleanup((Relation) res); } + +static void +release_rd_amcache(Relation rel) +{ + table_free_rd_amcache(rel); +} diff --git a/src/include/access/tableam.h b/src/include/access/tableam.h index 467bdc09d36..be092e8bedb 100644 --- a/src/include/access/tableam.h +++ b/src/include/access/tableam.h @@ -715,6 +715,13 @@ typedef struct TableAmRoutine * ------------------------------------------------------------------------ */ + /* + * This callback frees relation private cache data stored in rd_amcache. + * If this callback is not provided, rd_amcache is assumed to point to + * single memory chunk. + */ + void (*free_rd_amcache) (Relation rel); + /* * See table_relation_size(). * @@ -1878,6 +1885,32 @@ table_index_validate_scan(Relation table_rel, * ---------------------------------------------------------------------------- */ +/* + * Frees relation private cache data stored in rd_amcache. Uses + * free_rd_amcache method if provided. Assumes rd_amcache to point to single + * memory chunk otherwise. + */ +static inline void +table_free_rd_amcache(Relation rel) +{ + if (rel->rd_tableam && rel->rd_tableam->free_rd_amcache) + { + rel->rd_tableam->free_rd_amcache(rel); + + /* + * We are assuming free_rd_amcache() did clear the cache and left NULL + * in rd_amcache. + */ + Assert(rel->rd_amcache == NULL); + } + else + { + if (rel->rd_amcache) + pfree(rel->rd_amcache); + rel->rd_amcache = NULL; + } +} + /* * Return the current size of `rel` in bytes. If `forkNumber` is * InvalidForkNumber, return the relation's overall size, otherwise the size diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h index 87002049538..69557fc7a2c 100644 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -221,10 +221,12 @@ typedef struct RelationData * rd_amcache is available for index and table AMs to cache private data * about the relation. This must be just a cache since it may get reset * at any time (in particular, it will get reset by a relcache inval - * message for the relation). If used, it must point to a single memory - * chunk palloc'd in CacheMemoryContext, or in rd_indexcxt for an index - * relation. A relcache reset will include freeing that chunk and setting - * rd_amcache = NULL. + * message for the relation). If used for table AM it must point to a + * single memory chunk palloc'd in CacheMemoryContext, or more complex + * data structure in that memory context to be freed by free_rd_amcache + * method. If used for index AM it must point to a single memory chunk + * palloc'd in rd_indexcxt memory context. A relcache reset will include + * freeing that chunk and setting rd_amcache = NULL. */ void *rd_amcache; /* available for use by index/table AM */ -- 2.39.3 (Apple Git-145)