@@ -65,21 +65,23 @@ extern crate phf;
6565extern crate phf_mac;
6666#[ phase( plugin, link) ]
6767extern crate log;
68+ extern crate time;
6869
6970use url:: Url ;
7071use openssl:: crypto:: hash:: { HashType , Hasher } ;
7172use openssl:: ssl:: { SslContext , MaybeSslStream } ;
7273use serialize:: hex:: ToHex ;
7374use std:: cell:: { Cell , RefCell } ;
7475use std:: collections:: { RingBuf , HashMap } ;
75- use std:: io:: { BufferedStream , IoResult } ;
76+ use std:: io:: { BufferedStream , IoResult , IoError , IoErrorKind } ;
7677use std:: io:: net:: ip:: Port ;
7778use std:: iter:: IteratorCloneExt ;
79+ use std:: time:: Duration ;
7880use std:: mem;
7981use std:: fmt;
8082use std:: result;
8183
82- use io:: InternalStream ;
84+ use io:: { InternalStream , Timeout } ;
8385use message:: { FrontendMessage , BackendMessage , RowDescriptionEntry } ;
8486use message:: FrontendMessage :: * ;
8587use message:: BackendMessage :: * ;
@@ -248,8 +250,9 @@ impl<'conn> Notifications<'conn> {
248250 return Ok ( notification) ;
249251 }
250252
251- check_desync ! ( self . conn. conn. borrow( ) ) ;
252- match try!( self . conn . conn . borrow_mut ( ) . read_message_with_notification ( ) ) {
253+ let mut conn = self . conn . conn . borrow_mut ( ) ;
254+ check_desync ! ( conn) ;
255+ match try!( conn. read_message_with_notification ( ) ) {
253256 NotificationResponse { pid, channel, payload } => {
254257 Ok ( Notification {
255258 pid : pid,
@@ -260,6 +263,42 @@ impl<'conn> Notifications<'conn> {
260263 _ => unreachable ! ( )
261264 }
262265 }
266+
267+ /// Returns the oldest pending notification
268+ ///
269+ /// If no notifications are pending, blocks for up to `timeout` time, after
270+ /// which an `IoError` with the `TimedOut` kind is returned.
271+ pub fn next_block_for ( & mut self , timeout : Duration ) -> Result < Notification > {
272+ if let Some ( notification) = self . next ( ) {
273+ return Ok ( notification) ;
274+ }
275+
276+ let mut conn = self . conn . conn . borrow_mut ( ) ;
277+ check_desync ! ( conn) ;
278+
279+ let end = time:: now ( ) . to_timespec ( ) + timeout;
280+ loop {
281+ let now = time:: now ( ) . to_timespec ( ) ;
282+ conn. stream . set_read_timeout ( Some ( ( end - now) . num_milliseconds ( ) as u64 ) ) ;
283+ match conn. read_one_message ( ) {
284+ Ok ( Some ( NotificationResponse { pid, channel, payload } ) ) => {
285+ return Ok ( Notification {
286+ pid : pid,
287+ channel : channel,
288+ payload : payload
289+ } )
290+ }
291+ Ok ( Some ( _) ) => unreachable ! ( ) ,
292+ Ok ( None ) => { }
293+ Err ( e @ IoError { kind : IoErrorKind :: TimedOut , .. } ) => {
294+ conn. desynchronized = false ;
295+ return Err ( Error :: IoError ( e) ) ;
296+ }
297+ Err ( e) => return Err ( Error :: IoError ( e) ) ,
298+ }
299+
300+ }
301+ }
263302}
264303
265304/// Contains information necessary to cancel queries for a session
@@ -394,19 +433,27 @@ impl InnerConnection {
394433 Ok ( try_desync ! ( self , self . stream. flush( ) ) )
395434 }
396435
397- fn read_message_with_notification ( & mut self ) -> IoResult < BackendMessage > {
436+ fn read_one_message ( & mut self ) -> IoResult < Option < BackendMessage > > {
398437 debug_assert ! ( !self . desynchronized) ;
399- loop {
400- match try_desync ! ( self , self . stream. read_message( ) ) {
401- NoticeResponse { fields } => {
402- if let Ok ( err) = DbError :: new_raw ( fields) {
403- self . notice_handler . handle ( err) ;
404- }
405- }
406- ParameterStatus { parameter, value } => {
407- debug ! ( "Parameter {} = {}" , parameter, value)
438+ match try_desync ! ( self , self . stream. read_message( ) ) {
439+ NoticeResponse { fields } => {
440+ if let Ok ( err) = DbError :: new_raw ( fields) {
441+ self . notice_handler . handle ( err) ;
408442 }
409- val => return Ok ( val)
443+ Ok ( None )
444+ }
445+ ParameterStatus { parameter, value } => {
446+ debug ! ( "Parameter {} = {}" , parameter, value) ;
447+ Ok ( None )
448+ }
449+ val => Ok ( Some ( val) )
450+ }
451+ }
452+
453+ fn read_message_with_notification ( & mut self ) -> IoResult < BackendMessage > {
454+ loop {
455+ if let Some ( msg) = try!( self . read_one_message ( ) ) {
456+ return Ok ( msg) ;
410457 }
411458 }
412459 }
0 commit comments