func (p *Pool) get() (Conn, error) { p.mu.Lock() if timeout := p.IdleTimeout; timeout > 0 { for i, n := 0, p.idle.Len(); i < n; i++ { e := p.idle.Back() if e == nil { break } ic := e.Value.(idleConn) if ic.t.Add(timeout).After(nowFunc()) { break } p.idle.Remove(e) p.release() p.mu.Unlock() ic.c.Close() p.mu.Lock() } } for { for i, n := 0, p.idle.Len(); i < n; i++ { e := p.idle.Front() if e == nil { break } ic := e.Value.(idleConn) p.idle.Remove(e) test := p.TestOnBorrow p.mu.Unlock() if test == nil || test(ic.c, ic.t) == nil { return ic.c, nil } ic.c.Close() p.mu.Lock() p.release() } if p.closed { p.mu.Unlock() return nil, errors.New("redigo: get on closed pool") } if p.MaxActive == 0 || p.active < p.MaxActive { dial := p.Dial p.active += 1 p.mu.Unlock() c, err := dial() if err != nil { p.mu.Lock() p.release() p.mu.Unlock() c = nil } return c, err } if !p.Wait { p.mu.Unlock() return nil, ErrPoolExhausted } if p.cond == nil { p.cond = sync.NewCond(&p.mu) } p.cond.Wait() } }
|