|
- package pool
-
- import (
- "fmt"
- "io"
- "sync"
- "time"
- )
-
- //TODO: 保存所有的连接, 而不是只保存连接计数
-
- var ErrMaxConn = fmt.Errorf("maximum connections reached")
-
- //
- type NConn interface {
- io.Closer
- Name() string
- Closed() bool
- }
-
- type ConnPool struct {
- sync.RWMutex
-
- Name string
- Address string
- MaxConns int
- MaxIdle int
- Cnt int64
- New func(name string) (NConn, error)
-
- active int
- free []NConn
- all map[string]NConn
- }
-
- func NewConnPool(name string, address string, maxConns int, maxIdle int) *ConnPool {
- return &ConnPool{Name: name, Address: address, MaxConns: maxConns, MaxIdle: maxIdle, Cnt: 0, all: make(map[string]NConn)}
- }
-
- func (this *ConnPool) Proc() string {
- this.RLock()
- defer this.RUnlock()
-
- return fmt.Sprintf("Name:%s,Cnt:%d,active:%d,all:%d,free:%d",
- this.Name, this.Cnt, this.active, len(this.all), len(this.free))
- }
-
- func (this *ConnPool) Fetch() (NConn, error) {
- this.Lock()
- defer this.Unlock()
-
- conn := this.fetchFree()
- if conn != nil {
- return conn, nil
- }
- if this.overMax() {
- return nil, ErrMaxConn
- }
-
- conn, err := this.newConn()
- if err != nil {
- return nil, err
- }
- this.increActive()
- return conn, nil
- }
-
- func (this *ConnPool) ForceClose(conn NConn) {
- this.Lock()
- defer this.Unlock()
-
- this.deleteConn(conn)
- this.decreActive()
- }
-
- func (this *ConnPool) Release(conn NConn) {
- this.Lock()
- defer this.Unlock()
-
- if this.overMaxIdle() {
- this.deleteConn(conn)
- this.decreActive()
- } else {
- this.addFree(conn)
- }
- }
-
- // internal, concurrently unsafe
- func (this *ConnPool) newConn() (NConn, error) {
- name := fmt.Sprintf("%s_%d_%d", this.Name, this.Cnt, time.Now().Unix())
- conn, err := this.New(name)
- if err != nil {
- if conn != nil {
- conn.Close()
- }
- return nil, err
- }
-
- this.Cnt++
- this.all[conn.Name()] = conn
- return conn, nil
- }
-
- func (this *ConnPool) fetchFree() NConn {
- if len(this.free) == 0 {
- return nil
- }
-
- conn := this.free[0]
- this.free = this.free[1:]
- return conn
- }
-
- func (this *ConnPool) addFree(conn NConn) {
- this.free = append(this.free, conn)
- }
-
- func (this *ConnPool) overMax() bool {
- return this.active >= this.MaxConns
- }
-
- func (this *ConnPool) overMaxIdle() bool {
- return len(this.free) >= this.MaxIdle
- }
-
- func (this *ConnPool) increActive() {
- this.active += 1
- }
-
- func (this *ConnPool) decreActive() {
- this.active -= 1
- }
-
- func (this *ConnPool) deleteConn(conn NConn) {
- if conn != nil {
- conn.Close()
- }
- delete(this.all, conn.Name())
- }
|