@@ -74,17 +74,47 @@ jsonbd_shmem_size(void)
74
74
shm_toc_initialize_estimator (& e );
75
75
76
76
shm_toc_estimate_chunk (& e , sizeof (jsonbd_shm_hdr ));
77
- for (i = 0 ; i < jsonbd_nworkers ; i ++ )
77
+ shm_toc_estimate_chunk (& e , PGSemaphoreShmemSize (1 ));
78
+
79
+ for (i = 0 ; i < MAX_JSONBD_WORKERS ; i ++ )
78
80
{
79
81
shm_toc_estimate_chunk (& e , sizeof (jsonbd_shm_worker ));
80
82
shm_toc_estimate_chunk (& e , jsonbd_get_queue_size ());
81
83
shm_toc_estimate_chunk (& e , jsonbd_get_queue_size ());
82
84
}
83
- shm_toc_estimate_keys (& e , jsonbd_nworkers * 3 + 1 );
85
+
86
+ /* 3 keys each worker + 3 for header (header itself and two queues) */
87
+ shm_toc_estimate_keys (& e , MAX_JSONBD_WORKERS * 3 + 3 );
84
88
size = shm_toc_estimate (& e );
85
89
return size ;
86
90
}
87
91
92
+ static void
93
+ jsonbd_init_worker (shm_toc * toc , jsonbd_shm_worker * wd , int worker_num ,
94
+ size_t queue_size )
95
+ {
96
+ static int mqkey = MAX_JSONBD_WORKERS + 1 ;
97
+
98
+ /* each worker will have two mq, for input and output */
99
+ wd -> mqin = shm_mq_create (shm_toc_allocate (toc , queue_size ), queue_size );
100
+ wd -> mqout = shm_mq_create (shm_toc_allocate (toc , queue_size ), queue_size );
101
+
102
+ /* init worker context */
103
+ pg_atomic_init_flag (& wd -> busy );
104
+ wd -> proc = NULL ;
105
+
106
+ shm_mq_clean_receiver (wd -> mqin );
107
+ shm_mq_clean_receiver (wd -> mqout );
108
+ shm_mq_clean_sender (wd -> mqin );
109
+ shm_mq_clean_sender (wd -> mqout );
110
+
111
+ if (worker_num )
112
+ shm_toc_insert (toc , i + 1 , wd );
113
+
114
+ shm_toc_insert (toc , mqkey ++ , wd -> mqin );
115
+ shm_toc_insert (toc , mqkey ++ , wd -> mqout );
116
+ }
117
+
88
118
static void
89
119
jsonbd_shmem_startup_hook (void )
90
120
{
@@ -102,40 +132,29 @@ jsonbd_shmem_startup_hook(void)
102
132
if (!found )
103
133
{
104
134
int i ;
105
- int mqkey ;
135
+ jsonbd_shm_worker * wd ;
136
+ size_t queue_size = jsonbd_get_queue_size ();
106
137
107
- toc = shm_toc_create (JSONBC_SHM_MQ_MAGIC , workers_data , size );
138
+ toc = shm_toc_create (JSONBD_SHM_MQ_MAGIC , workers_data , size );
139
+
140
+ /* initialize header */
108
141
hdr = shm_toc_allocate (toc , sizeof (jsonbd_shm_hdr ));
109
142
hdr -> workers_ready = 0 ;
110
- sem_init (& hdr -> workers_sem , 1 , jsonbd_nworkers );
111
- shm_toc_insert (toc , 0 , hdr );
112
- mqkey = jsonbd_nworkers + 1 ;
143
+ hdr -> launcher_sem = PGSemaphoreCreate ();
144
+ jsonbd_init_worker (toc , & hdr -> launcher , sizeof (Oid ));
113
145
114
- for (i = 0 ; i < jsonbd_nworkers ; i ++ )
115
- {
116
- size_t queue_size = jsonbd_get_queue_size ();
117
-
118
- jsonbd_shm_worker * wd = shm_toc_allocate (toc , sizeof (jsonbd_shm_worker ));
119
-
120
- /* each worker will have two mq, for input and output */
121
- wd -> mqin = shm_mq_create (shm_toc_allocate (toc , queue_size ), queue_size );
122
- wd -> mqout = shm_mq_create (shm_toc_allocate (toc , queue_size ), queue_size );
146
+ for (i = 0 ; i < MAX_DATABASES ; i ++ )
147
+ sem_init (& hdr -> workers_sem [i ], 1 , jsonbd_nworkers );
123
148
124
- /* init worker context */
125
- pg_atomic_init_flag (& wd -> busy );
126
- wd -> proc = NULL ;
127
-
128
- shm_mq_clean_receiver (wd -> mqin );
129
- shm_mq_clean_receiver (wd -> mqout );
130
- shm_mq_clean_sender (wd -> mqin );
131
- shm_mq_clean_sender (wd -> mqout );
149
+ shm_toc_insert (toc , 0 , hdr );
132
150
133
- shm_toc_insert (toc , i + 1 , wd );
134
- shm_toc_insert (toc , mqkey ++ , wd -> mqin );
135
- shm_toc_insert (toc , mqkey ++ , wd -> mqout );
151
+ for (i = 0 ; i < MAX_JSONBD_WORKERS ; i ++ )
152
+ {
153
+ wd = shm_toc_allocate (toc , sizeof (jsonbd_shm_worker ));
154
+ jsonbd_init_worker (toc , wd , i + 1 , queue_size );
136
155
}
137
156
}
138
- else toc = shm_toc_attach (JSONBC_SHM_MQ_MAGIC , workers_data );
157
+ else toc = shm_toc_attach (JSONBD_SHM_MQ_MAGIC , workers_data );
139
158
140
159
LWLockRelease (AddinShmemInitLock );
141
160
}
@@ -159,8 +178,7 @@ _PG_init(void)
159
178
{
160
179
int i ;
161
180
RequestAddinShmemSpace (jsonbd_shmem_size ());
162
- for (i = 0 ; i < jsonbd_nworkers ; i ++ )
163
- jsonbd_register_worker (i );
181
+ jsonbd_register_worker_launcher ();
164
182
}
165
183
else elog (LOG , "jsonbd: workers are disabled" );
166
184
}
@@ -174,7 +192,7 @@ setup_guc_variables(void)
174
192
& jsonbd_nworkers ,
175
193
1 , /* default */
176
194
0 , /* if zero then no workers */
177
- MAX_JSONBC_WORKERS ,
195
+ MAX_JSONBD_WORKERS ,
178
196
PGC_SUSET ,
179
197
0 ,
180
198
NULL ,
@@ -256,37 +274,90 @@ static void
256
274
jsonbd_communicate (shm_mq_iovec * iov , int iov_len ,
257
275
bool (* callback )(char * , size_t , void * ), void * callback_arg )
258
276
{
259
- int i ;
277
+ int i ,
278
+ j ;
260
279
bool detached = false;
261
280
bool callback_succeded = false;
262
281
shm_mq_result resmq ;
263
282
shm_mq_handle * mqh ;
264
283
jsonbd_shm_hdr * hdr ;
265
- jsonbd_shm_worker * wd ;
284
+ jsonbd_shm_worker * wd ,
285
+ * wd_inner ;
266
286
267
287
char * res ;
268
288
Size reslen ;
289
+ sem_t * cursem = NULL ;
269
290
270
291
if (jsonbd_nworkers <= 0 )
271
292
/* TODO: maybe add support of multiple databases for dictionaries */
272
293
elog (ERROR , "jsonbd workers are not available" );
273
294
274
295
hdr = shm_toc_lookup (toc , 0 , false);
275
- sem_wait (& hdr -> workers_sem );
276
296
277
- for ( i = 0 ; i < jsonbd_nworkers ; i ++ )
297
+ while ( cursem == NULL )
278
298
{
279
- wd = shm_toc_lookup (toc , i + 1 , false);
280
- if (pg_atomic_test_set_flag (& wd -> busy ))
281
- break ;
282
- }
299
+ /* find some not busy worker */
300
+ for (i = 0 ; i < hdr -> workers_ready ; i ++ )
301
+ {
302
+ wd = shm_toc_lookup (toc , i + 1 , false);
303
+ if (wd -> dboid != MyDatabaseId )
304
+ continue ;
305
+
306
+ /*
307
+ * we found first worker for our database, next 'jsonbd_nworkers'
308
+ * workers should be ours, and one of them should be free after sem_wait
309
+ */
310
+ cursem = wd -> dbsem ;
311
+ sem_wait (cursem );
312
+ for (j = i ; j < (i + jsonbd_nworkers ); j ++ )
313
+ {
314
+ wd = shm_toc_lookup (toc , j + 1 , false);
315
+ Assert (wd -> dboid == MyDatabaseId );
316
+ if (pg_atomic_test_set_flag (& wd -> busy ))
317
+ goto comm ;
318
+ }
283
319
284
- if (i == jsonbd_nworkers )
285
- {
286
- sem_post (& hdr -> workers_sem );
287
- elog (ERROR , "jsonbd: could not make a connection with workers" );
320
+ /* should never reach here if all worked correctly */
321
+ sem_post (cursem );
322
+ elog (ERROR , "jsonbd: could not make a connection with workers" );
323
+ }
324
+
325
+ /*
326
+ * there are no workers for our database,
327
+ * so we should launch them using our jsonbd workers launcher
328
+ */
329
+ PGSemaphoreLock (hdr -> launcher_sem );
330
+ shm_mq_set_sender (hdr -> launcher .mqin , MyProc );
331
+ shm_mq_set_receiver (hdr -> launcher .mqout , MyProc );
332
+
333
+ mqh = shm_mq_attach (hdr -> launcher .mqin , NULL , NULL );
334
+ resmq = shm_mq_sendv (mqh ,
335
+ & ((shm_mq_iovec ) {(char * ) & MyDatabaseId , sizeof (MyDatabaseId )}), 1 , false);
336
+ if (resmq != SHM_MQ_SUCCESS )
337
+ detached = true;
338
+ shm_mq_detach (mqh );
339
+
340
+ if (!detached )
341
+ {
342
+ mqh = shm_mq_attach (hdr -> launcher .mqout , NULL , NULL );
343
+ resmq = shm_mq_receive (mqh , & reslen , (void * * ) & res , false);
344
+ if (resmq != SHM_MQ_SUCCESS )
345
+ detached = true;
346
+
347
+ shm_mq_detach (mqh );
348
+ }
349
+
350
+ shm_mq_clean_sender (hdr -> launcher .mqin );
351
+ shm_mq_clean_receiver (hdr -> launcher .mqout );
352
+ PGSemaphoreUnlock (hdr -> launcher_sem );
353
+
354
+ if (detached )
355
+ elog (ERROR , "jsonbd: workers launcher was detached" );
288
356
}
289
357
358
+ goto comm :
359
+ detached = false;
360
+
290
361
/* send data */
291
362
shm_mq_set_sender (wd -> mqin , MyProc );
292
363
shm_mq_set_receiver (wd -> mqout , MyProc );
@@ -315,7 +386,7 @@ jsonbd_communicate(shm_mq_iovec *iov, int iov_len,
315
386
shm_mq_clean_sender (wd -> mqin );
316
387
shm_mq_clean_receiver (wd -> mqout );
317
388
pg_atomic_clear_flag (& wd -> busy );
318
- sem_post (& hdr -> workers_sem );
389
+ sem_post (cursem );
319
390
320
391
if (detached )
321
392
elog (ERROR , "jsonbd: worker has detached" );
@@ -329,7 +400,7 @@ jsonbd_communicate(shm_mq_iovec *iov, int iov_len,
329
400
static void
330
401
jsonbd_worker_get_key_ids (Oid cmoptoid , char * buf , int buflen , uint32 * idsbuf , int nkeys )
331
402
{
332
- JsonbcCommand cmd = JSONBC_CMD_GET_IDS ;
403
+ JsonbcCommand cmd = JSONBD_CMD_GET_IDS ;
333
404
shm_mq_iovec iov [4 ];
334
405
ids_callback_state state ;
335
406
@@ -354,7 +425,7 @@ jsonbd_worker_get_key_ids(Oid cmoptoid, char *buf, int buflen, uint32 *idsbuf, i
354
425
static char *
355
426
jsonbd_worker_get_keys (Oid cmoptoid , uint32 * ids , int nkeys , size_t * buflen )
356
427
{
357
- JsonbcCommand cmd = JSONBC_CMD_GET_KEYS ;
428
+ JsonbcCommand cmd = JSONBD_CMD_GET_KEYS ;
358
429
shm_mq_iovec iov [4 ];
359
430
keys_callback_state state ;
360
431
@@ -478,7 +549,7 @@ memory_reset_callback(void *arg)
478
549
* The result is palloc'd.
479
550
* It adds a space for header, that should be filled later.
480
551
*/
481
- #ifdef PGPRO_JSONBC
552
+ #ifdef PGPRO_JSONBD
482
553
static char *
483
554
packJsonbValue (JsonbValue * val , int header_size , int * len )
484
555
{
0 commit comments