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

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
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  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. s := bytes.SplitN(resp.Data, []byte{'\x00'}, 2)
  32. if len(s) != 2 {
  33. err = fmt.Errorf("Invalid data: %V", resp.Data)
  34. return
  35. }
  36. resp.Handle = string(s[0])
  37. data = s[1]
  38. default:
  39. err = ErrDataType
  40. }
  41. return
  42. }
  43. // Extract the job's update
  44. func (resp *Response) Update() (data []byte, err error) {
  45. if resp.DataType != dtWorkData &&
  46. resp.DataType != dtWorkWarning {
  47. err = ErrDataType
  48. return
  49. }
  50. s := bytes.SplitN(resp.Data, []byte{'\x00'}, 2)
  51. if len(s) != 2 {
  52. err = ErrInvalidData
  53. return
  54. }
  55. if resp.DataType == dtWorkWarning {
  56. err = ErrWorkWarning
  57. }
  58. resp.Handle = string(s[0])
  59. data = s[1]
  60. return
  61. }
  62. // Decode a job from byte slice
  63. func decodeResponse(data []byte) (resp *Response, l int, err error) {
  64. if len(data) < minPacketLength { // valid package should not less 12 bytes
  65. err = fmt.Errorf("Invalid data: %V", data)
  66. return
  67. }
  68. dl := int(binary.BigEndian.Uint32(data[8:12]))
  69. dt := data[minPacketLength : dl+minPacketLength]
  70. if len(dt) != int(dl) { // length not equal
  71. err = fmt.Errorf("Invalid data: %V", data)
  72. return
  73. }
  74. resp = getResponse()
  75. resp.DataType = binary.BigEndian.Uint32(data[4:8])
  76. switch resp.DataType {
  77. case dtJobCreated:
  78. resp.Handle = string(dt)
  79. case dtStatusRes, dtWorkData, dtWorkWarning, dtWorkStatus,
  80. dtWorkComplete, dtWorkFail, dtWorkException:
  81. s := bytes.SplitN(dt, []byte{'\x00'}, 2)
  82. if len(s) >= 2 {
  83. resp.Handle = string(s[0])
  84. resp.Data = s[1]
  85. } else {
  86. err = fmt.Errorf("Invalid data: %V", data)
  87. return
  88. }
  89. case dtEchoRes:
  90. fallthrough
  91. default:
  92. resp.Data = dt
  93. }
  94. l = dl + minPacketLength
  95. return
  96. }
  97. // status handler
  98. func (resp *Response) Status() (status *Status, err error) {
  99. data := bytes.SplitN(resp.Data, []byte{'\x00'}, 4)
  100. if len(data) != 4 {
  101. err = fmt.Errorf("Invalid data: %V", resp.Data)
  102. return
  103. }
  104. status = &Status{}
  105. status.Handle = resp.Handle
  106. status.Known = (data[0][0] == '1')
  107. status.Running = (data[1][0] == '1')
  108. status.Numerator, err = strconv.ParseUint(string(data[2]), 10, 0)
  109. if err != nil {
  110. err = fmt.Errorf("Invalid Integer: %s", data[2])
  111. return
  112. }
  113. status.Denominator, err = strconv.ParseUint(string(data[3]), 10, 0)
  114. if err != nil {
  115. err = fmt.Errorf("Invalid Integer: %s", data[3])
  116. return
  117. }
  118. return
  119. }
  120. func getResponse() (resp *Response) {
  121. // TODO add a pool
  122. resp = &Response{}
  123. return
  124. }