Skip to content

Commit 02eb07e

Browse files
committed
Allow table AM to store complex data structures in rd_amcache
The new table AM method free_rd_amcache is responsible for freeing all the memory related to rd_amcache and setting free_rd_amcache to NULL. If the new method is not specified, we still assume rd_amcache to be a single chunk of memory, which could be just pfree'd. Discussion: https://postgr.es/m/CAPpHfdurb9ycV8udYqM%3Do0sPS66PJ4RCBM1g-bBpvzUfogY0EA%40mail.gmail.com Reviewed-by: Matthias van de Meent, Mark Dilger, Pavel Borisov Reviewed-by: Nikita Malakhov, Japin Li
1 parent 57184c3 commit 02eb07e

File tree

4 files changed

+44
-12
lines changed

4 files changed

+44
-12
lines changed

src/backend/access/heap/heapam_handler.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2582,6 +2582,7 @@ static const TableAmRoutine heapam_methods = {
25822582
.index_build_range_scan = heapam_index_build_range_scan,
25832583
.index_validate_scan = heapam_index_validate_scan,
25842584

2585+
.free_rd_amcache = NULL,
25852586
.relation_size = table_block_relation_size,
25862587
.relation_needs_toast_table = heapam_relation_needs_toast_table,
25872588
.relation_toast_am = heapam_relation_toast_am,

src/backend/utils/cache/relcache.c

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2262,9 +2262,7 @@ RelationReloadIndexInfo(Relation relation)
22622262
RelationCloseSmgr(relation);
22632263

22642264
/* Must free any AM cached data upon relcache flush */
2265-
if (relation->rd_amcache)
2266-
pfree(relation->rd_amcache);
2267-
relation->rd_amcache = NULL;
2265+
table_free_rd_amcache(relation);
22682266

22692267
/*
22702268
* If it's a shared index, we might be called before backend startup has
@@ -2484,8 +2482,7 @@ RelationDestroyRelation(Relation relation, bool remember_tupdesc)
24842482
pfree(relation->rd_options);
24852483
if (relation->rd_indextuple)
24862484
pfree(relation->rd_indextuple);
2487-
if (relation->rd_amcache)
2488-
pfree(relation->rd_amcache);
2485+
table_free_rd_amcache(relation);
24892486
if (relation->rd_fdwroutine)
24902487
pfree(relation->rd_fdwroutine);
24912488
if (relation->rd_indexcxt)
@@ -2547,9 +2544,7 @@ RelationClearRelation(Relation relation, bool rebuild)
25472544
RelationCloseSmgr(relation);
25482545

25492546
/* Free AM cached data, if any */
2550-
if (relation->rd_amcache)
2551-
pfree(relation->rd_amcache);
2552-
relation->rd_amcache = NULL;
2547+
table_free_rd_amcache(relation);
25532548

25542549
/*
25552550
* Treat nailed-in system relations separately, they always need to be

src/include/access/tableam.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,14 @@ typedef struct TableAmRoutine
708708
* ------------------------------------------------------------------------
709709
*/
710710

711+
/*
712+
* This callback frees relation private cache data stored in rd_amcache.
713+
* After the call all memory related to rd_amcache must be freed,
714+
* rd_amcache must be set to NULL. If this callback is not provided,
715+
* rd_amcache is assumed to point to a single memory chunk.
716+
*/
717+
void (*free_rd_amcache) (Relation rel);
718+
711719
/*
712720
* See table_relation_size().
713721
*
@@ -1847,6 +1855,32 @@ table_index_validate_scan(Relation table_rel,
18471855
* ----------------------------------------------------------------------------
18481856
*/
18491857

1858+
/*
1859+
* Frees relation private cache data stored in rd_amcache. Uses
1860+
* free_rd_amcache method if provided. Assumes rd_amcache to point to single
1861+
* memory chunk otherwise.
1862+
*/
1863+
static inline void
1864+
table_free_rd_amcache(Relation rel)
1865+
{
1866+
if (rel->rd_tableam && rel->rd_tableam->free_rd_amcache)
1867+
{
1868+
rel->rd_tableam->free_rd_amcache(rel);
1869+
1870+
/*
1871+
* We are assuming free_rd_amcache() did clear the cache and left NULL
1872+
* in rd_amcache.
1873+
*/
1874+
Assert(rel->rd_amcache == NULL);
1875+
}
1876+
else
1877+
{
1878+
if (rel->rd_amcache)
1879+
pfree(rel->rd_amcache);
1880+
rel->rd_amcache = NULL;
1881+
}
1882+
}
1883+
18501884
/*
18511885
* Return the current size of `rel` in bytes. If `forkNumber` is
18521886
* InvalidForkNumber, return the relation's overall size, otherwise the size

src/include/utils/rel.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -221,10 +221,12 @@ typedef struct RelationData
221221
* rd_amcache is available for index and table AMs to cache private data
222222
* about the relation. This must be just a cache since it may get reset
223223
* at any time (in particular, it will get reset by a relcache inval
224-
* message for the relation). If used, it must point to a single memory
225-
* chunk palloc'd in CacheMemoryContext, or in rd_indexcxt for an index
226-
* relation. A relcache reset will include freeing that chunk and setting
227-
* rd_amcache = NULL.
224+
* message for the relation). If used for table AM it must point to a
225+
* single memory chunk palloc'd in CacheMemoryContext, or more complex
226+
* data structure in that memory context to be freed by free_rd_amcache
227+
* method. If used for index AM it must point to a single memory chunk
228+
* palloc'd in rd_indexcxt memory context. A relcache reset will include
229+
* freeing that chunk and setting rd_amcache = NULL.
228230
*/
229231
void *rd_amcache; /* available for use by index/table AM */
230232

0 commit comments

Comments
 (0)