Skip to content

Commit 79466c6

Browse files
committed
PartitionFilter: invalidate PartRelationInfo on partition creation, fix invalidate_pathman_relation_info()
1 parent f9fa69a commit 79466c6

File tree

8 files changed

+163
-92
lines changed

8 files changed

+163
-92
lines changed

src/hooks.c

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,10 @@ pathman_post_parse_analysis_hook(ParseState *pstate, Query *query)
452452
if (post_parse_analyze_hook_next)
453453
post_parse_analyze_hook_next(pstate, query);
454454

455+
/* Finish delayed invalidation jobs */
456+
if (IsPathmanReady())
457+
finish_delayed_invalidation();
458+
455459
/* Load config if pg_pathman exists & it's still necessary */
456460
if (IsPathmanEnabled() &&
457461
initialization_needed &&
@@ -461,10 +465,6 @@ pathman_post_parse_analysis_hook(ParseState *pstate, Query *query)
461465
load_config(); /* perform main cache initialization */
462466
}
463467

464-
/* Finish delayed invalidation jobs */
465-
if (IsPathmanReady())
466-
finish_delayed_invalidation();
467-
468468
inheritance_disabled_relids = NIL;
469469
inheritance_enabled_relids = NIL;
470470
}
@@ -495,6 +495,9 @@ pathman_relcache_hook(Datum arg, Oid relid)
495495
PartParentSearch search;
496496
Oid partitioned_table;
497497

498+
if (!IsPathmanReady())
499+
return;
500+
498501
/* Invalidate PartParentInfo cache if needed */
499502
partitioned_table = forget_parent_of_partition(relid, &search);
500503

@@ -516,6 +519,9 @@ pathman_relcache_hook(Datum arg, Oid relid)
516519
{
517520
elog(DEBUG2, "Invalidation message for relation %u [%u]",
518521
relid, MyProcPid);
522+
523+
if (relid == get_pathman_config_relid())
524+
delay_pathman_shutdown();
519525
}
520526
break;
521527

src/init.c

Lines changed: 36 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,11 @@ static int oid_cmp(const void *p1, const void *p2);
7878
* Create local PartRelationInfo cache & load pg_pathman's config.
7979
*/
8080
void
81-
load_config()
81+
load_config(void)
8282
{
83+
/* cache PATHMAN_CONFIG relation Oid */
84+
pathman_config_relid = get_relname_relid(PATHMAN_CONFIG, get_pathman_schema());
85+
8386
init_local_config(); /* create 'relations' hash table */
8487
read_pathman_config(); /* read PATHMAN_CONFIG table & fill cache */
8588

@@ -88,6 +91,34 @@ load_config()
8891
elog(DEBUG2, "pg_pathman's config has been loaded successfully");
8992
}
9093

94+
/*
95+
* Destroy local caches & free memory.
96+
*/
97+
void
98+
unload_config(void)
99+
{
100+
HASH_SEQ_STATUS status;
101+
PartRelationInfo *prel;
102+
103+
hash_seq_init(&status, partitioned_rels);
104+
while((prel = (PartRelationInfo *) hash_seq_search(&status)) != NULL)
105+
{
106+
if (PrelIsValid(prel))
107+
{
108+
FreeChildrenArray(prel);
109+
FreeRangesArray(prel);
110+
}
111+
}
112+
113+
/* Now we can safely destroy hash tables */
114+
hash_destroy(partitioned_rels);
115+
hash_destroy(parent_cache);
116+
partitioned_rels = NULL;
117+
parent_cache = NULL;
118+
119+
initialization_needed = true;
120+
}
121+
91122
/*
92123
* Estimate shmem amount needed for pg_pathman to run.
93124
*/
@@ -105,12 +136,6 @@ init_local_config(void)
105136
{
106137
HASHCTL ctl;
107138

108-
if (partitioned_rels)
109-
{
110-
elog(DEBUG2, "pg_pathman's partitioned relations table already exists");
111-
return;
112-
}
113-
114139
memset(&ctl, 0, sizeof(ctl));
115140
ctl.keysize = sizeof(Oid);
116141
ctl.entrysize = sizeof(PartRelationInfo);
@@ -392,24 +417,20 @@ bool
392417
pathman_config_contains_relation(Oid relid, Datum *values, bool *isnull,
393418
TransactionId *xmin)
394419
{
395-
Oid pathman_config;
396420
Relation rel;
397421
HeapScanDesc scan;
398422
ScanKeyData key[1];
399423
Snapshot snapshot;
400424
HeapTuple htup;
401425
bool contains_rel = false;
402426

403-
/* Get PATHMAN_CONFIG table Oid */
404-
pathman_config = get_relname_relid(PATHMAN_CONFIG, get_pathman_schema());
405-
406427
ScanKeyInit(&key[0],
407428
Anum_pathman_config_partrel,
408429
BTEqualStrategyNumber, F_OIDEQ,
409430
ObjectIdGetDatum(relid));
410431

411-
/* Open relation with latest snapshot available */
412-
rel = heap_open(pathman_config, AccessShareLock);
432+
/* Open PATHMAN_CONFIG with latest snapshot available */
433+
rel = heap_open(get_pathman_config_relid(), AccessShareLock);
413434

414435
/* Check that 'partrel' column is if regclass type */
415436
Assert(RelationGetDescr(rel)->
@@ -471,17 +492,13 @@ pathman_config_contains_relation(Oid relid, Datum *values, bool *isnull,
471492
static void
472493
read_pathman_config(void)
473494
{
474-
Oid pathman_config;
475495
Relation rel;
476496
HeapScanDesc scan;
477497
Snapshot snapshot;
478498
HeapTuple htup;
479499

480-
/* Get PATHMAN_CONFIG table Oid */
481-
pathman_config = get_relname_relid(PATHMAN_CONFIG, get_pathman_schema());
482-
483-
/* Open relation with latest snapshot available */
484-
rel = heap_open(pathman_config, AccessShareLock);
500+
/* Open PATHMAN_CONFIG with latest snapshot available */
501+
rel = heap_open(get_pathman_config_relid(), AccessShareLock);
485502

486503
/* Check that 'partrel' column is if regclass type */
487504
Assert(RelationGetDescr(rel)->

src/init.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ Size estimate_pathman_shmem_size(void);
2828
void init_local_config(void);
2929
void init_shmem_config(void);
3030
void load_config(void);
31+
void unload_config(void);
3132

3233
void fill_prel_with_partitions(const Oid *partitions,
3334
const uint32 parts_count,

src/partition_filter.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,9 @@ partition_filter_exec(CustomScanState *node)
207207
selected_partid = create_partitions(state->partitioned_table,
208208
state->temp_const.constvalue,
209209
state->temp_const.consttype);
210+
211+
/* get_pathman_relation_info() will refresh this entry */
212+
invalidate_pathman_relation_info(state->partitioned_table, NULL);
210213
}
211214
else
212215
selected_partid = parts[0];

src/pathman.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,10 @@
5656
/* type modifier (typmod) for 'range_interval' */
5757
#define PATHMAN_CONFIG_interval_typmod -1
5858

59+
extern Oid pathman_config_relid;
60+
61+
Oid get_pathman_config_relid(void);
62+
5963

6064
/*
6165
* pg_pathman's global state.

src/pg_pathman.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ List *inheritance_disabled_relids = NIL;
5050
List *inheritance_enabled_relids = NIL;
5151
bool pg_pathman_enable = true;
5252
PathmanState *pmstate;
53+
Oid pathman_config_relid = InvalidOid;
5354

5455

5556
/* pg module functions */
@@ -2075,3 +2076,9 @@ generate_mergeappend_paths(PlannerInfo *root, RelOptInfo *rel,
20752076
}
20762077
}
20772078
}
2079+
2080+
Oid
2081+
get_pathman_config_relid(void)
2082+
{
2083+
return pathman_config_relid;
2084+
}

src/relation_info.c

Lines changed: 43 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,9 @@
2626
#include "utils/snapmgr.h"
2727

2828

29-
static List *delayed_invalidation_parent_rels = NIL;
30-
static List *delayed_invalidation_vague_rels = NIL;
29+
static List *delayed_invalidation_parent_rels = NIL;
30+
static List *delayed_invalidation_vague_rels = NIL;
31+
static bool delayed_shutdown = false;
3132

3233
/* Add unique Oid to list, allocate in TopMemoryContext */
3334
#define list_add_unique(list, oid) \
@@ -51,60 +52,6 @@ static Oid get_parent_of_partition_internal(Oid partition,
5152
static bool perform_parent_refresh(Oid parent);
5253

5354

54-
/*
55-
* Useful static functions for freeing memory.
56-
*/
57-
58-
static inline void
59-
FreeChildrenArray(PartRelationInfo *prel)
60-
{
61-
uint32 i;
62-
63-
Assert(PrelIsValid(prel));
64-
65-
/* Remove relevant PartParentInfos */
66-
if ((prel)->children)
67-
{
68-
for (i = 0; i < PrelChildrenCount(prel); i++)
69-
{
70-
Oid child = (prel)->children[i];
71-
72-
/* If it's *always been* relid's partition, free cache */
73-
if (prel->key == get_parent_of_partition(child, NULL))
74-
forget_parent_of_partition(child, NULL);
75-
}
76-
77-
pfree((prel)->children);
78-
(prel)->children = NULL;
79-
}
80-
}
81-
82-
static inline void
83-
FreeRangesArray(PartRelationInfo *prel)
84-
{
85-
uint32 i;
86-
87-
Assert(PrelIsValid(prel));
88-
89-
/* Remove RangeEntries array */
90-
if ((prel)->ranges)
91-
{
92-
/* Remove persistent entries if not byVal */
93-
if (!(prel)->attbyval)
94-
{
95-
for (i = 0; i < PrelChildrenCount(prel); i++)
96-
{
97-
pfree(DatumGetPointer((prel)->ranges[i].min));
98-
pfree(DatumGetPointer((prel)->ranges[i].max));
99-
}
100-
}
101-
102-
pfree((prel)->ranges);
103-
(prel)->ranges = NULL;
104-
}
105-
}
106-
107-
10855
/*
10956
* refresh\invalidate\get\remove PartRelationInfo functions.
11057
*/
@@ -132,6 +79,12 @@ refresh_pathman_relation_info(Oid relid,
13279
"Creating new record for relation %u in pg_pathman's cache [%u]",
13380
relid, MyProcPid);
13481

82+
/*
83+
* NOTE: Trick clang analyzer (first access without NULL pointer check).
84+
* Access to field 'valid' results in a dereference of a null pointer.
85+
*/
86+
prel->cmp_proc = InvalidOid;
87+
13588
/* Clear outdated resources */
13689
if (found && PrelIsValid(prel))
13790
{
@@ -199,24 +152,33 @@ refresh_pathman_relation_info(Oid relid,
199152
void
200153
invalidate_pathman_relation_info(Oid relid, bool *found)
201154
{
202-
PartRelationInfo *prel = hash_search(partitioned_rels,
203-
(const void *) &relid,
204-
(found ? HASH_FIND : HASH_ENTER),
205-
found);
155+
bool prel_found;
156+
HASHACTION action = found ? HASH_FIND : HASH_ENTER;
157+
PartRelationInfo *prel;
206158

207-
if(found && PrelIsValid(prel))
159+
prel = hash_search(partitioned_rels,
160+
(const void *) &relid,
161+
action, &prel_found);
162+
163+
if ((action == HASH_FIND ||
164+
(action == HASH_ENTER && prel_found)) && PrelIsValid(prel))
208165
{
209166
FreeChildrenArray(prel);
210167
FreeRangesArray(prel);
168+
169+
prel->valid = false; /* now cache entry is invalid */
211170
}
212-
/* not found => we create a new one */
213-
else if (!found)
171+
/* Handle invalid PartRelationInfo */
172+
else if (prel)
214173
{
215174
prel->children = NULL;
216175
prel->ranges = NULL;
176+
177+
prel->valid = false; /* now cache entry is invalid */
217178
}
218179

219-
prel->valid = false; /* now cache entry is invalid */
180+
/* Set 'found' if necessary */
181+
if (found) *found = prel_found;
220182

221183
elog(DEBUG2,
222184
"Invalidating record for relation %u in pg_pathman's cache [%u]",
@@ -291,6 +253,13 @@ remove_pathman_relation_info(Oid relid)
291253
* Functions for delayed invalidation.
292254
*/
293255

256+
/* Add new delayed pathman shutdown job (DROP EXTENSION) */
257+
void
258+
delay_pathman_shutdown(void)
259+
{
260+
delayed_shutdown = true;
261+
}
262+
294263
/* Add new delayed invalidation job for a [ex-]parent relation */
295264
void
296265
delay_invalidation_parent_rel(Oid parent)
@@ -311,17 +280,23 @@ finish_delayed_invalidation(void)
311280
{
312281
/* Exit early if there's nothing to do */
313282
if (delayed_invalidation_parent_rels == NIL &&
314-
delayed_invalidation_vague_rels == NIL)
283+
delayed_invalidation_vague_rels == NIL &&
284+
delayed_shutdown == false)
315285
{
316286
return;
317287
}
318288

319289
/* Check that current state is transactional */
320290
if (IsTransactionState())
321291
{
322-
ListCell *lc;
292+
ListCell *lc;
323293

324-
//elog(WARNING, "invalidating...");
294+
if (delayed_shutdown)
295+
{
296+
delayed_shutdown = false;
297+
unload_config();
298+
return;
299+
}
325300

326301
/* Process relations that are (or were) definitely partitioned */
327302
foreach (lc, delayed_invalidation_parent_rels)
@@ -541,8 +516,7 @@ perform_parent_refresh(Oid parent)
541516
parttype = DatumGetPartType(values[Anum_pathman_config_parttype - 1]);
542517
attname = DatumGetTextP(values[Anum_pathman_config_attname - 1]);
543518

544-
if (!refresh_pathman_relation_info(parent, parttype,
545-
text_to_cstring(attname)))
519+
if (!refresh_pathman_relation_info(parent, parttype, text_to_cstring(attname)))
546520
return false;
547521
}
548522
else

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy