You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

pool.go 3.0 KiB

11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. package client
  2. import (
  3. "errors"
  4. "math/rand"
  5. "sync"
  6. )
  7. const (
  8. poolSize = 10
  9. )
  10. var (
  11. ErrNotFound = errors.New("Server Not Found")
  12. SelectWithRate = selectWithRate
  13. SelectRandom = selectRandom
  14. )
  15. type poolClient struct {
  16. *Client
  17. Rate int
  18. }
  19. type SelectionHandler func(map[string]*poolClient, string) string
  20. func selectWithRate(pool map[string]*poolClient,
  21. last string) (addr string) {
  22. total := 0
  23. for _, item := range pool {
  24. total += item.Rate
  25. if rand.Intn(total) < item.Rate {
  26. return item.addr
  27. }
  28. }
  29. return last
  30. }
  31. func selectRandom(pool map[string]*poolClient,
  32. last string) (addr string) {
  33. r := rand.Intn(len(pool))
  34. i := 0
  35. for k, _ := range pool {
  36. if r == i {
  37. return k
  38. }
  39. i++
  40. }
  41. return last
  42. }
  43. type Pool struct {
  44. SelectionHandler SelectionHandler
  45. ErrorHandler ErrorHandler
  46. clients map[string]*poolClient
  47. last string
  48. mutex sync.Mutex
  49. }
  50. // Return a new pool.
  51. func NewPool() (pool *Pool) {
  52. return &Pool{
  53. clients: make(map[string]*poolClient, poolSize),
  54. SelectionHandler: SelectWithRate,
  55. }
  56. }
  57. // Add a server with rate.
  58. func (pool *Pool) Add(net, addr string, rate int) (err error) {
  59. pool.mutex.Lock()
  60. defer pool.mutex.Unlock()
  61. var item *poolClient
  62. var ok bool
  63. if item, ok = pool.clients[addr]; ok {
  64. item.Rate = rate
  65. } else {
  66. var client *Client
  67. client, err = New(net, addr)
  68. if err == nil {
  69. item = &poolClient{Client: client, Rate: rate}
  70. pool.clients[addr] = item
  71. }
  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. }