Du kan inte välja fler än 25 ämnen Ämnen måste starta med en bokstav eller siffra, kan innehålla bindestreck ('-') och vara max 35 tecken långa.
 
 
 

160 lines
3.1 KiB

  1. // Copyright 2011 Xing Xing <mikespook@gmail.com>.
  2. // All rights reserved.
  3. // Use of this source code is governed by a MIT
  4. // license that can be found in the LICENSE file.
  5. package client
  6. import (
  7. "errors"
  8. "math/rand"
  9. "sync"
  10. )
  11. const (
  12. PoolSize = 10
  13. )
  14. var (
  15. ErrNotFound = errors.New("Server Not Found")
  16. )
  17. type poolClient struct {
  18. *Client
  19. Rate int
  20. }
  21. type SelectionHandler func(map[string]*poolClient, string) string
  22. func SelectWithRate(pool map[string]*poolClient,
  23. last string) (addr string) {
  24. total := 0
  25. for _, item := range pool {
  26. total += item.Rate
  27. if rand.Intn(total) < item.Rate {
  28. return item.addr
  29. }
  30. }
  31. return last
  32. }
  33. func SelectRandom(pool map[string]*poolClient,
  34. last string) (addr string) {
  35. r := rand.Intn(len(pool))
  36. i := 0
  37. for k, _ := range pool {
  38. if r == i {
  39. return k
  40. }
  41. i++
  42. }
  43. return last
  44. }
  45. type Pool struct {
  46. SelectionHandler SelectionHandler
  47. ErrorHandler ErrorHandler
  48. clients map[string]*poolClient
  49. last string
  50. mutex sync.Mutex
  51. }
  52. // Create a new pool.
  53. func NewPool() (pool *Pool) {
  54. return &Pool{
  55. clients: make(map[string]*poolClient, PoolSize),
  56. SelectionHandler: SelectWithRate,
  57. }
  58. }
  59. // Add a server with rate.
  60. func (pool *Pool) Add(net, addr string, rate int) (err error) {
  61. pool.mutex.Lock()
  62. defer pool.mutex.Unlock()
  63. var item *poolClient
  64. var ok bool
  65. if item, ok = pool.clients[addr]; ok {
  66. item.Rate = rate
  67. } else {
  68. var client *Client
  69. client, err = New(net, addr)
  70. item = &poolClient{Client: client, Rate: rate}
  71. pool.clients[addr] = item
  72. }
  73. return
  74. }
  75. // Remove a server.
  76. func (pool *Pool) Remove(addr string) {
  77. pool.mutex.Lock()
  78. defer pool.mutex.Unlock()
  79. delete(pool.clients, addr)
  80. }
  81. func (pool *Pool) Do(funcname string, data []byte,
  82. flag byte, h ResponseHandler) (addr, handle string, err error) {
  83. client := pool.selectServer()
  84. handle, err = client.Do(funcname, data, flag, h)
  85. addr = client.addr
  86. return
  87. }
  88. func (pool *Pool) DoBg(funcname string, data []byte,
  89. flag byte) (addr, handle string, err error) {
  90. client := pool.selectServer()
  91. handle, err = client.DoBg(funcname, data, flag)
  92. addr = client.addr
  93. return
  94. }
  95. // Get job status from job server.
  96. // !!!Not fully tested.!!!
  97. func (pool *Pool) Status(addr, handle string) (status *Status, err error) {
  98. if client, ok := pool.clients[addr]; ok {
  99. status, err = client.Status(handle)
  100. } else {
  101. err = ErrNotFound
  102. }
  103. return
  104. }
  105. // Send a something out, get the samething back.
  106. func (pool *Pool) Echo(addr string, data []byte) (echo []byte, err error) {
  107. var client *poolClient
  108. if addr == "" {
  109. client = pool.selectServer()
  110. } else {
  111. var ok bool
  112. if client, ok = pool.clients[addr]; !ok {
  113. err = ErrNotFound
  114. return
  115. }
  116. }
  117. echo, err = client.Echo(data)
  118. return
  119. }
  120. // Close
  121. func (pool *Pool) Close() (err map[string]error) {
  122. err = make(map[string]error)
  123. for _, c := range pool.clients {
  124. err[c.addr] = c.Close()
  125. }
  126. return
  127. }
  128. // selecting server
  129. func (pool *Pool) selectServer() (client *poolClient) {
  130. for client == nil {
  131. addr := pool.SelectionHandler(pool.clients, pool.last)
  132. var ok bool
  133. if client, ok = pool.clients[addr]; ok {
  134. pool.last = addr
  135. break
  136. }
  137. }
  138. return
  139. }