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.

agent.go 2.7 KiB

11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. package worker
  2. import (
  3. "io"
  4. "net"
  5. "strings"
  6. "sync"
  7. )
  8. // The agent of job server.
  9. type agent struct {
  10. sync.Mutex
  11. conn net.Conn
  12. worker *Worker
  13. in chan []byte
  14. net, addr string
  15. }
  16. // Create the agent of job server.
  17. func newAgent(net, addr string, worker *Worker) (a *agent, err error) {
  18. a = &agent{
  19. net: net,
  20. addr: addr,
  21. worker: worker,
  22. in: make(chan []byte, queueSize),
  23. }
  24. return
  25. }
  26. func (a *agent) Connect() (err error) {
  27. a.Lock()
  28. defer a.Unlock()
  29. a.conn, err = net.Dial(a.net, a.addr)
  30. if err != nil {
  31. return
  32. }
  33. go a.work()
  34. return
  35. }
  36. func (a *agent) work() {
  37. defer func() {
  38. if err := recover(); err != nil {
  39. a.worker.err(err.(error))
  40. }
  41. }()
  42. var inpack *inPack
  43. var l int
  44. var err error
  45. var data, leftdata []byte
  46. for {
  47. if data, err = a.read(bufferSize); err != nil {
  48. if err == ErrLostConn {
  49. break
  50. }
  51. a.worker.err(err)
  52. // If it is unexpected error and the connection wasn't
  53. // closed by Gearmand, the agent should close the conection
  54. // and reconnect to job server.
  55. a.Close()
  56. a.conn, err = net.Dial(a.net, a.addr)
  57. if err != nil {
  58. a.worker.err(err)
  59. break
  60. }
  61. }
  62. if len(leftdata) > 0 { // some data left for processing
  63. data = append(leftdata, data...)
  64. }
  65. if len(data) < minPacketLength { // not enough data
  66. leftdata = data
  67. continue
  68. }
  69. if inpack, l, err = decodeInPack(data); err != nil {
  70. a.worker.err(err)
  71. continue
  72. }
  73. leftdata = nil
  74. inpack.a = a
  75. a.worker.in <- inpack
  76. if len(data) > l {
  77. leftdata = data[l:]
  78. }
  79. }
  80. }
  81. func (a *agent) Close() {
  82. a.Lock()
  83. defer a.Unlock()
  84. if a.conn != nil {
  85. a.conn.Close()
  86. a.conn = nil
  87. }
  88. }
  89. func (a *agent) Grab() {
  90. a.Lock()
  91. defer a.Unlock()
  92. outpack := getOutPack()
  93. outpack.dataType = dtGrabJobUniq
  94. a.write(outpack)
  95. }
  96. func (a *agent) PreSleep() {
  97. a.Lock()
  98. defer a.Unlock()
  99. outpack := getOutPack()
  100. outpack.dataType = dtPreSleep
  101. a.write(outpack)
  102. }
  103. func isClosed(err error) bool {
  104. switch {
  105. case err == io.EOF:
  106. fallthrough
  107. case strings.Contains(err.Error(), "use of closed network connection"):
  108. return true
  109. }
  110. return false
  111. }
  112. // read length bytes from the socket
  113. func (a *agent) read(length int) (data []byte, err error) {
  114. n := 0
  115. buf := getBuffer(bufferSize)
  116. // read until data can be unpacked
  117. for i := length; i > 0 || len(data) < minPacketLength; i -= n {
  118. if n, err = a.conn.Read(buf); err != nil {
  119. if isClosed(err) {
  120. err = ErrLostConn
  121. }
  122. return
  123. }
  124. data = append(data, buf[0:n]...)
  125. if n < bufferSize {
  126. break
  127. }
  128. }
  129. return
  130. }
  131. // Internal write the encoded job.
  132. func (a *agent) write(outpack *outPack) (err error) {
  133. var n int
  134. buf := outpack.Encode()
  135. for i := 0; i < len(buf); i += n {
  136. n, err = a.conn.Write(buf[i:])
  137. if err != nil {
  138. return err
  139. }
  140. }
  141. return
  142. }