-
Notifications
You must be signed in to change notification settings - Fork 43
/
Copy pathbinder.go
154 lines (125 loc) · 3.51 KB
/
binder.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
package wserver
import (
"errors"
"fmt"
"sync"
)
// eventConn wraps Conn with a specified event type.
type eventConn struct {
Event string
Conn *Conn
}
// binder is defined to store the relation of userID and eventConn
type binder struct {
mu sync.RWMutex
// map stores key: userID and value of related slice of eventConn
userID2EventConnMap map[string]*[]eventConn
// map stores key: connID and value: userID
connID2UserIDMap map[string]string
}
// Bind binds userID with eConn specified by event. It fails if the
// return error is not nil.
func (b *binder) Bind(userID, event string, conn *Conn) error {
if userID == "" {
return errors.New("userID can't be empty")
}
if event == "" {
return errors.New("event can't be empty")
}
if conn == nil {
return errors.New("conn can't be nil")
}
b.mu.Lock()
defer b.mu.Unlock()
// map the eConn if it isn't be put.
if eConns, ok := b.userID2EventConnMap[userID]; ok {
for i := range *eConns {
if (*eConns)[i].Conn == conn {
return nil
}
}
newEConns := append(*eConns, eventConn{event, conn})
b.userID2EventConnMap[userID] = &newEConns
} else {
b.userID2EventConnMap[userID] = &[]eventConn{{event, conn}}
}
b.connID2UserIDMap[conn.GetID()] = userID
return nil
}
// Unbind unbind and removes Conn if it's exist.
func (b *binder) Unbind(conn *Conn) error {
if conn == nil {
return errors.New("conn can't be empty")
}
b.mu.Lock()
defer b.mu.Unlock()
// query userID by connID
userID, ok := b.connID2UserIDMap[conn.GetID()]
if !ok {
return fmt.Errorf("can't find userID by connID: %s", conn.GetID())
}
if eConns, ok := b.userID2EventConnMap[userID]; ok {
for i := range *eConns {
if (*eConns)[i].Conn == conn {
newEConns := append((*eConns)[:i], (*eConns)[i+1:]...)
b.userID2EventConnMap[userID] = &newEConns
delete(b.connID2UserIDMap, conn.GetID())
// delete the key of userID when the length of the related
// eventConn slice is 0.
if len(newEConns) == 0 {
delete(b.userID2EventConnMap, userID)
}
return nil
}
}
return fmt.Errorf("can't find the conn of ID: %s", conn.GetID())
}
return fmt.Errorf("can't find the eventConns by userID: %s", userID)
}
// FindConn trys to find Conn by ID.
func (b *binder) FindConn(connID string) (*Conn, bool) {
if connID == "" {
return nil, false
}
userID, ok := b.connID2UserIDMap[connID]
// if userID been found by connID, then find the Conn using userID
if ok {
if eConns, ok := b.userID2EventConnMap[userID]; ok {
for i := range *eConns {
if (*eConns)[i].Conn.GetID() == connID {
return (*eConns)[i].Conn, true
}
}
}
return nil, false
}
// userID not found, iterate all the conns
for _, eConns := range b.userID2EventConnMap {
for i := range *eConns {
if (*eConns)[i].Conn.GetID() == connID {
return (*eConns)[i].Conn, true
}
}
}
return nil, false
}
// FilterConn searches the conns related to userID, and filtered by
// event. The userID can't be empty. The event will be ignored if it's empty.
// All the conns related to the userID will be returned if the event is empty.
func (b *binder) FilterConn(userID, event string) ([]*Conn, error) {
if userID == "" {
return nil, errors.New("userID can't be empty")
}
b.mu.RLock()
defer b.mu.RUnlock()
if eConns, ok := b.userID2EventConnMap[userID]; ok {
ecs := make([]*Conn, 0, len(*eConns))
for i := range *eConns {
if event == "" || (*eConns)[i].Event == event {
ecs = append(ecs, (*eConns)[i].Conn)
}
}
return ecs, nil
}
return []*Conn{}, nil
}