@@ -45,17 +45,31 @@ typedef struct PartitionArgs
4545 * waits till it finishes the job and returns the result (new partition oid)
4646 */
4747Oid
48- create_partitions_bg_worker (Oid relid ,Datum value ,Oid value_type , bool * crashed )
48+ create_partitions_bg_worker (Oid relid ,Datum value ,Oid value_type )
4949{
50+ #define HandleError (condition ,new_state ) \
51+ if (condition) { exec_state = (new_state); goto handle_exec_state; }
52+
53+ /* Execution state to be checked */
54+ enum
55+ {
56+ BGW_OK = 0 ,/* everything is fine (default) */
57+ BGW_COULD_NOT_START ,/* could not start worker */
58+ BGW_PM_DIED ,/* postmaster died */
59+ BGW_CRASHED /* worker crashed */
60+ }exec_state = BGW_OK ;
61+
5062BackgroundWorker worker ;
51- BackgroundWorkerHandle * worker_handle ;
52- BgwHandleStatus status ;
53- dsm_segment * segment ;
54- dsm_handle segment_handle ;
55- pid_t pid ;
56- PartitionArgs * args ;
57- Oid child_oid ;
58- TypeCacheEntry * tce ;
63+ BackgroundWorkerHandle * bgw_handle ;
64+ BgwHandleStatus bgw_status ;
65+ bool bgw_started ;
66+ dsm_segment * segment ;
67+ dsm_handle segment_handle ;
68+ pid_t pid ;
69+ PartitionArgs * args ;
70+ TypeCacheEntry * tce ;
71+ Oid child_oid = InvalidOid ;
72+
5973
6074/* Create a dsm segment for the worker to pass arguments */
6175segment = dsm_create (sizeof (PartitionArgs ),0 );
@@ -84,34 +98,53 @@ create_partitions_bg_worker(Oid relid, Datum value, Oid value_type, bool *crashe
8498worker .bgw_main_arg = Int32GetDatum (segment_handle );
8599worker .bgw_notify_pid = MyProcPid ;
86100
101+ LWLockAcquire (pmstate -> load_config_lock ,LW_EXCLUSIVE );
102+ LWLockAcquire (pmstate -> edit_partitions_lock ,LW_EXCLUSIVE );
103+
87104/* Start dynamic worker */
88- if (!RegisterDynamicBackgroundWorker (& worker ,& worker_handle ))
89- {
90- elog (WARNING ,"Unable to create background worker for pg_pathman" );
91- }
105+ bgw_started = RegisterDynamicBackgroundWorker (& worker ,& bgw_handle );
106+ HandleError (bgw_started == false,BGW_COULD_NOT_START );
92107
93- status = WaitForBackgroundWorkerStartup (worker_handle ,& pid );
94- if (status == BGWH_POSTMASTER_DIED )
95- {
96- ereport (WARNING ,
97- (errmsg ("Postmaster died during the pg_pathman background worker process" ),
98- errhint ("More details may be available in the server log." )));
99- }
108+ /* Wait till the worker starts */
109+ bgw_status = WaitForBackgroundWorkerStartup (bgw_handle ,& pid );
110+ HandleError (bgw_status == BGWH_POSTMASTER_DIED ,BGW_PM_DIED );
100111
101- /* Wait till the worker finishes its job */
102- status = WaitForBackgroundWorkerShutdown (worker_handle );
103- if (status == BGWH_POSTMASTER_DIED )
104- {
105- ereport (WARNING ,
106- (errmsg ("Postmaster died during the pg_pathman background worker process" ),
107- errhint ("More details may be available in the server log." )));
108- }
109- * crashed = args -> crashed ;
112+ /* Wait till the worker finishes job */
113+ bgw_status = WaitForBackgroundWorkerShutdown (bgw_handle );
114+ HandleError (bgw_status == BGWH_POSTMASTER_DIED ,BGW_PM_DIED );
115+
116+ /* Save the result (partition Oid) */
110117child_oid = args -> result ;
111118
119+
120+ /* end execution */
121+ handle_exec_state :
122+ LWLockRelease (pmstate -> load_config_lock );
123+ LWLockRelease (pmstate -> edit_partitions_lock );
124+
112125/* Free dsm segment */
113126dsm_detach (segment );
114127
128+ switch (exec_state )
129+ {
130+ case BGW_COULD_NOT_START :
131+ elog (ERROR ,"Unable to create background worker for pg_pathman" );
132+ break ;
133+
134+ case BGW_PM_DIED :
135+ ereport (ERROR ,
136+ (errmsg ("Postmaster died during the pg_pathman background worker process" ),
137+ errhint ("More details may be available in the server log." )));
138+ break ;
139+
140+ case BGW_CRASHED :
141+ elog (ERROR ,"Could not create partition due to background worker crash" );
142+ break ;
143+
144+ default :
145+ break ;
146+ }
147+
115148return child_oid ;
116149}
117150
@@ -129,10 +162,8 @@ bg_worker_main(Datum main_arg)
129162
130163/* Attach to dynamic shared memory */
131164if (!handle )
132- {
133- ereport (WARNING ,
134- (errmsg ("pg_pathman worker: invalid dsm_handle" )));
135- }
165+ ereport (WARNING , (errmsg ("pg_pathman worker: invalid dsm_handle" )));
166+
136167segment = dsm_attach (handle );
137168args = dsm_segment_address (segment );
138169
@@ -163,19 +194,16 @@ bg_worker_main(Datum main_arg)
163194Oid
164195create_partitions (Oid relid ,Datum value ,Oid value_type ,bool * crashed )
165196{
166- int ret ;
167- Datum vals [2 ];
168- Oid oids []= {OIDOID ,value_type };
169- bool nulls []= {false, false};
197+ Oid oids []= {OIDOID ,value_type };
198+ Datum vals []= {ObjectIdGetDatum (relid ),value };
199+ bool nulls []= { false, false };
170200char * sql ;
171201PartRelationInfo * prel ;
172202RangeRelation * rangerel ;
173203FmgrInfo cmp_func ;
174204char * schema ;
175- search_rangerel_result search_state ;
176- RangeEntry found_re ;
177205
178- * crashed = false ;
206+ * crashed = true ;
179207schema = get_extension_schema ();
180208
181209prel = get_pathman_relation_info (relid ,NULL );
@@ -184,36 +212,39 @@ create_partitions(Oid relid, Datum value, Oid value_type, bool *crashed)
184212/* Comparison function */
185213fill_type_cmp_fmgr_info (& cmp_func ,value_type ,prel -> atttype );
186214
187- vals [0 ]= ObjectIdGetDatum (relid );
188- vals [1 ]= value ;
189-
190215/* Perform PL procedure */
191216sql = psprintf ("SELECT %s.append_partitions_on_demand_internal($1, $2)" ,
192217schema );
193218PG_TRY ();
194219{
220+ int ret ;
221+ Oid partid = InvalidOid ;
222+ bool isnull ;
223+
195224ret = SPI_execute_with_args (sql ,2 ,oids ,vals ,nulls , false,0 );
196225if (ret > 0 )
197226{
227+ TupleDesc tupdesc = SPI_tuptable -> tupdesc ;
228+ HeapTuple tuple = SPI_tuptable -> vals [0 ];
229+
230+ Assert (SPI_processed == 1 );
231+
232+ partid = DatumGetObjectId (SPI_getbinval (tuple ,tupdesc ,1 ,& isnull ));
233+
198234/* Update relation info */
199235free_dsm_array (& rangerel -> ranges );
200236free_dsm_array (& prel -> children );
201237load_check_constraints (relid ,GetCatalogSnapshot (relid ));
202238}
239+
240+ * crashed = false;
241+ return partid ;
203242}
204243PG_CATCH ();
205244{
206- elog (WARNING ,"Attempt to create new partitions failed" );
207- if (crashed != NULL )
208- * crashed = true;
209- return 0 ;
245+ elog (ERROR ,"Attempt to create new partitions failed" );
246+
247+ return InvalidOid ;/* compiler should be happy */
210248}
211249PG_END_TRY ();
212-
213- search_state = search_range_partition_eq (value ,& cmp_func ,
214- rangerel ,& found_re );
215- if (search_state == SEARCH_RANGEREL_FOUND )
216- return found_re .child_oid ;
217-
218- return 0 ;
219250}