Advertisement
Guest User

Untitled

a guest
Jan 24th, 2017
111
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.52 KB | None | 0 0
  1. package examplepool
  2.  
  3. import (
  4. "context"
  5. "errors"
  6. "fmt"
  7. "sync"
  8. "time"
  9.  
  10. _ "github.com/alexbrainman/odbc"
  11. "github.com/jmoiron/sqlx"
  12. )
  13.  
  14. type Examplepool struct {
  15. username string
  16. password string
  17.  
  18. connsMutex sync.Mutex
  19. conns []*connection
  20. }
  21.  
  22. type connection struct {
  23. *sqlx.DB
  24. inUse bool
  25. ep *Examplepool
  26. }
  27.  
  28. var (
  29. ErrNotInUse = errors.New("Connection is not in use, can't release")
  30. ErrNotInPool = errors.New("Connection to release not actually in pool")
  31. )
  32.  
  33. func New(username, password string) (*Examplepool, error) {
  34. ep := &Examplepool{
  35. username: username,
  36. password: password,
  37. conns: make([]*connection, 0),
  38. }
  39.  
  40. // Have at least one connection ready
  41. c, err := ep.Acquire()
  42. if err != nil {
  43. return nil, err
  44. }
  45. err = c.Release()
  46. if err != nil {
  47. return nil, err
  48. }
  49. return ep, nil
  50. }
  51.  
  52. func (ep *Examplepool) newConnection() (*connection, error) {
  53. db, err := sqlx.Open("odbc", fmt.Sprintf("dsn=mydsn;uid=%s;pwd=%s;tracing=0", ep.username, ep.password))
  54. if err != nil {
  55. return nil, err
  56. }
  57. db.SetMaxOpenConns(1)
  58. db.SetMaxIdleConns(1)
  59.  
  60. return &connection{
  61. db,
  62. false,
  63. ep,
  64. }, nil
  65. }
  66.  
  67. func (ep *Examplepool) Acquire() (*connection, error) {
  68. ep.connsMutex.Lock()
  69. defer ep.connsMutex.Unlock()
  70.  
  71. for i, c := range ep.conns {
  72. if !c.inUse {
  73. // Log.Debugf("Acquire() returning id %d", i)
  74. ep.conns[i].inUse = true
  75. return c, nil
  76. }
  77. }
  78.  
  79. c, err := ep.newConnection()
  80. if err != nil {
  81. return nil, err
  82. }
  83.  
  84. // Log.Debugf("Acquire() returning new connection, index: %d", len(ep.conns))
  85. c.inUse = true
  86. ep.conns = append(ep.conns, c)
  87. return c, nil
  88. }
  89.  
  90. func (c *connection) Release() error {
  91. c.ep.connsMutex.Lock()
  92. defer c.ep.connsMutex.Unlock()
  93.  
  94. for i, co := range c.ep.conns {
  95. if co == c {
  96. // Log.Debugf("Release() found connection, index: %d", i)
  97. if !co.inUse {
  98. // Log.Error(ErrNotInUse.Error())
  99. return ErrNotInUse
  100. }
  101. c.ep.conns[i].inUse = false
  102. return nil
  103. }
  104. }
  105.  
  106. // Log.Error(ErrNotInPool.Error())
  107. return ErrNotInPool
  108. }
  109.  
  110. func (ep *Examplepool) StartKeepAlive(ctx context.Context) {
  111. go func() {
  112. select {
  113. case <-time.After(15 * time.Minute):
  114. ep.connsMutex.Lock()
  115. defer ep.connsMutex.Unlock()
  116.  
  117. for _, c := range ep.conns {
  118. if !c.inUse {
  119. // Log.Debugf("KeepAlive() for index: %d", i)
  120. c.KeepAlive()
  121. } else {
  122. // Log.Debugf("No KeepAlive() for index: %d (in use)", i)
  123. }
  124. }
  125.  
  126. case <-ctx.Done():
  127. return
  128. }
  129. }()
  130. }
  131.  
  132. func (c *connection) KeepAlive() error {
  133. rows, err := c.Query(`SELECT CURRENT_TIMESTAMP()`)
  134. if err != nil {
  135. return err
  136. }
  137. rows.Close()
  138. return nil
  139. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement