2012-06-07 22:55:06 +04:00
|
|
|
// Copyright 2012, Google Inc. All rights reserved.
|
|
|
|
// Use of this source code is governed by a BSD-style
|
|
|
|
// license that can be found in the LICENSE file.
|
2012-02-25 11:30:03 +04:00
|
|
|
|
|
|
|
package tabletserver
|
|
|
|
|
|
|
|
import (
|
2013-05-15 03:04:23 +04:00
|
|
|
"sync"
|
2012-02-25 11:30:03 +04:00
|
|
|
"time"
|
2013-04-11 02:43:10 +04:00
|
|
|
|
2013-07-19 05:18:20 +04:00
|
|
|
"github.com/youtube/vitess/go/pools"
|
2013-08-12 12:47:35 +04:00
|
|
|
"github.com/youtube/vitess/go/stats"
|
2012-02-25 11:30:03 +04:00
|
|
|
)
|
|
|
|
|
2013-05-15 03:04:23 +04:00
|
|
|
// ConnectionPool re-exposes ResourcePool as a pool of DBConnection objects
|
2012-02-25 11:30:03 +04:00
|
|
|
type ConnectionPool struct {
|
2013-05-15 03:04:23 +04:00
|
|
|
pool *pools.ResourcePool
|
|
|
|
mu sync.Mutex
|
|
|
|
capacity int
|
|
|
|
idleTimeout time.Duration
|
2012-02-25 11:30:03 +04:00
|
|
|
}
|
|
|
|
|
2013-08-12 12:47:35 +04:00
|
|
|
func NewConnectionPool(name string, capacity int, idleTimeout time.Duration) *ConnectionPool {
|
|
|
|
cp := &ConnectionPool{capacity: capacity, idleTimeout: idleTimeout}
|
|
|
|
if name == "" {
|
|
|
|
return cp
|
|
|
|
}
|
|
|
|
stats.Publish(name+"Capacity", stats.IntFunc(cp.Capacity))
|
|
|
|
stats.Publish(name+"Available", stats.IntFunc(cp.Available))
|
|
|
|
stats.Publish(name+"MaxCap", stats.IntFunc(cp.MaxCap))
|
|
|
|
stats.Publish(name+"WaitCount", stats.IntFunc(cp.WaitCount))
|
|
|
|
stats.Publish(name+"WaitTime", stats.DurationFunc(cp.WaitTime))
|
|
|
|
stats.Publish(name+"IdleTimeout", stats.DurationFunc(cp.IdleTimeout))
|
|
|
|
return cp
|
2012-02-25 11:30:03 +04:00
|
|
|
}
|
|
|
|
|
2013-04-11 02:43:10 +04:00
|
|
|
func (cp *ConnectionPool) Open(connFactory CreateConnectionFunc) {
|
2012-03-17 04:07:27 +04:00
|
|
|
f := func() (pools.Resource, error) {
|
|
|
|
c, err := connFactory()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2013-04-11 02:43:10 +04:00
|
|
|
return &pooledConnection{c, cp}, nil
|
2012-02-25 11:30:03 +04:00
|
|
|
}
|
2013-05-15 03:04:23 +04:00
|
|
|
cp.pool = pools.NewResourcePool(f, cp.capacity, cp.capacity, cp.idleTimeout)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cp *ConnectionPool) Close() {
|
|
|
|
cp.pool.Close()
|
|
|
|
cp.pool = nil
|
2012-02-25 11:30:03 +04:00
|
|
|
}
|
|
|
|
|
2012-03-17 04:07:27 +04:00
|
|
|
// You must call Recycle on the PoolConnection once done.
|
2013-04-11 02:43:10 +04:00
|
|
|
func (cp *ConnectionPool) Get() PoolConnection {
|
2013-05-15 03:04:23 +04:00
|
|
|
r, err := cp.pool.Get()
|
2012-03-17 04:07:27 +04:00
|
|
|
if err != nil {
|
|
|
|
panic(NewTabletErrorSql(FATAL, err))
|
2012-02-25 11:30:03 +04:00
|
|
|
}
|
2012-03-17 04:07:27 +04:00
|
|
|
return r.(*pooledConnection)
|
2012-02-25 11:30:03 +04:00
|
|
|
}
|
|
|
|
|
2013-01-30 11:34:09 +04:00
|
|
|
// You must call Recycle on the PoolConnection once done.
|
2013-04-11 02:43:10 +04:00
|
|
|
func (cp *ConnectionPool) SafeGet() (PoolConnection, error) {
|
2013-05-15 03:04:23 +04:00
|
|
|
r, err := cp.pool.Get()
|
2013-01-30 11:34:09 +04:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return r.(*pooledConnection), nil
|
|
|
|
}
|
|
|
|
|
2012-03-17 04:07:27 +04:00
|
|
|
// You must call Recycle on the PoolConnection once done.
|
2013-04-11 02:43:10 +04:00
|
|
|
func (cp *ConnectionPool) TryGet() PoolConnection {
|
2013-05-15 03:04:23 +04:00
|
|
|
r, err := cp.pool.TryGet()
|
2012-02-25 11:30:03 +04:00
|
|
|
if err != nil {
|
2012-03-17 04:07:27 +04:00
|
|
|
panic(NewTabletErrorSql(FATAL, err))
|
2012-02-25 11:30:03 +04:00
|
|
|
}
|
2012-03-17 04:07:27 +04:00
|
|
|
if r == nil {
|
|
|
|
return nil
|
2012-02-25 11:30:03 +04:00
|
|
|
}
|
2012-03-17 04:07:27 +04:00
|
|
|
return r.(*pooledConnection)
|
2012-02-25 11:30:03 +04:00
|
|
|
}
|
|
|
|
|
2013-05-15 03:04:23 +04:00
|
|
|
func (cp *ConnectionPool) Put(conn PoolConnection) {
|
|
|
|
cp.pool.Put(conn)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cp *ConnectionPool) SetCapacity(capacity int) (err error) {
|
|
|
|
cp.mu.Lock()
|
|
|
|
defer cp.mu.Unlock()
|
|
|
|
err = cp.pool.SetCapacity(capacity)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
cp.capacity = capacity
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cp *ConnectionPool) SetIdleTimeout(idleTimeout time.Duration) {
|
|
|
|
cp.mu.Lock()
|
|
|
|
defer cp.mu.Unlock()
|
|
|
|
cp.pool.SetIdleTimeout(idleTimeout)
|
|
|
|
cp.idleTimeout = idleTimeout
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cp *ConnectionPool) StatsJSON() string {
|
|
|
|
if cp.pool == nil {
|
|
|
|
return "{}"
|
|
|
|
}
|
|
|
|
return cp.pool.StatsJSON()
|
|
|
|
}
|
|
|
|
|
2013-08-12 12:47:35 +04:00
|
|
|
func (cp *ConnectionPool) Capacity() int64 {
|
2013-08-12 22:31:08 +04:00
|
|
|
if cp.pool == nil {
|
2013-08-12 12:47:35 +04:00
|
|
|
return 0
|
|
|
|
}
|
|
|
|
return cp.pool.Capacity()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cp *ConnectionPool) Available() int64 {
|
2013-08-12 22:31:08 +04:00
|
|
|
if cp.pool == nil {
|
2013-08-12 12:47:35 +04:00
|
|
|
return 0
|
|
|
|
}
|
|
|
|
return cp.pool.Available()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cp *ConnectionPool) MaxCap() int64 {
|
2013-08-12 22:31:08 +04:00
|
|
|
if cp.pool == nil {
|
2013-08-12 12:47:35 +04:00
|
|
|
return 0
|
|
|
|
}
|
|
|
|
return cp.pool.MaxCap()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cp *ConnectionPool) WaitCount() int64 {
|
2013-08-12 22:31:08 +04:00
|
|
|
if cp.pool == nil {
|
2013-08-12 12:47:35 +04:00
|
|
|
return 0
|
|
|
|
}
|
|
|
|
return cp.pool.WaitCount()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cp *ConnectionPool) WaitTime() time.Duration {
|
2013-08-12 22:31:08 +04:00
|
|
|
if cp.pool == nil {
|
2013-08-12 12:47:35 +04:00
|
|
|
return 0
|
|
|
|
}
|
|
|
|
return cp.pool.WaitTime()
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cp *ConnectionPool) IdleTimeout() time.Duration {
|
2013-08-12 22:31:08 +04:00
|
|
|
if cp.pool == nil {
|
2013-08-12 12:47:35 +04:00
|
|
|
return 0
|
|
|
|
}
|
|
|
|
return cp.pool.IdleTimeout()
|
|
|
|
}
|
|
|
|
|
2012-03-17 04:07:27 +04:00
|
|
|
// pooledConnection re-exposes DBConnection as a PoolConnection
|
|
|
|
type pooledConnection struct {
|
2012-03-21 04:33:11 +04:00
|
|
|
*DBConnection
|
2012-03-17 04:07:27 +04:00
|
|
|
pool *ConnectionPool
|
2012-02-25 11:30:03 +04:00
|
|
|
}
|
|
|
|
|
2013-04-11 02:43:10 +04:00
|
|
|
func (pc *pooledConnection) Recycle() {
|
2013-05-15 03:04:23 +04:00
|
|
|
if pc.IsClosed() {
|
|
|
|
pc.pool.Put(nil)
|
|
|
|
} else {
|
|
|
|
pc.pool.Put(pc)
|
|
|
|
}
|
2012-02-25 11:30:03 +04:00
|
|
|
}
|