@@ -45,17 +45,31 @@ typedef struct PartitionArgs
45
45
* waits till it finishes the job and returns the result (new partition oid)
46
46
*/
47
47
Oid
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 )
49
49
{
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
+
50
62
BackgroundWorker 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
+
59
73
60
74
/* Create a dsm segment for the worker to pass arguments */
61
75
segment = dsm_create (sizeof (PartitionArgs ),0 );
@@ -84,34 +98,53 @@ create_partitions_bg_worker(Oid relid, Datum value, Oid value_type, bool *crashe
84
98
worker .bgw_main_arg = Int32GetDatum (segment_handle );
85
99
worker .bgw_notify_pid = MyProcPid ;
86
100
101
+ LWLockAcquire (pmstate -> load_config_lock ,LW_EXCLUSIVE );
102
+ LWLockAcquire (pmstate -> edit_partitions_lock ,LW_EXCLUSIVE );
103
+
87
104
/* 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 );
92
107
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 );
100
111
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) */
110
117
child_oid = args -> result ;
111
118
119
+
120
+ /* end execution */
121
+ handle_exec_state :
122
+ LWLockRelease (pmstate -> load_config_lock );
123
+ LWLockRelease (pmstate -> edit_partitions_lock );
124
+
112
125
/* Free dsm segment */
113
126
dsm_detach (segment );
114
127
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
+
115
148
return child_oid ;
116
149
}
117
150
@@ -129,10 +162,8 @@ bg_worker_main(Datum main_arg)
129
162
130
163
/* Attach to dynamic shared memory */
131
164
if (!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
+
136
167
segment = dsm_attach (handle );
137
168
args = dsm_segment_address (segment );
138
169
@@ -163,19 +194,16 @@ bg_worker_main(Datum main_arg)
163
194
Oid
164
195
create_partitions (Oid relid ,Datum value ,Oid value_type ,bool * crashed )
165
196
{
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 };
170
200
char * sql ;
171
201
PartRelationInfo * prel ;
172
202
RangeRelation * rangerel ;
173
203
FmgrInfo cmp_func ;
174
204
char * schema ;
175
- search_rangerel_result search_state ;
176
- RangeEntry found_re ;
177
205
178
- * crashed = false ;
206
+ * crashed = true ;
179
207
schema = get_extension_schema ();
180
208
181
209
prel = get_pathman_relation_info (relid ,NULL );
@@ -184,36 +212,39 @@ create_partitions(Oid relid, Datum value, Oid value_type, bool *crashed)
184
212
/* Comparison function */
185
213
fill_type_cmp_fmgr_info (& cmp_func ,value_type ,prel -> atttype );
186
214
187
- vals [0 ]= ObjectIdGetDatum (relid );
188
- vals [1 ]= value ;
189
-
190
215
/* Perform PL procedure */
191
216
sql = psprintf ("SELECT %s.append_partitions_on_demand_internal($1, $2)" ,
192
217
schema );
193
218
PG_TRY ();
194
219
{
220
+ int ret ;
221
+ Oid partid = InvalidOid ;
222
+ bool isnull ;
223
+
195
224
ret = SPI_execute_with_args (sql ,2 ,oids ,vals ,nulls , false,0 );
196
225
if (ret > 0 )
197
226
{
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
+
198
234
/* Update relation info */
199
235
free_dsm_array (& rangerel -> ranges );
200
236
free_dsm_array (& prel -> children );
201
237
load_check_constraints (relid ,GetCatalogSnapshot (relid ));
202
238
}
239
+
240
+ * crashed = false;
241
+ return partid ;
203
242
}
204
243
PG_CATCH ();
205
244
{
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 */
210
248
}
211
249
PG_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 ;
219
250
}