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.4 KiB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
10 years ago
11 years ago
10 years ago
10 years ago
11 years ago
11 years ago
11 years ago
10 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148
  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, dtWorkFail, 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 dtEchoRes:
  83. fallthrough
  84. default:
  85. resp.Data = dt
  86. }
  87. l = dl + minPacketLength
  88. return
  89. }
  90. func (resp *Response) Status() (status *Status, err error) {
  91. data := bytes.SplitN(resp.Data, []byte{'\x00'}, 2)
  92. if len(data) != 2 {
  93. err = fmt.Errorf("Invalid data: %V", resp.Data)
  94. return
  95. }
  96. status = &Status{}
  97. status.Handle = resp.Handle
  98. status.Known = true
  99. status.Running = true
  100. status.Numerator, err = strconv.ParseUint(string(data[0]), 10, 0)
  101. if err != nil {
  102. err = fmt.Errorf("Invalid Integer: %s", data[0])
  103. return
  104. }
  105. status.Denominator, err = strconv.ParseUint(string(data[1]), 10, 0)
  106. if err != nil {
  107. err = fmt.Errorf("Invalid Integer: %s", data[1])
  108. return
  109. }
  110. return
  111. }
  112. // status handler
  113. func (resp *Response) _status() (status *Status, err error) {
  114. data := bytes.SplitN(resp.Data, []byte{'\x00'}, 4)
  115. if len(data) != 4 {
  116. err = fmt.Errorf("Invalid data: %V", resp.Data)
  117. return
  118. }
  119. status = &Status{}
  120. status.Handle = resp.Handle
  121. status.Known = (data[0][0] == '1')
  122. status.Running = (data[1][0] == '1')
  123. status.Numerator, err = strconv.ParseUint(string(data[2]), 10, 0)
  124. if err != nil {
  125. err = fmt.Errorf("Invalid Integer: %s", data[2])
  126. return
  127. }
  128. status.Denominator, err = strconv.ParseUint(string(data[3]), 10, 0)
  129. if err != nil {
  130. err = fmt.Errorf("Invalid Integer: %s", data[3])
  131. return
  132. }
  133. return
  134. }
  135. func getResponse() (resp *Response) {
  136. // TODO add a pool
  137. resp = &Response{}
  138. return
  139. }