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.

response.go 3.6 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. package client
  2. import (
  3. "bytes"
  4. "encoding/binary"
  5. "fmt"
  6. "strconv"
  7. )
  8. // Response handler
  9. type ResponseHandler func(*Response)
  10. // response
  11. type Response struct {
  12. DataType uint32
  13. Data, UID []byte
  14. Handle string
  15. }
  16. // Extract the Response's result.
  17. // if data == nil, err != nil, then worker failing to execute job
  18. // if data != nil, err != nil, then worker has a exception
  19. // if data != nil, err == nil, then worker complate job
  20. // after calling this method, the Response.Handle will be filled
  21. func (resp *Response) Result() (data []byte, err error) {
  22. switch resp.DataType {
  23. case dtWorkFail:
  24. resp.Handle = string(resp.Data)
  25. err = ErrWorkFail
  26. return
  27. case dtWorkException:
  28. err = ErrWorkException
  29. fallthrough
  30. case dtWorkComplete:
  31. data = resp.Data
  32. default:
  33. err = ErrDataType
  34. }
  35. return
  36. }
  37. // Extract the job's update
  38. func (resp *Response) Update() (data []byte, err error) {
  39. if resp.DataType != dtWorkData &&
  40. resp.DataType != dtWorkWarning {
  41. err = ErrDataType
  42. return
  43. }
  44. data = resp.Data
  45. if resp.DataType == dtWorkWarning {
  46. err = ErrWorkWarning
  47. }
  48. return
  49. }
  50. // Decode a job from byte slice
  51. func decodeResponse(data []byte) (resp *Response, l int, err error) {
  52. a := len(data)
  53. if a < minPacketLength { // valid package should not less 12 bytes
  54. err = fmt.Errorf("Invalid data: %v", data)
  55. return
  56. }
  57. dl := int(binary.BigEndian.Uint32(data[8:12]))
  58. if a < minPacketLength+dl {
  59. err = fmt.Errorf("Invalid data: %v", data)
  60. return
  61. }
  62. dt := data[minPacketLength : dl+minPacketLength]
  63. if len(dt) != int(dl) { // length not equal
  64. err = fmt.Errorf("Invalid data: %v", data)
  65. return
  66. }
  67. resp = getResponse()
  68. resp.DataType = binary.BigEndian.Uint32(data[4:8])
  69. switch resp.DataType {
  70. case dtJobCreated:
  71. resp.Handle = string(dt)
  72. case dtStatusRes, dtWorkData, dtWorkWarning, dtWorkStatus,
  73. dtWorkComplete, dtWorkException:
  74. s := bytes.SplitN(dt, []byte{'\x00'}, 2)
  75. if len(s) >= 2 {
  76. resp.Handle = string(s[0])
  77. resp.Data = s[1]
  78. } else {
  79. err = fmt.Errorf("Invalid data: %v", data)
  80. return
  81. }
  82. case dtWorkFail:
  83. s := bytes.SplitN(dt, []byte{'\x00'}, 2)
  84. if len(s) >= 1 {
  85. resp.Handle = string(s[0])
  86. } else {
  87. err = fmt.Errorf("Invalid data: %v", data)
  88. return
  89. }
  90. case dtEchoRes:
  91. fallthrough
  92. default:
  93. resp.Data = dt
  94. }
  95. l = dl + minPacketLength
  96. return
  97. }
  98. func (resp *Response) Status() (status *Status, err error) {
  99. data := bytes.SplitN(resp.Data, []byte{'\x00'}, 2)
  100. if len(data) != 2 {
  101. err = fmt.Errorf("Invalid data: %v", resp.Data)
  102. return
  103. }
  104. status = &Status{}
  105. status.Handle = resp.Handle
  106. status.Known = true
  107. status.Running = true
  108. status.Numerator, err = strconv.ParseUint(string(data[0]), 10, 0)
  109. if err != nil {
  110. err = fmt.Errorf("Invalid Integer: %s", data[0])
  111. return
  112. }
  113. status.Denominator, err = strconv.ParseUint(string(data[1]), 10, 0)
  114. if err != nil {
  115. err = fmt.Errorf("Invalid Integer: %s", data[1])
  116. return
  117. }
  118. return
  119. }
  120. // status handler
  121. func (resp *Response) _status() (status *Status, err error) {
  122. data := bytes.SplitN(resp.Data, []byte{'\x00'}, 4)
  123. if len(data) != 4 {
  124. err = fmt.Errorf("Invalid data: %v", resp.Data)
  125. return
  126. }
  127. status = &Status{}
  128. status.Handle = resp.Handle
  129. status.Known = (data[0][0] == '1')
  130. status.Running = (data[1][0] == '1')
  131. status.Numerator, err = strconv.ParseUint(string(data[2]), 10, 0)
  132. if err != nil {
  133. err = fmt.Errorf("Invalid Integer: %s", data[2])
  134. return
  135. }
  136. status.Denominator, err = strconv.ParseUint(string(data[3]), 10, 0)
  137. if err != nil {
  138. err = fmt.Errorf("Invalid Integer: %s", data[3])
  139. return
  140. }
  141. return
  142. }
  143. func getResponse() (resp *Response) {
  144. // TODO add a pool
  145. resp = &Response{}
  146. return
  147. }