23
23
#include "utils/builtins.h"
24
24
#include "utils/fmgroids.h"
25
25
#include "utils/hsearch.h"
26
- #include "utils/lsyscache.h"
27
26
#include "utils/memutils.h"
28
27
#include "utils/snapmgr.h"
28
+ #include "utils/syscache.h"
29
+ #include "utils/lsyscache.h"
29
30
#include "utils/typcache.h"
30
31
31
32
@@ -67,23 +68,24 @@ static Oid get_parent_of_partition_internal(Oid partition,
67
68
const PartRelationInfo *
68
69
refresh_pathman_relation_info (Oid relid ,
69
70
PartType partitioning_type ,
70
- const char * part_column_name )
71
+ const char * part_column_name ,
72
+ bool allow_incomplete )
71
73
{
72
74
const LOCKMODE lockmode = AccessShareLock ;
73
75
const TypeCacheEntry * typcache ;
74
76
Oid * prel_children ;
75
77
uint32 prel_children_count = 0 ,
76
78
i ;
77
- bool found ;
79
+ bool found_entry ;
78
80
PartRelationInfo * prel ;
79
81
Datum param_values [Natts_pathman_config_params ];
80
82
bool param_isnull [Natts_pathman_config_params ];
81
83
82
84
prel = (PartRelationInfo * ) hash_search (partitioned_rels ,
83
85
(const void * ) & relid ,
84
- HASH_ENTER , & found );
86
+ HASH_ENTER , & found_entry );
85
87
elog (DEBUG2 ,
86
- found ?
88
+ found_entry ?
87
89
"Refreshing record for relation %u in pg_pathman's cache [%u]" :
88
90
"Creating new record for relation %u in pg_pathman's cache [%u]" ,
89
91
relid , MyProcPid );
@@ -92,25 +94,42 @@ refresh_pathman_relation_info(Oid relid,
92
94
* NOTE: Trick clang analyzer (first access without NULL pointer check).
93
95
* Access to field 'valid' results in a dereference of a null pointer.
94
96
*/
95
- prel -> cmp_proc = InvalidOid ;
97
+ prel -> cmp_proc = InvalidOid ;
96
98
97
99
/* Clear outdated resources */
98
- if (found && PrelIsValid (prel ))
100
+ if (found_entry && PrelIsValid (prel ))
99
101
{
100
102
/* Free these arrays iff they're not NULL */
101
103
FreeChildrenArray (prel );
102
104
FreeRangesArray (prel );
103
105
}
104
106
105
107
/* 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
+ }
107
126
108
127
/* Make both arrays point to NULL */
109
- prel -> children = NULL ;
110
- prel -> ranges = NULL ;
128
+ prel -> children = NULL ;
129
+ prel -> ranges = NULL ;
111
130
112
131
/* Set partitioning type */
113
- prel -> parttype = partitioning_type ;
132
+ prel -> parttype = partitioning_type ;
114
133
115
134
/* Initialize PartRelationInfo using syscache & typcache */
116
135
prel -> attnum = get_attnum (relid , part_column_name );
@@ -135,16 +154,31 @@ refresh_pathman_relation_info(Oid relid,
135
154
prel -> cmp_proc = typcache -> cmp_proc ;
136
155
prel -> hash_proc = typcache -> hash_proc ;
137
156
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 ))
145
162
{
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 ));
148
182
}
149
183
150
184
/*
@@ -155,10 +189,16 @@ refresh_pathman_relation_info(Oid relid,
155
189
*/
156
190
fill_prel_with_partitions (prel_children , prel_children_count , prel );
157
191
158
- /* Add "partition+parent" tuple to cache */
192
+ /* Peform some actions for each child */
159
193
for (i = 0 ; i < prel_children_count ; i ++ )
194
+ {
195
+ /* Add "partition+parent" pair to cache */
160
196
cache_parent_of_partition (prel_children [i ], relid );
161
197
198
+ /* Now it's time to unlock this child */
199
+ UnlockRelationOid (prel_children [i ], lockmode );
200
+ }
201
+
162
202
pfree (prel_children );
163
203
164
204
/* Read additional parameters ('enable_parent' and 'auto' at the moment) */
@@ -245,7 +285,7 @@ get_pathman_relation_info(Oid relid)
245
285
246
286
/* Refresh partitioned table cache entry (might turn NULL) */
247
287
/* 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 );
249
289
}
250
290
/* Else clear remaining cache entry */
251
291
else remove_pathman_relation_info (relid );
@@ -609,10 +649,10 @@ try_perform_parent_refresh(Oid parent)
609
649
parttype = DatumGetPartType (values [Anum_pathman_config_parttype - 1 ]);
610
650
attname = DatumGetTextP (values [Anum_pathman_config_attname - 1 ]);
611
651
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 */
616
656
}
617
657
/* Not a partitioned relation */
618
658
else return false;
0 commit comments