-
Notifications
You must be signed in to change notification settings - Fork 333
/
Copy pathpool.go
111 lines (104 loc) · 2.02 KB
/
pool.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
package xdb
import (
"sync"
"time"
"fmt"
"runtime/debug"
"log"
)
type PoolClient struct {
sync.RWMutex
ClientChan chan *Client
Uri string
MaxClientCount uint8
CurrentClientCount uint8
AvailableCount uint8
}
var clientPool map[string]*PoolClient
func init() {
clientPool = make(map[string]*PoolClient,0)
}
func InitClientPool(name string,uri string,count uint8) error{
if _,ok:=clientPool[name];!ok{
clientPool[name] = &PoolClient{
ClientChan: make(chan *Client, int(count)),
Uri:uri,
MaxClientCount: count,
CurrentClientCount: 0,
AvailableCount:0,
}
}
return nil
}
func GetClient(name string) (c *Client,err error) {
if _,ok:=clientPool[name];!ok{
return nil,fmt.Errorf(name+" not esxit")
}
t := clientPool[name]
t.Lock()
if t.AvailableCount > 0 {
t.AvailableCount--
t.Unlock()
//这里为什么不需要timeout,是因为前面加了lock 判断空闲连接数
c = <- t.ClientChan
return
}
if t.MaxClientCount > t.CurrentClientCount{
t.CurrentClientCount++
t.Unlock()
f,stringKey := NewClient(name,t.Uri)
if f == nil{
t.Lock()
t.CurrentClientCount--
t.Unlock()
}
return f,stringKey
}
t.Unlock()
timer := time.NewTimer(5 * time.Second)
select {
case c = <-t.ClientChan:
break
case <- timer.C:
break
}
timer.Stop()
if c == nil{
return nil,fmt.Errorf("get client time out")
}
t.Lock()
t.AvailableCount--
t.Unlock()
return
}
func BackCient(name string,c *Client) bool {
defer func() {
if err := recover();err !=nil{
log.Println(string(debug.Stack()))
return
}
}()
if _,ok:=clientPool[name];!ok{
return true
}
t:=clientPool[name]
t.Lock()
if t.CurrentClientCount > t.MaxClientCount{
t.CurrentClientCount--
func(){
defer func() {
if err := recover();err != nil{
log.Println(string(debug.Stack()))
return
}
}()
//调用插件函数,关闭连接,这里防止插件代码写得有问题,抛异常,所以这里需要recover一次
c.Close()
}()
}else{
t.AvailableCount++
t.ClientChan <- c
}
t.Unlock()
return true
}