@@ -54,8 +54,7 @@ struct WorkerContext {
54
54
}
55
55
56
56
impl WorkerContext {
57
- fn new ( ) -> Self {
58
- let capacity = max_backends ( ) as usize ;
57
+ fn with_capacity ( capacity : usize ) -> Self {
59
58
let tasks = Vec :: with_capacity ( capacity) ;
60
59
let mut states = Vec :: with_capacity ( capacity) ;
61
60
let mut statements = Vec :: with_capacity ( capacity) ;
@@ -88,8 +87,8 @@ impl WorkerContext {
88
87
}
89
88
}
90
89
91
- fn init_slots ( ) -> Result < ( ) > {
92
- for locked_slot in Bus :: new ( ) . into_iter ( ) . flatten ( ) {
90
+ fn init_slots ( holder : i32 ) -> Result < ( ) > {
91
+ for locked_slot in Bus :: new ( ) . into_iter ( holder ) . flatten ( ) {
93
92
let mut stream = SlotStream :: from ( locked_slot) ;
94
93
stream. reset ( ) ;
95
94
let header = Header {
@@ -115,32 +114,41 @@ fn response_error(id: SlotNumber, ctx: &mut WorkerContext, stream: SlotStream, m
115
114
#[ no_mangle]
116
115
pub extern "C" fn worker_main ( _arg : pg_sys:: Datum ) {
117
116
BackgroundWorker :: attach_signal_handlers ( SignalWakeFlags :: SIGHUP | SignalWakeFlags :: SIGTERM ) ;
118
- let mut ctx = WorkerContext :: new ( ) ;
117
+ let capacity = max_backends ( ) as usize ;
118
+ let mut ctx = WorkerContext :: with_capacity ( capacity) ;
119
119
let rt = Builder :: new_multi_thread ( )
120
120
. worker_threads ( TOKIO_THREAD_NUMBER )
121
121
. enable_all ( )
122
122
. build ( )
123
123
. unwrap ( ) ;
124
124
let mut do_retry = false ;
125
- let capacity = max_backends ( ) as usize ;
126
125
let mut errors: Vec < Option < SmolStr > > = vec ! [ None ; capacity] ;
127
126
let mut signals: Vec < bool > = vec ! [ false ; capacity] ;
128
- init_slots ( ) . expect ( "Failed to initialize slots" ) ;
129
- unsafe { set_worker_id ( MyProcNumber ) } ;
127
+ let worker_proc_number = unsafe { MyProcNumber } ;
128
+ init_slots ( worker_proc_number) . expect ( "Failed to initialize slots" ) ;
129
+ set_worker_id ( worker_proc_number) ;
130
130
131
131
log ! ( "DataFusion worker is running" ) ;
132
132
while do_retry || BackgroundWorker :: wait_latch ( Some ( WORKER_WAIT_TIMEOUT ) ) {
133
133
rt. block_on ( async {
134
134
do_retry = false ;
135
- create_tasks ( & mut ctx, & mut errors) . await ;
136
- wait_results ( & mut ctx, & mut errors, & mut signals, & mut do_retry) . await ;
135
+ create_tasks ( & mut ctx, & mut errors, worker_proc_number) . await ;
136
+ wait_results (
137
+ & mut ctx,
138
+ & mut errors,
139
+ & mut signals,
140
+ & mut do_retry,
141
+ worker_proc_number,
142
+ )
143
+ . await ;
137
144
} ) ;
138
145
// Process errors returned by the tasks.
139
146
for ( slot_id, msg) in errors. iter_mut ( ) . enumerate ( ) {
140
147
if let Some ( msg) = msg {
141
148
let stream;
142
149
loop {
143
- let Some ( slot) = Bus :: new ( ) . slot_locked ( slot_id as u32 ) else {
150
+ let Some ( slot) = Bus :: new ( ) . slot_locked ( slot_id as u32 , worker_proc_number)
151
+ else {
144
152
BackgroundWorker :: wait_latch ( Some ( SLOT_WAIT_TIMEOUT ) ) ;
145
153
continue ;
146
154
} ;
@@ -168,8 +176,8 @@ pub extern "C" fn worker_main(_arg: pg_sys::Datum) {
168
176
// runtime, while postgres functions can work only in single thread.
169
177
170
178
/// Process packets from the slots and create tasks for them.
171
- async fn create_tasks ( ctx : & mut WorkerContext , errors : & mut [ Option < SmolStr > ] ) {
172
- for ( id, locked_slot) in Bus :: new ( ) . into_iter ( ) . enumerate ( ) {
179
+ async fn create_tasks ( ctx : & mut WorkerContext , errors : & mut [ Option < SmolStr > ] , holder : i32 ) {
180
+ for ( id, locked_slot) in Bus :: new ( ) . into_iter ( holder ) . enumerate ( ) {
173
181
let Some ( slot) = locked_slot else {
174
182
continue ;
175
183
} ;
@@ -226,12 +234,13 @@ async fn wait_results(
226
234
errors : & mut [ Option < SmolStr > ] ,
227
235
signals : & mut [ bool ] ,
228
236
do_retry : & mut bool ,
237
+ holder : i32 ,
229
238
) {
230
239
for ( id, task) in & mut ctx. tasks {
231
240
let result = task. await . expect ( "Failed to await task" ) ;
232
241
match result {
233
242
Ok ( TaskResult :: Parsing ( ( stmt, tables) ) ) => {
234
- let mut stream = wait_stream ( * id) . await ;
243
+ let mut stream = wait_stream ( * id, holder ) . await ;
235
244
if tables. is_empty ( ) {
236
245
// We don't need any table metadata for this query.
237
246
// So, write a fake metadata packet to the slot and proceed it
@@ -260,7 +269,7 @@ async fn wait_results(
260
269
ctx. statements [ * id as usize ] = Some ( stmt) ;
261
270
}
262
271
Ok ( TaskResult :: Compilation ( plan) ) => {
263
- let mut stream = wait_stream ( * id) . await ;
272
+ let mut stream = wait_stream ( * id, holder ) . await ;
264
273
match request_params ( & mut stream) {
265
274
Ok ( ( ) ) => signals[ * id as usize ] = true ,
266
275
Err ( err) => {
@@ -282,9 +291,9 @@ async fn wait_results(
282
291
}
283
292
284
293
#[ inline( always) ]
285
- async fn wait_stream ( slot_id : u32 ) -> SlotStream {
294
+ async fn wait_stream ( slot_id : u32 , holder : i32 ) -> SlotStream {
286
295
loop {
287
- let Some ( slot) = Bus :: new ( ) . slot_locked ( slot_id) else {
296
+ let Some ( slot) = Bus :: new ( ) . slot_locked ( slot_id, holder ) else {
288
297
tokio:: time:: sleep ( SLOT_WAIT_TIMEOUT ) . await ;
289
298
continue ;
290
299
} ;
@@ -339,6 +348,7 @@ mod tests {
339
348
use super :: * ;
340
349
use crate :: data_type:: { write_scalar_value, EncodedType } ;
341
350
use crate :: ipc:: tests:: { make_slot, SLOT_SIZE } ;
351
+ use crate :: ipc:: { Slot , BUS_PTR } ;
342
352
use crate :: protocol:: prepare_query;
343
353
344
354
#[ tokio:: test]
@@ -503,4 +513,36 @@ mod tests {
503
513
"Projection: Int64(1) [Int64(1):Int64]\n EmptyRelation []" ,
504
514
) ;
505
515
}
516
+
517
+ #[ tokio:: test]
518
+ async fn test_loop ( ) {
519
+ let holder = 42 ;
520
+ let capacity = 2 ;
521
+ let mut ctx = WorkerContext :: with_capacity ( capacity) ;
522
+ let mut errors: Vec < Option < SmolStr > > = vec ! [ None ; capacity] ;
523
+ let mut signals: Vec < bool > = vec ! [ false ; capacity] ;
524
+ let mut do_retry = false ;
525
+ let bus_size = Slot :: estimated_size ( ) * capacity;
526
+ let mut buffer = vec ! [ 0 ; bus_size] ;
527
+ unsafe { BUS_PTR . set ( buffer. as_mut_ptr ( ) as _ ) . unwrap ( ) } ;
528
+ init_slots ( holder) . expect ( "Failed to initialize slots" ) ;
529
+ // Check processing of the parse message.
530
+ let sql = "SELECT * FROM foo" ;
531
+ {
532
+ let slot = Bus :: new ( ) . slot_locked ( 0 , holder) . unwrap ( ) ;
533
+ let mut stream = SlotStream :: from ( slot) ;
534
+ prepare_query ( & mut stream, sql) . unwrap ( ) ;
535
+ }
536
+ create_tasks ( & mut ctx, & mut errors, holder) . await ;
537
+ wait_results ( & mut ctx, & mut errors, & mut signals, & mut do_retry, holder) . await ;
538
+ let error = errors[ 0 ] . take ( ) ;
539
+ assert ! ( error. is_none( ) , "Error: {:?}" , error) ;
540
+ let stmt = ctx. statements [ 0 ] . take ( ) . unwrap ( ) ;
541
+ let expected_stmt = DFParser :: parse_sql ( sql)
542
+ . expect ( "Failed to parse SQL" )
543
+ . into_iter ( )
544
+ . next ( )
545
+ . expect ( "Failed to get statement" ) ;
546
+ assert_eq ! ( stmt, expected_stmt) ;
547
+ }
506
548
}
0 commit comments