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
This commit is contained in:
parent
57184c3b5d
commit
02eb07ea89
|
@ -2582,6 +2582,7 @@ static const TableAmRoutine heapam_methods = {
|
||||||
.index_build_range_scan = heapam_index_build_range_scan,
|
.index_build_range_scan = heapam_index_build_range_scan,
|
||||||
.index_validate_scan = heapam_index_validate_scan,
|
.index_validate_scan = heapam_index_validate_scan,
|
||||||
|
|
||||||
|
.free_rd_amcache = NULL,
|
||||||
.relation_size = table_block_relation_size,
|
.relation_size = table_block_relation_size,
|
||||||
.relation_needs_toast_table = heapam_relation_needs_toast_table,
|
.relation_needs_toast_table = heapam_relation_needs_toast_table,
|
||||||
.relation_toast_am = heapam_relation_toast_am,
|
.relation_toast_am = heapam_relation_toast_am,
|
||||||
|
|
|
@ -2262,9 +2262,7 @@ RelationReloadIndexInfo(Relation relation)
|
||||||
RelationCloseSmgr(relation);
|
RelationCloseSmgr(relation);
|
||||||
|
|
||||||
/* Must free any AM cached data upon relcache flush */
|
/* Must free any AM cached data upon relcache flush */
|
||||||
if (relation->rd_amcache)
|
table_free_rd_amcache(relation);
|
||||||
pfree(relation->rd_amcache);
|
|
||||||
relation->rd_amcache = NULL;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If it's a shared index, we might be called before backend startup has
|
* If it's a shared index, we might be called before backend startup has
|
||||||
|
@ -2484,8 +2482,7 @@ RelationDestroyRelation(Relation relation, bool remember_tupdesc)
|
||||||
pfree(relation->rd_options);
|
pfree(relation->rd_options);
|
||||||
if (relation->rd_indextuple)
|
if (relation->rd_indextuple)
|
||||||
pfree(relation->rd_indextuple);
|
pfree(relation->rd_indextuple);
|
||||||
if (relation->rd_amcache)
|
table_free_rd_amcache(relation);
|
||||||
pfree(relation->rd_amcache);
|
|
||||||
if (relation->rd_fdwroutine)
|
if (relation->rd_fdwroutine)
|
||||||
pfree(relation->rd_fdwroutine);
|
pfree(relation->rd_fdwroutine);
|
||||||
if (relation->rd_indexcxt)
|
if (relation->rd_indexcxt)
|
||||||
|
@ -2547,9 +2544,7 @@ RelationClearRelation(Relation relation, bool rebuild)
|
||||||
RelationCloseSmgr(relation);
|
RelationCloseSmgr(relation);
|
||||||
|
|
||||||
/* Free AM cached data, if any */
|
/* Free AM cached data, if any */
|
||||||
if (relation->rd_amcache)
|
table_free_rd_amcache(relation);
|
||||||
pfree(relation->rd_amcache);
|
|
||||||
relation->rd_amcache = NULL;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Treat nailed-in system relations separately, they always need to be
|
* Treat nailed-in system relations separately, they always need to be
|
||||||
|
|
|
@ -708,6 +708,14 @@ typedef struct TableAmRoutine
|
||||||
* ------------------------------------------------------------------------
|
* ------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This callback frees relation private cache data stored in rd_amcache.
|
||||||
|
* After the call all memory related to rd_amcache must be freed,
|
||||||
|
* rd_amcache must be set to NULL. If this callback is not provided,
|
||||||
|
* rd_amcache is assumed to point to a single memory chunk.
|
||||||
|
*/
|
||||||
|
void (*free_rd_amcache) (Relation rel);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* See table_relation_size().
|
* See table_relation_size().
|
||||||
*
|
*
|
||||||
|
@ -1847,6 +1855,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
|
* Return the current size of `rel` in bytes. If `forkNumber` is
|
||||||
* InvalidForkNumber, return the relation's overall size, otherwise the size
|
* InvalidForkNumber, return the relation's overall size, otherwise the size
|
||||||
|
|
|
@ -221,10 +221,12 @@ typedef struct RelationData
|
||||||
* rd_amcache is available for index and table AMs to cache private data
|
* 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
|
* 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
|
* 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
|
* message for the relation). If used for table AM it must point to a
|
||||||
* chunk palloc'd in CacheMemoryContext, or in rd_indexcxt for an index
|
* single memory chunk palloc'd in CacheMemoryContext, or more complex
|
||||||
* relation. A relcache reset will include freeing that chunk and setting
|
* data structure in that memory context to be freed by free_rd_amcache
|
||||||
* rd_amcache = NULL.
|
* 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 */
|
void *rd_amcache; /* available for use by index/table AM */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue