@@ -16,6 +16,8 @@ use postgres_shared::RowData;
16
16
use std:: collections:: HashMap ;
17
17
use std:: fmt;
18
18
use std:: io;
19
+ use std:: mem;
20
+ use std:: sync:: mpsc:: { self , Sender , Receiver } ;
19
21
use tokio_core:: reactor:: Handle ;
20
22
21
23
#[ doc( inline) ]
@@ -40,6 +42,8 @@ pub struct CancelData {
40
42
41
43
struct InnerConnection {
42
44
stream : PostgresStream ,
45
+ close_receiver : Receiver < ( u8 , String ) > ,
46
+ close_sender : Sender < ( u8 , String ) > ,
43
47
parameters : HashMap < String , String > ,
44
48
cancel_data : CancelData ,
45
49
next_stmt_id : u32 ,
@@ -122,8 +126,11 @@ impl Connection {
122
126
stream:: connect ( params. host ( ) , params. port ( ) , handle)
123
127
. map_err ( ConnectError :: Io )
124
128
. map ( |s| {
129
+ let ( sender, receiver) = mpsc:: channel ( ) ;
125
130
Connection ( InnerConnection {
126
131
stream : s,
132
+ close_sender : sender,
133
+ close_receiver : receiver,
127
134
parameters : HashMap :: new ( ) ,
128
135
cancel_data : CancelData {
129
136
process_id : 0 ,
@@ -321,6 +328,7 @@ impl Connection {
321
328
_ => Err ( bad_message ( ) )
322
329
}
323
330
} )
331
+ . and_then ( |( t, s) | s. close_gc ( ) . map ( |s| ( t, s) ) )
324
332
. boxed ( )
325
333
}
326
334
@@ -336,7 +344,9 @@ impl Connection {
336
344
}
337
345
338
346
pub fn batch_execute ( self , query : & str ) -> BoxFuture < Connection , Error > {
339
- self . simple_query ( query) . map ( |r| r. 1 ) . boxed ( )
347
+ self . simple_query ( query)
348
+ . map ( |r| r. 1 )
349
+ . boxed ( )
340
350
}
341
351
342
352
fn raw_prepare ( self ,
@@ -346,9 +356,9 @@ impl Connection {
346
356
let mut parse = vec ! [ ] ;
347
357
let mut describe = vec ! [ ] ;
348
358
let mut sync = vec ! [ ] ;
359
+ frontend:: sync ( & mut sync) ;
349
360
frontend:: parse ( name, query, None , & mut parse)
350
361
. and_then ( |( ) | frontend:: describe ( b'S' , name, & mut describe) )
351
- . and_then ( |( ) | Ok ( frontend:: sync ( & mut sync) ) )
352
362
. into_future ( )
353
363
. and_then ( move |( ) | {
354
364
let it = Some ( parse) . into_iter ( )
@@ -457,6 +467,7 @@ impl Connection {
457
467
let mut bind = vec ! [ ] ;
458
468
let mut execute = vec ! [ ] ;
459
469
let mut sync = vec ! [ ] ;
470
+ frontend:: sync ( & mut sync) ;
460
471
let r = frontend:: bind ( portal,
461
472
stmt,
462
473
Some ( 1 ) ,
@@ -482,10 +493,6 @@ impl Connection {
482
493
. map ( |( ) | s)
483
494
. map_err ( Error :: Io )
484
495
} )
485
- . map ( |s| {
486
- frontend:: sync ( & mut sync) ;
487
- s
488
- } )
489
496
. into_future ( )
490
497
. and_then ( |s| {
491
498
let it = Some ( bind) . into_iter ( )
@@ -546,6 +553,7 @@ impl Connection {
546
553
self . raw_prepare ( & name, query)
547
554
. map ( |( params, columns, conn) | {
548
555
let stmt = Statement {
556
+ close_sender : conn. 0 . close_sender . clone ( ) ,
549
557
name : name,
550
558
params : params,
551
559
columns : columns,
@@ -555,29 +563,41 @@ impl Connection {
555
563
. boxed ( )
556
564
}
557
565
558
- fn raw_close ( self , type_ : u8 , name : & str ) -> BoxFuture < Connection , Error > {
559
- let mut close = vec ! [ ] ;
560
- let mut sync = vec ! [ ] ;
561
- frontend:: close ( type_, name, & mut close)
562
- . map ( |( ) | frontend:: sync ( & mut sync) )
563
- . into_future ( )
564
- . and_then ( move |( ) | {
565
- let it = Some ( close) . into_iter ( ) . chain ( Some ( sync) ) . map ( Ok :: < _ , io:: Error > ) ;
566
- self . 0 . send_all ( futures:: stream:: iter ( it) )
567
- } )
568
- . and_then ( |s| s. 0 . read ( ) )
566
+ fn close_gc ( self ) -> BoxFuture < Connection , Error > {
567
+ let mut messages = vec ! [ ] ;
568
+ while let Ok ( ( type_, name) ) = self . 0 . close_receiver . try_recv ( ) {
569
+ let mut buf = vec ! [ ] ;
570
+ frontend:: close ( type_, & name, & mut buf) . unwrap ( ) ; // this can only fail on bad names
571
+ messages. push ( buf) ;
572
+ }
573
+ if messages. is_empty ( ) {
574
+ return Ok ( self ) . into_future ( ) . boxed ( ) ;
575
+ }
576
+
577
+ let mut buf = vec ! [ ] ;
578
+ frontend:: sync ( & mut buf) ;
579
+ messages. push ( buf) ;
580
+ self . 0 . send_all ( futures:: stream:: iter ( messages. into_iter ( ) . map ( Ok :: < _ , io:: Error > ) ) )
581
+ . map_err ( Error :: Io )
582
+ . and_then ( |s| Connection ( s. 0 ) . finish_close_gc ( ) )
583
+ . boxed ( )
584
+ }
585
+
586
+ fn finish_close_gc ( self ) -> BoxFuture < Connection , Error > {
587
+ self . 0 . read ( )
569
588
. map_err ( Error :: Io )
570
589
. and_then ( |( m, s) | {
571
590
match m {
572
- backend:: Message :: CloseComplete => Either :: A ( Ok ( Connection ( s) ) . into_future ( ) ) ,
591
+ backend:: Message :: ReadyForQuery ( _) => {
592
+ Either :: A ( Ok ( Connection ( s) ) . into_future ( ) )
593
+ }
594
+ backend:: Message :: CloseComplete => Either :: B ( Connection ( s) . finish_close_gc ( ) ) ,
573
595
backend:: Message :: ErrorResponse ( body) => {
574
596
Either :: B ( Connection ( s) . ready_err ( body) )
575
597
}
576
598
_ => Either :: A ( Err ( bad_message ( ) ) . into_future ( ) ) ,
577
599
}
578
600
} )
579
- . and_then ( |s| s. ready ( ( ) ) )
580
- . map ( |( ( ) , s) | s)
581
601
. boxed ( )
582
602
}
583
603
@@ -601,11 +621,19 @@ struct Column {
601
621
}
602
622
603
623
pub struct Statement {
624
+ close_sender : Sender < ( u8 , String ) > ,
604
625
name : String ,
605
626
params : Vec < Type > ,
606
627
columns : Vec < Column > ,
607
628
}
608
629
630
+ impl Drop for Statement {
631
+ fn drop ( & mut self ) {
632
+ let name = mem:: replace ( & mut self . name , String :: new ( ) ) ;
633
+ let _ = self . close_sender . send ( ( b'S' , name) ) ;
634
+ }
635
+ }
636
+
609
637
impl Statement {
610
638
pub fn execute ( self ,
611
639
params : & [ & ToSql ] ,
@@ -616,10 +644,6 @@ impl Statement {
616
644
. map ( |( n, conn) | ( n, self , conn) )
617
645
. boxed ( )
618
646
}
619
-
620
- pub fn close ( self , conn : Connection ) -> BoxFuture < Connection , Error > {
621
- conn. raw_close ( b'S' , & self . name )
622
- }
623
647
}
624
648
625
649
fn connect_err ( fields : & mut ErrorFields ) -> ConnectError {
0 commit comments