@@ -57,6 +57,10 @@ impl Storage {
5757 * self = Self :: default ( ) ;
5858 self . registry = registry;
5959 }
60+
61+ pub fn set_registry_conn ( & mut self , conn_id : usize ) {
62+ self . registry = Arc :: new ( crate :: pgscan:: ScanRegistry :: with_conn ( conn_id) ) ;
63+ }
6064}
6165
6266pub struct Connection < ' bytes > {
@@ -87,6 +91,11 @@ impl<'bytes> Connection<'bytes> {
8791 }
8892
8993 pub async fn poll ( & mut self ) -> Result < ( ) > {
94+ let pending = self . recv_socket . buffer . len ( ) ;
95+ if pending > 0 {
96+ trace ! ( "poll: data already available: {} bytes" , pending) ;
97+ return Ok ( ( ) ) ;
98+ }
9099 trace ! ( "poll: waiting for socket signal" ) ;
91100 ( & mut self . recv_socket ) . await ?;
92101 trace ! (
@@ -135,6 +144,13 @@ impl<'bytes> Connection<'bytes> {
135144 }
136145
137146 pub async fn process_message ( & mut self , storage : & mut Storage ) -> Result < ( ) > {
147+ // Guard against spurious wakeups where no bytes are available yet.
148+ let pending = self . recv_socket . buffer . len ( ) ;
149+ if pending < 6 {
150+ // Header is at least 6 bytes (3 fixints + u16)
151+ trace ! ( "process_message: woke but no header bytes available" , ) ;
152+ return Ok ( ( ) ) ;
153+ }
138154 let header = consume_header ( & mut self . recv_socket . buffer ) ?;
139155 debug ! (
140156 direction = ?header. direction,
@@ -152,6 +168,8 @@ impl<'bytes> Connection<'bytes> {
152168 // Column layout arrives during planning/prepare; store it for later encoding use.
153169 if header. tag == ControlPacket :: ColumnLayout as u8 {
154170 let attrs = consume_column_layout ( & mut self . recv_socket . buffer ) ?;
171+ let len = attrs. len ( ) ;
172+ tracing:: trace!( target = "executor::server" , pg_attrs = len, "column layout received" ) ;
155173 storage. pg_attrs = Some ( attrs) ;
156174 return Ok ( ( ) ) ;
157175 }
@@ -162,6 +180,16 @@ impl<'bytes> Connection<'bytes> {
162180 // Read metadata; we expect the visibility bitmap to be stored in shared memory.
163181 let meta =
164182 read_heap_block_bitmap_meta ( & mut self . recv_socket . buffer , header. length ) ?;
183+ trace ! (
184+ target = "executor::server" ,
185+ scan_id = meta. scan_id,
186+ slot_id = meta. slot_id,
187+ table_oid = meta. table_oid,
188+ blkno = meta. blkno,
189+ num_offsets = meta. num_offsets,
190+ bitmap_inline_len = meta. bitmap_len,
191+ "heap bitmap meta received"
192+ ) ;
165193 // If payload included inline bitmap bytes (legacy), drain them without allocation.
166194 let mut remaining = meta. bitmap_len as usize ;
167195 while remaining > 0 {
@@ -172,6 +200,13 @@ impl<'bytes> Connection<'bytes> {
172200 }
173201 // Trailing u16 carries the visibility bitmap length in shared memory
174202 let vis_len = read_u16_msgpack ( & mut self . recv_socket . buffer ) ?;
203+ trace ! (
204+ target = "executor::server" ,
205+ scan_id = meta. scan_id,
206+ slot_id = meta. slot_id,
207+ vis_len,
208+ "heap bitmap vis_len (shm) received"
209+ ) ;
175210 if let Some ( tx) = storage. registry . sender ( meta. scan_id as u64 ) {
176211 let block = crate :: pgscan:: HeapBlock {
177212 scan_id : meta. scan_id as u64 ,
@@ -190,6 +225,13 @@ impl<'bytes> Connection<'bytes> {
190225 ) ;
191226 }
192227 // Request the next heap block for this scan using the same slot
228+ trace ! (
229+ target = "executor::server" ,
230+ scan_id = meta. scan_id,
231+ table_oid = meta. table_oid,
232+ slot_id = meta. slot_id,
233+ "requesting next heap block"
234+ ) ;
193235 if let Err ( e) = request_heap_block (
194236 & mut self . send_buffer ,
195237 meta. scan_id ,
@@ -411,6 +453,13 @@ fn encode_and_write_rows(
411453 let rows = batch. num_rows ( ) ;
412454 let cols = std:: cmp:: min ( batch. num_columns ( ) , attrs. len ( ) ) ;
413455 if cols == 0 || rows == 0 {
456+ tracing:: trace!(
457+ target = "executor::server" ,
458+ rows,
459+ cols,
460+ attrs = attrs. len( ) ,
461+ "execution: empty batch or no attrs; skipping write"
462+ ) ;
414463 return 0 ;
415464 }
416465 // Working buffers reused across rows to minimize allocations
@@ -554,9 +603,11 @@ fn open_data_flow(_conn: &mut Connection, storage: &mut Storage) -> Result<TaskR
554603 let phys = storage. physical_plan . as_ref ( ) . expect ( "checked above" ) ;
555604 // Reserve capacity to avoid HashMap reallocation while registering
556605 let scan_count = count_scans ( phys) as usize ;
606+ trace ! ( scan_count, "open_data_flow: reserving scan registry capacity" ) ;
557607 storage. registry . reserve ( scan_count) ;
558608 // Register channels per scan in the connection-local registry; no response payload
559- let _ = for_each_scan :: < _ , Error > ( phys, |id, _table_oid| {
609+ let _ = for_each_scan :: < _ , Error > ( phys, |id, table_oid| {
610+ trace ! ( scan_id = id, table_oid, "open_data_flow: registering scan channel" ) ;
560611 let _ = storage. registry . register ( id, 16 ) ;
561612 Ok ( ( ) )
562613 } ) ;
@@ -578,6 +629,7 @@ fn start_data_flow(conn: &mut Connection, storage: &mut Storage) -> Result<TaskR
578629
579630 let plan = Arc :: clone ( storage. physical_plan . as_ref ( ) . expect ( "checked above" ) ) ;
580631 let pg_attrs = storage. pg_attrs . clone ( ) . unwrap_or_default ( ) ;
632+ tracing:: trace!( target = "executor::server" , pg_attrs = pg_attrs. len( ) , "start_data_flow: attrs snapshot" ) ;
581633 // Build a fresh TaskContext for execution
582634 let state = SessionStateBuilder :: new ( ) . build ( ) ;
583635 let ctx = state. task_ctx ( ) ;
@@ -586,6 +638,7 @@ fn start_data_flow(conn: &mut Connection, storage: &mut Storage) -> Result<TaskR
586638 let client_pid_val = conn
587639 . client_pid
588640 . load ( std:: sync:: atomic:: Ordering :: Relaxed ) ; // snapshot pid
641+ trace ! ( conn_id, "start_data_flow: spawning execution task" ) ;
589642 let handle = tokio:: spawn ( async move {
590643 // Execute a single partition; PgScanExec uses a single stream
591644 match plan. execute ( 0 , ctx) {
@@ -606,6 +659,12 @@ fn start_data_flow(conn: &mut Connection, storage: &mut Storage) -> Result<TaskR
606659 continue ;
607660 }
608661 let wrote = encode_and_write_rows ( & batch, & pg_attrs, & mut ring) ;
662+ tracing:: trace!(
663+ target = "executor::server" ,
664+ rows = wrote,
665+ cols = batch. num_columns( ) ,
666+ "execution: batch encoded and written"
667+ ) ;
609668 if wrote > 0 {
610669 let pid = client_pid_val;
611670 if pid > 0 && pid != i32:: MAX {
@@ -618,6 +677,11 @@ fn start_data_flow(conn: &mut Connection, storage: &mut Storage) -> Result<TaskR
618677 tracing:: trace!( target = "pg_fusion::server" , "execution stream completed" ) ;
619678 // Write EOF sentinel row to result ring to unblock backend
620679 let _ = protocol:: result:: write_eof ( & mut ring) ;
680+ // Nudge the backend in case it is waiting on latch
681+ let pid = client_pid_val;
682+ if pid > 0 && pid != i32:: MAX {
683+ unsafe { libc:: kill ( pid as libc:: pid_t , libc:: SIGUSR1 ) } ;
684+ }
621685 }
622686 Err ( e) => {
623687 tracing:: error!(
@@ -629,11 +693,13 @@ fn start_data_flow(conn: &mut Connection, storage: &mut Storage) -> Result<TaskR
629693 } ) ;
630694 storage. exec_task = Some ( handle) ;
631695 // Send a tiny ack to the backend indicating execution is ready
696+ trace ! ( "start_data_flow: sending ExecReady to backend" ) ;
632697 protocol:: exec:: prepare_exec_ready ( & mut conn. send_buffer ) ?;
633698 // No demo row: result rows will be written by the execution task
634699 // Kick off initial heap block requests for each scan using slot 0
635700 if let Some ( phys) = storage. physical_plan . as_ref ( ) {
636701 let _ = for_each_scan :: < _ , Error > ( phys, |id, table_oid| {
702+ trace ! ( scan_id = id, table_oid, slot_id = 0 , "start_data_flow: initial heap request" ) ;
637703 request_heap_block ( & mut conn. send_buffer , id, table_oid, 0 ) ?;
638704 Ok ( ( ) )
639705 } ) ;
@@ -642,12 +708,9 @@ fn start_data_flow(conn: &mut Connection, storage: &mut Storage) -> Result<TaskR
642708}
643709
644710fn end_data_flow ( storage : & mut Storage ) -> Result < TaskResult > {
645- // Cancel running execution task if present
646- if let Some ( handle) = storage. exec_task . take ( ) {
647- handle. abort ( ) ;
648- }
649- // Close and clear all registered scan channels
650- storage. registry . close_and_clear ( ) ;
711+ // Use unified reset to ensure state machine returns to Initialized and
712+ // any in-flight execution task is aborted, while preserving registry object.
713+ storage. flush ( ) ;
651714 Ok ( TaskResult :: Noop )
652715}
653716
0 commit comments