6
6
"log"
7
7
"math/rand"
8
8
"net/url"
9
- "reflect"
10
9
"strings"
11
10
"sync"
12
11
"time"
@@ -23,7 +22,7 @@ type Server struct {
23
22
Upgrader websocket.Upgrader
24
23
25
24
// In Pools, keep connections with WebSocket peers.
26
- Pools [ ]* Pool
25
+ Pools map [ string ]* Pool
27
26
28
27
// A RWMutex is a reader/writer mutual exclusion Lock,
29
28
// and it is for exclusive control with pools operation.
@@ -72,6 +71,7 @@ func NewServer(configFile string) (server *Server) {
72
71
server = new (Server )
73
72
server .Config = config
74
73
server .Upgrader = websocket.Upgrader {}
74
+ server .Pools = make (map [string ]* Pool )
75
75
76
76
server .done = make (chan struct {})
77
77
server .Dispatcher = make (chan * ConnectionRequest )
@@ -111,13 +111,13 @@ func (s *Server) clean() {
111
111
idle := 0
112
112
busy := 0
113
113
114
- var pools [ ]* Pool
115
- for _ , pool := range s .Pools {
114
+ pools := make ( map [ string ]* Pool )
115
+ for subdomain , pool := range s .Pools {
116
116
if pool .IsEmpty () {
117
117
log .Printf ("Removing empty connection pool : %s" , pool .ID )
118
118
pool .Shutdown ()
119
119
} else {
120
- pools = append ( pools , pool )
120
+ pools [ subdomain ] = pool
121
121
}
122
122
123
123
ps := pool .Size ()
@@ -156,36 +156,25 @@ func (s *Server) DispatchConnections() {
156
156
}
157
157
158
158
s .Lock .RLock ()
159
- if len (s .Pools ) == 0 {
159
+ pool , ok := s .Pools [request .Subdomain ]
160
+ if ! ok {
160
161
// No connection pool available
161
162
s .Lock .RUnlock ()
162
163
break
163
164
}
164
165
165
- // [1]: Select a pool which has an idle connection
166
- // Build a select statement dynamically to handle an arbitrary number of pools.
167
- cases := make ([]reflect.SelectCase , len (s .Pools )+ 1 )
168
- for i , ch := range s .Pools {
169
- // Pick connection for the requested subdomain
170
- if ch .Subdomain != request .Subdomain {
171
- cases [i ] = reflect.SelectCase {
172
- Dir : reflect .SelectRecv ,
173
- Chan : reflect .ValueOf (nil )}
174
- continue
166
+ var connection * Connection
167
+ for _ , conn := range pool .connections {
168
+ if conn .status == Idle {
169
+ connection = conn
170
+ break
175
171
}
176
- cases [i ] = reflect.SelectCase {
177
- Dir : reflect .SelectRecv ,
178
- Chan : reflect .ValueOf (ch .idle )}
179
172
}
180
- cases [len (cases )- 1 ] = reflect.SelectCase {
181
- Dir : reflect .SelectDefault }
182
173
s .Lock .RUnlock ()
183
174
184
- _ , value , ok := reflect .Select (cases )
185
- if ! ok {
186
- continue // a pool has been removed, try again
175
+ if connection == nil {
176
+ continue
187
177
}
188
- connection , _ := value .Interface ().(* Connection )
189
178
190
179
// [2]: Verify that we can use this connection and take it.
191
180
if connection .Take () {
@@ -233,37 +222,27 @@ func (s *Server) Shutdown() {
233
222
}
234
223
235
224
func (s * Server ) GetOrCreatePoolForUser (subdomain , localServer , userIdentifier string , id PoolID ) (* Pool , error ) {
236
- var pool * Pool
237
225
// There is no need to create a new pool,
238
226
// if it is already registered in current pools.
239
- for _ , p := range s .Pools {
240
- if p .Subdomain == subdomain {
241
- if p .ID == id {
242
- pool = p
243
- break
244
- } else {
245
- // Pool exist for the subdomain, but for different user
246
- return nil , fmt .Errorf ("subdomain already in use" )
247
- }
248
- }
227
+ p , ok := s .Pools [subdomain ]
228
+ if ! ok {
229
+ pool := NewPool (s , id , subdomain , localServer , userIdentifier )
230
+ s .Pools [subdomain ] = pool
231
+ return pool , nil
249
232
}
250
- if pool == nil {
251
- // Create new pool, if no pools exist for the user
252
- pool = NewPool (s , id , subdomain , localServer , userIdentifier )
253
- s .Pools = append (s .Pools , pool )
233
+
234
+ if p .ID != id {
235
+ return nil , fmt .Errorf ("subdomain already in use" )
254
236
}
255
- return pool , nil
237
+
238
+ return p , nil
256
239
}
257
240
258
241
func (s * Server ) GetDestinationURL (subdomain string ) string {
259
- var dstURL string
260
-
261
- for _ , p := range s .Pools {
262
- if p .Subdomain == subdomain {
263
- dstURL = p .LocalServer
264
- break
265
- }
242
+ p , ok := s .Pools [subdomain ]
243
+ if ! ok {
244
+ return ""
266
245
}
267
246
268
- return dstURL
247
+ return p . LocalServer
269
248
}
0 commit comments