@@ -28,17 +28,15 @@ static WorkerState *worker_state = NULL;
28
28
static const int curl_handle_event_timeout_ms = 1000 ;
29
29
static const int net_worker_restart_time_sec = 1 ;
30
30
static const long no_timeout = -1L ;
31
- static bool extension_locked = false;
32
31
static bool wake_commit_cb_active = false;
33
32
static bool worker_should_restart = false;
33
+ static const size_t total_extension_tables = 2 ;
34
34
35
35
static char * guc_ttl ;
36
36
static int guc_batch_size ;
37
37
static char * guc_database_name ;
38
38
static char * guc_username ;
39
39
static MemoryContext CurlMemContext = NULL ;
40
- static LockRelId queue_table_lock ;
41
- static LockRelId response_table_lock ;
42
40
static shmem_startup_hook_type prev_shmem_startup_hook = NULL ;
43
41
static volatile sig_atomic_t got_sighup = false;
44
42
@@ -147,54 +145,11 @@ static void publish_state(WorkerStatus s) {
147
145
ConditionVariableBroadcast (& worker_state -> cv );
148
146
}
149
147
150
- static bool is_extension_loaded (){
151
- StartTransactionCommand ();
152
-
153
- bool extension_exists = OidIsValid (get_extension_oid ("pg_net" , true));
154
-
155
- if (extension_exists && !extension_locked ){
156
- Oid db_oid = get_database_oid (guc_database_name , false);
157
-
158
- Oid net_oid = get_namespace_oid ("net" , false);
159
-
160
- queue_table_lock .dbId = db_oid ;
161
- queue_table_lock .relId = get_relname_relid ("http_request_queue" , net_oid );
162
-
163
- response_table_lock .dbId = db_oid ;
164
- response_table_lock .relId = get_relname_relid ("_http_response" , net_oid );
165
- }
166
-
167
- CommitTransactionCommand ();
168
-
169
- return extension_exists ;
170
- }
171
-
172
- static inline void lock_extension (){
173
- if (!extension_locked ){
174
- elog (DEBUG1 , "pg_net worker locking extension tables" );
175
- LockRelationIdForSession (& queue_table_lock , AccessShareLock );
176
- LockRelationIdForSession (& response_table_lock , AccessShareLock );
177
- extension_locked = true;
178
- }
179
- }
180
-
181
- static inline void unlock_extension (){
182
- if (extension_locked ){
183
- elog (DEBUG1 , "pg_net worker unlocking extension tables" );
184
- UnlockRelationIdForSession (& queue_table_lock , AccessShareLock );
185
- UnlockRelationIdForSession (& response_table_lock , AccessShareLock );
186
- extension_locked = false;
187
- }
188
- }
189
-
190
148
static void
191
149
net_on_exit (__attribute__ ((unused )) int code , __attribute__ ((unused )) Datum arg ){
192
150
worker_should_restart = false;
193
151
pg_atomic_write_u32 (& worker_state -> should_wake , 1 ); // ensure the remaining work will continue since we'll restart
194
152
195
- // ensure unlock happens in case of error
196
- unlock_extension ();
197
-
198
153
DisownLatch (& worker_state -> latch );
199
154
200
155
ev_monitor_close (worker_state );
@@ -231,6 +186,31 @@ static void wait_while_processing_interrupts(WorkerWait ww, bool *should_restart
231
186
}
232
187
}
233
188
189
+ static bool is_extension_locked (Oid ext_table_oids [static total_extension_tables ]){
190
+ Oid net_oid = get_namespace_oid ("net" , true);
191
+
192
+ if (!OidIsValid (net_oid )){
193
+ return false;
194
+ }
195
+
196
+ Oid queue_oid = get_relname_relid ("http_request_queue" , net_oid );
197
+ Oid resp_oid = get_relname_relid ("_http_response" , net_oid );
198
+
199
+ bool is_locked = ConditionalLockRelationOid (queue_oid , AccessShareLock ) && ConditionalLockRelationOid (resp_oid , AccessShareLock );
200
+
201
+ if (is_locked ) {
202
+ ext_table_oids [0 ] = queue_oid ;
203
+ ext_table_oids [1 ] = resp_oid ;
204
+ }
205
+
206
+ return is_locked ;
207
+ }
208
+
209
+ static void unlock_extension (Oid ext_table_oids [static total_extension_tables ]){
210
+ UnlockRelationOid (ext_table_oids [0 ], AccessShareLock );
211
+ UnlockRelationOid (ext_table_oids [1 ], AccessShareLock );
212
+ }
213
+
234
214
void pg_net_worker (__attribute__ ((unused )) Datum main_arg ) {
235
215
on_proc_exit (net_on_exit , 0 );
236
216
@@ -266,17 +246,8 @@ void pg_net_worker(__attribute__ ((unused)) Datum main_arg) {
266
246
267
247
do {
268
248
269
- if (!is_extension_loaded ()){
270
- elog (DEBUG1 , "pg_net worker waiting for extension to load" );
271
- wait_while_processing_interrupts (WORKER_WAIT_ONE_SECOND , & worker_should_restart );
272
- continue ;
273
- }
274
-
275
- lock_extension (); // lock the extension immediately after it's loaded
276
-
277
249
uint32 expected = 1 ;
278
250
if (!pg_atomic_compare_exchange_u32 (& worker_state -> should_wake , & expected , 0 )){
279
- unlock_extension ();
280
251
elog (DEBUG1 , "pg_net worker waiting for wake" );
281
252
wait_while_processing_interrupts (WORKER_WAIT_NO_TIMEOUT , & worker_should_restart );
282
253
continue ;
@@ -286,13 +257,23 @@ void pg_net_worker(__attribute__ ((unused)) Datum main_arg) {
286
257
uint64 expired_responses = 0 ;
287
258
288
259
do {
260
+ SetCurrentStatementStartTimestamp ();
261
+ StartTransactionCommand ();
262
+ PushActiveSnapshot (GetTransactionSnapshot ());
263
+
264
+ Oid ext_table_oids [total_extension_tables ];
265
+
266
+ if (!is_extension_locked (ext_table_oids )){
267
+ elog (DEBUG1 , "pg_net extension not loaded" );
268
+ PopActiveSnapshot ();
269
+ AbortCurrentTransaction ();
270
+ break ;
271
+ }
272
+
289
273
expired_responses = delete_expired_responses (guc_ttl , guc_batch_size );
290
274
291
275
elog (DEBUG1 , "Deleted " UINT64_FORMAT " expired rows" , expired_responses );
292
276
293
- StartTransactionCommand ();
294
- PushActiveSnapshot (GetTransactionSnapshot ());
295
-
296
277
requests_consumed = consume_request_queue (worker_state -> curl_mhandle , guc_batch_size , CurlMemContext );
297
278
298
279
elog (DEBUG1 , "Consumed " UINT64_FORMAT " request rows" , requests_consumed );
@@ -341,6 +322,8 @@ void pg_net_worker(__attribute__ ((unused)) Datum main_arg) {
341
322
} while (running_handles > 0 ); // run while there are curl handles, some won't finish in a single iteration since they could be slow and waiting for a timeout
342
323
}
343
324
325
+ unlock_extension (ext_table_oids );
326
+
344
327
PopActiveSnapshot ();
345
328
CommitTransactionCommand ();
346
329
@@ -353,8 +336,6 @@ void pg_net_worker(__attribute__ ((unused)) Datum main_arg) {
353
336
354
337
} while (!worker_should_restart );
355
338
356
- unlock_extension ();
357
-
358
339
publish_state (WS_EXITED );
359
340
360
341
// causing a failure on exit will make the postmaster process restart the bg worker
0 commit comments