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,
6768const PartRelationInfo *
6869refresh_pathman_relation_info (Oid relid ,
6970PartType partitioning_type ,
70- const char * part_column_name )
71+ const char * part_column_name ,
72+ bool allow_incomplete )
7173{
7274const LOCKMODE lockmode = AccessShareLock ;
7375const TypeCacheEntry * typcache ;
7476Oid * prel_children ;
7577uint32 prel_children_count = 0 ,
7678i ;
77- bool found ;
79+ bool found_entry ;
7880PartRelationInfo * prel ;
7981Datum param_values [Natts_pathman_config_params ];
8082bool param_isnull [Natts_pathman_config_params ];
8183
8284prel = (PartRelationInfo * )hash_search (partitioned_rels ,
8385(const void * )& relid ,
84- HASH_ENTER ,& found );
86+ HASH_ENTER ,& found_entry );
8587elog (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]" ,
8991relid ,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 */
101103FreeChildrenArray (prel );
102104FreeRangesArray (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 */
116135prel -> attnum = get_attnum (relid ,part_column_name );
@@ -135,16 +154,31 @@ refresh_pathman_relation_info(Oid relid,
135154prel -> cmp_proc = typcache -> cmp_proc ;
136155prel -> 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 */
156190fill_prel_with_partitions (prel_children ,prel_children_count ,prel );
157191
158- /*Add "partition+parent" tuple to cache */
192+ /*Peform some actions for each child */
159193for (i = 0 ;i < prel_children_count ;i ++ )
194+ {
195+ /* Add "partition+parent" pair to cache */
160196cache_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+
162202pfree (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 */
251291else remove_pathman_relation_info (relid );
@@ -609,10 +649,10 @@ try_perform_parent_refresh(Oid parent)
609649parttype = DatumGetPartType (values [Anum_pathman_config_parttype - 1 ]);
610650attname = DatumGetTextP (values [Anum_pathman_config_attname - 1 ]);
611651
612- /* If anything went wrong, return false (actually, it mightthrow 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 mightemit ERROR) */
653+ refresh_pathman_relation_info (parent ,parttype ,
654+ text_to_cstring (attname ),
655+ true); /* allow lazy */
616656}
617657/* Not a partitioned relation */
618658else return false;