@@ -4,25 +4,23 @@ use std::io::{self, IoSlice};
4
4
use hashbrown:: HashMap ;
5
5
use strum:: IntoEnumIterator ;
6
6
use tokio:: net:: TcpStream ;
7
- use tokio:: sync:: oneshot;
8
7
9
- use super :: request:: { self , MarshalledRequest , Operation , SessionOperation , StateResponser } ;
8
+ use super :: request:: { MarshalledRequest , Operation , SessionOperation , StateResponser } ;
10
9
use super :: types:: WatchMode ;
11
10
use super :: xid:: Xid ;
12
11
use super :: SessionId ;
13
12
use crate :: error:: Error ;
14
- use crate :: proto:: { AuthPacket , OpCode , RemoveWatchesRequest } ;
15
-
16
- pub type AuthResponser = oneshot:: Sender < Result < ( ) , Error > > ;
13
+ use crate :: proto:: { OpCode , PredefinedXid , RemoveWatchesRequest } ;
17
14
18
15
#[ derive( Default ) ]
19
16
pub struct Depot {
20
17
xid : Xid ,
21
18
19
+ pending_authes : Vec < SessionOperation > ,
20
+
22
21
writing_slices : Vec < IoSlice < ' static > > ,
23
22
writing_operations : VecDeque < Operation > ,
24
- written_operations : VecDeque < SessionOperation > ,
25
- pending_auth : Option < ( AuthPacket , AuthResponser ) > ,
23
+ written_operations : HashMap < i32 , SessionOperation > ,
26
24
27
25
watching_paths : HashMap < ( & ' static str , WatchMode ) , usize > ,
28
26
unwatching_paths : HashMap < ( & ' static str , WatchMode ) , SessionOperation > ,
@@ -33,10 +31,10 @@ impl Depot {
33
31
let writing_capacity = 128usize ;
34
32
Depot {
35
33
xid : Default :: default ( ) ,
34
+ pending_authes : Vec :: with_capacity ( 5 ) ,
36
35
writing_slices : Vec :: with_capacity ( writing_capacity) ,
37
36
writing_operations : VecDeque :: with_capacity ( writing_capacity) ,
38
- written_operations : VecDeque :: with_capacity ( 128 ) ,
39
- pending_auth : None ,
37
+ written_operations : HashMap :: with_capacity ( 128 ) ,
40
38
watching_paths : HashMap :: with_capacity ( 32 ) ,
41
39
unwatching_paths : HashMap :: with_capacity ( 32 ) ,
42
40
}
@@ -45,28 +43,40 @@ impl Depot {
45
43
pub fn for_connecting ( ) -> Depot {
46
44
Depot {
47
45
xid : Default :: default ( ) ,
46
+ pending_authes : Default :: default ( ) ,
48
47
writing_slices : Vec :: with_capacity ( 10 ) ,
49
48
writing_operations : VecDeque :: with_capacity ( 10 ) ,
50
- written_operations : VecDeque :: with_capacity ( 10 ) ,
51
- pending_auth : None ,
49
+ written_operations : HashMap :: with_capacity ( 10 ) ,
52
50
watching_paths : HashMap :: new ( ) ,
53
51
unwatching_paths : HashMap :: new ( ) ,
54
52
}
55
53
}
56
54
55
+ /// Clear all buffered operations from previous run.
57
56
pub fn clear ( & mut self ) {
57
+ self . pending_authes . clear ( ) ;
58
58
self . writing_slices . clear ( ) ;
59
59
self . watching_paths . clear ( ) ;
60
+ self . unwatching_paths . clear ( ) ;
60
61
self . writing_operations . clear ( ) ;
61
62
self . written_operations . clear ( ) ;
62
63
}
63
64
64
- pub fn error ( & mut self , err : Error ) {
65
- self . written_operations . drain ( ..) . for_each ( |operation| {
65
+ /// Error out ongoing operations except authes.
66
+ pub fn error ( & mut self , err : & Error ) {
67
+ self . written_operations . drain ( ) . for_each ( |( _, operation) | {
68
+ if operation. request . get_code ( ) == OpCode :: Auth {
69
+ self . pending_authes . push ( operation) ;
70
+ return ;
71
+ }
66
72
operation. responser . send ( Err ( err. clone ( ) ) ) ;
67
73
} ) ;
68
74
self . writing_operations . drain ( ..) . for_each ( |operation| {
69
75
if let Operation :: Session ( operation) = operation {
76
+ if operation. request . get_code ( ) == OpCode :: Auth {
77
+ self . pending_authes . push ( operation) ;
78
+ return ;
79
+ }
70
80
operation. responser . send ( Err ( err. clone ( ) ) ) ;
71
81
}
72
82
} ) ;
@@ -77,42 +87,28 @@ impl Depot {
77
87
self . watching_paths . clear ( ) ;
78
88
}
79
89
80
- pub fn is_empty ( & self ) -> bool {
81
- self . writing_operations . is_empty ( ) && self . written_operations . is_empty ( )
82
- }
83
-
84
- pub fn pop_pending_auth ( & mut self ) -> Option < ( AuthPacket , AuthResponser ) > {
85
- self . pending_auth . take ( )
90
+ /// Terminate all ongoing operations including authes.
91
+ pub fn terminate ( & mut self , err : Error ) {
92
+ self . error ( & err ) ;
93
+ for SessionOperation { responser , .. } in self . pending_authes . drain ( .. ) {
94
+ responser . send ( Err ( err . clone ( ) ) ) ;
95
+ }
86
96
}
87
97
88
- pub fn has_pending_auth ( & self ) -> bool {
89
- self . pending_auth . is_some ( )
98
+ /// Check whether there is any ongoing operations.
99
+ pub fn is_empty ( & self ) -> bool {
100
+ self . writing_operations . is_empty ( ) && self . written_operations . is_empty ( )
90
101
}
91
102
92
- pub fn pop_reqeust ( & mut self , xid : i32 ) -> Result < SessionOperation , Error > {
93
- match self . written_operations . pop_front ( ) {
103
+ pub fn pop_request ( & mut self , xid : i32 ) -> Result < SessionOperation , Error > {
104
+ match self . written_operations . remove ( & xid ) {
94
105
None => Err ( Error :: UnexpectedError ( format ! ( "recv response with xid {} but no pending request" , xid) ) ) ,
95
- Some ( operation) => {
96
- let request_xid = operation. request . get_xid ( ) ;
97
- if xid == request_xid {
98
- return Ok ( operation) ;
99
- }
100
- self . written_operations . push_front ( operation) ;
101
- Err ( Error :: UnexpectedError ( format ! ( "expect response xid {} but got {}" , xid, request_xid) ) )
102
- } ,
106
+ Some ( operation) => Ok ( operation) ,
103
107
}
104
108
}
105
109
106
110
pub fn pop_ping ( & mut self ) -> Result < ( ) , Error > {
107
- if let Some ( operation) = self . written_operations . pop_front ( ) {
108
- let op_code = operation. request . get_code ( ) ;
109
- if op_code != OpCode :: Ping {
110
- self . written_operations . push_front ( operation) ;
111
- return Err ( Error :: UnexpectedError ( format ! ( "expect pending ping request, got {}" , op_code) ) ) ;
112
- }
113
- return Ok ( ( ) ) ;
114
- }
115
- Err ( Error :: UnexpectedError ( "expect pending ping request, got none" . to_string ( ) ) )
111
+ self . pop_request ( PredefinedXid :: Ping . into ( ) ) . map ( |_| ( ) )
116
112
}
117
113
118
114
pub fn push_operation ( & mut self , operation : Operation ) {
@@ -126,9 +122,11 @@ impl Depot {
126
122
}
127
123
128
124
pub fn start ( & mut self ) {
129
- if let Some ( ( auth, responser) ) = self . pending_auth . take ( ) {
130
- self . push_auth ( auth, responser) ;
125
+ let mut pending_authes = std:: mem:: take ( & mut self . pending_authes ) ;
126
+ for operation in pending_authes. drain ( ..) {
127
+ self . push_session ( operation) ;
131
128
}
129
+ self . pending_authes = pending_authes;
132
130
}
133
131
134
132
fn cancel_unwatch ( & mut self , path : & ' static str , mode : WatchMode ) {
@@ -195,12 +193,6 @@ impl Depot {
195
193
. any ( |mode| self . watching_paths . contains_key ( & ( path, mode) ) )
196
194
}
197
195
198
- pub fn push_auth ( & mut self , auth : AuthPacket , responser : AuthResponser ) {
199
- let operation = request:: build_auth_operation ( OpCode :: Auth , & auth) ;
200
- self . pending_auth = Some ( ( auth, responser) ) ;
201
- self . push_operation ( Operation :: Auth ( operation) ) ;
202
- }
203
-
204
196
pub fn write_operations ( & mut self , sock : & TcpStream , session_id : SessionId ) -> Result < ( ) , Error > {
205
197
let result = sock. try_write_vectored ( self . writing_slices . as_slice ( ) ) ;
206
198
let mut written_bytes = match result {
@@ -226,13 +218,18 @@ impl Depot {
226
218
. unwrap_or ( self . writing_slices . len ( ) ) ;
227
219
if written_slices != 0 {
228
220
self . writing_slices . drain ( ..written_slices) ;
229
- let written = self . writing_operations . drain ( ..written_slices) . filter_map ( |operation| {
230
- if let Operation :: Session ( operation) = operation {
231
- return Some ( operation) ;
232
- }
233
- None
234
- } ) ;
235
- self . written_operations . extend ( written) ;
221
+ self . writing_operations
222
+ . drain ( ..written_slices)
223
+ . filter_map ( |operation| {
224
+ if let Operation :: Session ( operation) = operation {
225
+ return Some ( operation) ;
226
+ }
227
+ None
228
+ } )
229
+ . for_each ( |operation| {
230
+ let xid = operation. request . get_xid ( ) ;
231
+ self . written_operations . insert ( xid, operation) ;
232
+ } ) ;
236
233
}
237
234
if written_bytes != 0 {
238
235
let ( _, rest) = self . writing_slices [ 0 ] . split_at ( written_bytes) ;
0 commit comments