Skip to content

Commit b94b2c1

Browse files
committed
resolve conflict in relation_info.c
2 parents cc320fc + 1eec8ca commit b94b2c1

File tree

5 files changed

+124
-39
lines changed

5 files changed

+124
-39
lines changed

src/init.c

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -466,8 +466,12 @@ fill_prel_with_partitions(const Oid *partitions,
466466
*
467467
* borrowed from pg_inherits.c
468468
*/
469-
Oid *
470-
find_inheritance_children_array(Oid parentrelId, LOCKMODE lockmode, uint32 *size)
469+
find_children_status
470+
find_inheritance_children_array(Oid parentrelId,
471+
LOCKMODE lockmode,
472+
bool nowait,
473+
uint32 *children_size, /* ret value #1 */
474+
Oid **children) /* ret value #2 */
471475
{
472476
Relation relation;
473477
SysScanDesc scan;
@@ -485,8 +489,12 @@ find_inheritance_children_array(Oid parentrelId, LOCKMODE lockmode, uint32 *size
485489
*/
486490
if (!has_subclass(parentrelId))
487491
{
488-
*size = 0;
489-
return NULL;
492+
/* Init return values */
493+
*children_size = 0;
494+
children = NULL;
495+
496+
/* Ok, could not find any children */
497+
return FCS_NO_CHILDREN;
490498
}
491499

492500
/*
@@ -540,7 +548,25 @@ find_inheritance_children_array(Oid parentrelId, LOCKMODE lockmode, uint32 *size
540548
if (lockmode != NoLock)
541549
{
542550
/* Get the lock to synchronize against concurrent drop */
543-
LockRelationOid(inhrelid, lockmode);
551+
if (nowait)
552+
{
553+
if (!ConditionalLockRelationOid(inhrelid, lockmode))
554+
{
555+
uint32 j;
556+
557+
/* Unlock all previously locked children */
558+
for (j = 0; j < i; j++)
559+
UnlockRelationOid(oidarr[j], lockmode);
560+
561+
/* Init return values */
562+
*children_size = numoids;
563+
*children = oidarr;
564+
565+
/* We couldn't lock this child, retreat! */
566+
return FCS_COULD_NOT_LOCK;
567+
}
568+
}
569+
else LockRelationOid(inhrelid, lockmode);
544570

545571
/*
546572
* Now that we have the lock, double-check to see if the relation
@@ -557,8 +583,12 @@ find_inheritance_children_array(Oid parentrelId, LOCKMODE lockmode, uint32 *size
557583
}
558584
}
559585

560-
*size = numoids;
561-
return oidarr;
586+
/* Init return values */
587+
*children_size = numoids;
588+
*children = oidarr;
589+
590+
/* Ok, we have children */
591+
return FCS_FOUND;
562592
}
563593

564594
/*
@@ -752,7 +782,9 @@ read_pathman_config(void)
752782
}
753783

754784
/* Create or update PartRelationInfo for this partitioned table */
755-
refresh_pathman_relation_info(relid, parttype, text_to_cstring(attname));
785+
refresh_pathman_relation_info(relid, parttype,
786+
text_to_cstring(attname),
787+
true); /* allow lazy prel loading */
756788
}
757789

758790
/* Clean resources */

src/init.h

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -109,9 +109,19 @@ void fill_prel_with_partitions(const Oid *partitions,
109109
const uint32 parts_count,
110110
PartRelationInfo *prel);
111111

112-
Oid *find_inheritance_children_array(Oid parentrelId,
113-
LOCKMODE lockmode,
114-
uint32 *size);
112+
/* Result of find_inheritance_children_array() */
113+
typedef enum
114+
{
115+
FCS_NO_CHILDREN = 0, /* could not find any children (GOOD) */
116+
FCS_COULD_NOT_LOCK, /* could not lock one of the children */
117+
FCS_FOUND /* found some children (GOOD) */
118+
} find_children_status;
119+
120+
find_children_status find_inheritance_children_array(Oid parentrelId,
121+
LOCKMODE lockmode,
122+
bool nowait,
123+
uint32 *children_size,
124+
Oid **children);
115125

116126
char *build_check_constraint_name_internal(Oid relid,
117127
AttrNumber attno);

src/pl_funcs.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,9 @@ add_to_pathman_config(PG_FUNCTION_ARGS)
623623
/* Some flags might change during refresh attempt */
624624
save_pathman_init_state(&init_state);
625625

626-
refresh_pathman_relation_info(relid, parttype, text_to_cstring(attname));
626+
refresh_pathman_relation_info(relid, parttype,
627+
text_to_cstring(attname),
628+
false); /* initialize immediately */
627629
}
628630
PG_CATCH();
629631
{

src/relation_info.c

Lines changed: 66 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,10 @@
2323
#include "utils/builtins.h"
2424
#include "utils/fmgroids.h"
2525
#include "utils/hsearch.h"
26-
#include "utils/lsyscache.h"
2726
#include "utils/memutils.h"
2827
#include "utils/snapmgr.h"
28+
#include "utils/syscache.h"
29+
#include "utils/lsyscache.h"
2930
#include "utils/typcache.h"
3031

3132

@@ -67,23 +68,24 @@ static Oid get_parent_of_partition_internal(Oid partition,
6768
const PartRelationInfo *
6869
refresh_pathman_relation_info(Oid relid,
6970
PartType partitioning_type,
70-
const char *part_column_name)
71+
const char *part_column_name,
72+
bool allow_incomplete)
7173
{
7274
const LOCKMODE lockmode = AccessShareLock;
7375
const TypeCacheEntry *typcache;
7476
Oid *prel_children;
7577
uint32 prel_children_count = 0,
7678
i;
77-
bool found;
79+
bool found_entry;
7880
PartRelationInfo *prel;
7981
Datum param_values[Natts_pathman_config_params];
8082
bool param_isnull[Natts_pathman_config_params];
8183

8284
prel = (PartRelationInfo *) hash_search(partitioned_rels,
8385
(const void *) &relid,
84-
HASH_ENTER, &found);
86+
HASH_ENTER, &found_entry);
8587
elog(DEBUG2,
86-
found ?
88+
found_entry ?
8789
"Refreshing record for relation %u in pg_pathman's cache [%u]" :
8890
"Creating new record for relation %u in pg_pathman's cache [%u]",
8991
relid, MyProcPid);
@@ -92,25 +94,42 @@ refresh_pathman_relation_info(Oid relid,
9294
* NOTE: Trick clang analyzer (first access without NULL pointer check).
9395
* Access to field 'valid' results in a dereference of a null pointer.
9496
*/
95-
prel->cmp_proc = InvalidOid;
97+
prel->cmp_proc = InvalidOid;
9698

9799
/* Clear outdated resources */
98-
if (found && PrelIsValid(prel))
100+
if (found_entry && PrelIsValid(prel))
99101
{
100102
/* Free these arrays iff they're not NULL */
101103
FreeChildrenArray(prel);
102104
FreeRangesArray(prel);
103105
}
104106

105107
/* First we assume that this entry is invalid */
106-
prel->valid = false;
108+
prel->valid = false;
109+
110+
/* Try locking parent, exit fast if 'allow_incomplete' */
111+
if (allow_incomplete)
112+
{
113+
if (!ConditionalLockRelationOid(relid, lockmode))
114+
return NULL; /* leave an invalid entry */
115+
}
116+
else LockRelationOid(relid, lockmode);
117+
118+
/* Check if parent exists */
119+
if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(relid)))
120+
{
121+
/* Nope, it doesn't, remove this entry and exit */
122+
UnlockRelationOid(relid, lockmode);
123+
remove_pathman_relation_info(relid);
124+
return NULL; /* exit */
125+
}
107126

108127
/* Make both arrays point to NULL */
109-
prel->children = NULL;
110-
prel->ranges = NULL;
128+
prel->children = NULL;
129+
prel->ranges = NULL;
111130

112131
/* Set partitioning type */
113-
prel->parttype = partitioning_type;
132+
prel->parttype = partitioning_type;
114133

115134
/* Initialize PartRelationInfo using syscache & typcache */
116135
prel->attnum = get_attnum(relid, part_column_name);
@@ -135,16 +154,31 @@ refresh_pathman_relation_info(Oid relid,
135154
prel->cmp_proc = typcache->cmp_proc;
136155
prel->hash_proc = typcache->hash_proc;
137156

138-
LockRelationOid(relid, lockmode);
139-
prel_children = find_inheritance_children_array(relid, lockmode,
140-
&prel_children_count);
141-
UnlockRelationOid(relid, lockmode);
142-
143-
/* If there's no children at all, remove this entry */
144-
if (prel_children_count == 0)
157+
/* Try searching for children (don't wait if we can't lock) */
158+
switch (find_inheritance_children_array(relid, lockmode,
159+
allow_incomplete,
160+
&prel_children_count,
161+
&prel_children))
145162
{
146-
remove_pathman_relation_info(relid);
147-
return NULL;
163+
/* If there's no children at all, remove this entry */
164+
case FCS_NO_CHILDREN:
165+
UnlockRelationOid(relid, lockmode);
166+
remove_pathman_relation_info(relid);
167+
return NULL; /* exit */
168+
169+
/* If can't lock children, leave an invalid entry */
170+
case FCS_COULD_NOT_LOCK:
171+
UnlockRelationOid(relid, lockmode);
172+
return NULL; /* exit */
173+
174+
/* Found some children, just unlock parent */
175+
case FCS_FOUND:
176+
UnlockRelationOid(relid, lockmode);
177+
break; /* continue */
178+
179+
/* Error: unknown result code */
180+
default:
181+
elog(ERROR, "error in " CppAsString(find_inheritance_children_array));
148182
}
149183

150184
/*
@@ -155,10 +189,16 @@ refresh_pathman_relation_info(Oid relid,
155189
*/
156190
fill_prel_with_partitions(prel_children, prel_children_count, prel);
157191

158-
/* Add "partition+parent" tuple to cache */
192+
/* Peform some actions for each child */
159193
for (i = 0; i < prel_children_count; i++)
194+
{
195+
/* Add "partition+parent" pair to cache */
160196
cache_parent_of_partition(prel_children[i], relid);
161197

198+
/* Now it's time to unlock this child */
199+
UnlockRelationOid(prel_children[i], lockmode);
200+
}
201+
162202
pfree(prel_children);
163203

164204
/* Read additional parameters ('enable_parent' and 'auto' at the moment) */
@@ -245,7 +285,7 @@ get_pathman_relation_info(Oid relid)
245285

246286
/* Refresh partitioned table cache entry (might turn NULL) */
247287
/* TODO: possible refactoring, pass found 'prel' instead of searching */
248-
prel = refresh_pathman_relation_info(relid, part_type, attname);
288+
prel = refresh_pathman_relation_info(relid, part_type, attname, false);
249289
}
250290
/* Else clear remaining cache entry */
251291
else remove_pathman_relation_info(relid);
@@ -609,10 +649,10 @@ try_perform_parent_refresh(Oid parent)
609649
parttype = DatumGetPartType(values[Anum_pathman_config_parttype - 1]);
610650
attname = DatumGetTextP(values[Anum_pathman_config_attname - 1]);
611651

612-
/* If anything went wrong, return false (actually, it might throw ERROR) */
613-
if (!PrelIsValid(refresh_pathman_relation_info(parent, parttype,
614-
text_to_cstring(attname))))
615-
return false;
652+
/* If anything went wrong, return false (actually, it might emit ERROR) */
653+
refresh_pathman_relation_info(parent, parttype,
654+
text_to_cstring(attname),
655+
true); /* allow lazy */
616656
}
617657
/* Not a partitioned relation */
618658
else return false;

src/relation_info.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,8 @@ PrelLastChild(const PartRelationInfo *prel)
120120

121121
const PartRelationInfo *refresh_pathman_relation_info(Oid relid,
122122
PartType partitioning_type,
123-
const char *part_column_name);
123+
const char *part_column_name,
124+
bool allow_incomplete);
124125
void invalidate_pathman_relation_info(Oid relid, bool *found);
125126
void remove_pathman_relation_info(Oid relid);
126127
const PartRelationInfo *get_pathman_relation_info(Oid relid);

0 commit comments

Comments
 (0)