25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

217 lines
5.2 KiB

  1. package gearman
  2. import(
  3. "os"
  4. "sync"
  5. // "log"
  6. )
  7. type JobFunction func(job *WorkerJob) ([]byte, os.Error)
  8. type JobFunctionMap map[string]JobFunction
  9. type Worker struct {
  10. clients []*jobClient
  11. functions JobFunctionMap
  12. running bool
  13. incoming chan *WorkerJob
  14. mutex sync.Mutex
  15. JobQueue chan *WorkerJob
  16. ErrQueue chan os.Error
  17. }
  18. func NewWorker() (worker *Worker) {
  19. worker = &Worker{
  20. // job server list
  21. clients:make([]*jobClient, 0, WORKER_SERVER_CAP),
  22. // function list
  23. functions: make(JobFunctionMap),
  24. incoming: make(chan *WorkerJob, QUEUE_CAP),
  25. JobQueue: make(chan *WorkerJob, QUEUE_CAP),
  26. ErrQueue: make(chan os.Error, QUEUE_CAP),
  27. running: true,
  28. }
  29. return
  30. }
  31. // add server
  32. // worker.AddServer("127.0.0.1:4730")
  33. func (worker * Worker) AddServer(addr string) (err os.Error) {
  34. worker.mutex.Lock()
  35. defer worker.mutex.Unlock()
  36. if len(worker.clients) == cap(worker.clients) {
  37. return os.NewError("There were too many clients.")
  38. }
  39. // Create a new job server's client as a agent of server
  40. server, err := newJobClient(addr, worker)
  41. if err != nil {
  42. return err
  43. }
  44. n := len(worker.clients)
  45. worker.clients = worker.clients[0: n + 1]
  46. worker.clients[n] = server
  47. return
  48. }
  49. // add function
  50. func (worker * Worker) AddFunction(funcname string,
  51. f JobFunction, timeout uint32) (err os.Error) {
  52. if f == nil {
  53. return os.NewError("Job function should not be nil.")
  54. }
  55. if len(worker.clients) < 1 {
  56. return os.NewError("Did not connect to Job Server.")
  57. }
  58. worker.mutex.Lock()
  59. defer worker.mutex.Unlock()
  60. worker.functions[funcname] = f
  61. var datatype uint32
  62. var data []byte
  63. if timeout == 0 {
  64. datatype = CAN_DO
  65. data = []byte(funcname)
  66. } else {
  67. datatype = CAN_DO_TIMEOUT
  68. data = []byte(funcname + "\x00")
  69. t := uint32ToByte(timeout)
  70. data = append(data, t[:] ...)
  71. }
  72. job := NewWorkerJob(REQ, datatype, data)
  73. worker.WriteJob(job)
  74. return
  75. }
  76. // remove function
  77. func (worker * Worker) RemoveFunction(funcname string) (err os.Error) {
  78. worker.mutex.Lock()
  79. defer worker.mutex.Unlock()
  80. if worker.functions[funcname] == nil {
  81. return os.NewError("No function named: " + funcname)
  82. }
  83. worker.functions[funcname] = nil, false
  84. job := NewWorkerJob(REQ, CANT_DO, []byte(funcname))
  85. worker.WriteJob(job)
  86. return
  87. }
  88. // work
  89. func (worker * Worker) Work() {
  90. for _, v := range worker.clients {
  91. go v.Work()
  92. }
  93. for worker.running {
  94. select {
  95. case job := <-worker.incoming:
  96. if job == nil {
  97. break
  98. }
  99. switch job.dataType {
  100. case NO_JOB:
  101. // do nothing
  102. case ERROR:
  103. _, err := getError(job.Data)
  104. worker.ErrQueue <- err
  105. case JOB_ASSIGN, JOB_ASSIGN_UNIQ:
  106. if err := worker.exec(job); err != nil {
  107. worker.ErrQueue <- err
  108. }
  109. continue
  110. default:
  111. worker.JobQueue <- job
  112. }
  113. }
  114. }
  115. }
  116. func (worker * Worker) LastResult() (job *WorkerJob) {
  117. if l := len(worker.JobQueue); l != 1 {
  118. if l == 0 {
  119. return
  120. }
  121. for i := 0; i < l - 1; i ++ {
  122. <-worker.JobQueue
  123. }
  124. }
  125. return <-worker.JobQueue
  126. }
  127. // Close
  128. // should used as defer
  129. func (worker * Worker) Close() (err os.Error){
  130. worker.running = false
  131. for _, v := range worker.clients {
  132. err = v.Close()
  133. }
  134. close(worker.incoming)
  135. return err
  136. }
  137. func (worker * Worker) WriteJob(job *WorkerJob) (err os.Error) {
  138. e := make(chan os.Error)
  139. for _, v := range worker.clients {
  140. go func() {
  141. e <- v.WriteJob(job)
  142. }()
  143. }
  144. return <- e
  145. }
  146. // Echo
  147. func (worker * Worker) Echo(data []byte) (err os.Error) {
  148. job := NewWorkerJob(REQ, ECHO_REQ, data)
  149. return worker.WriteJob(job)
  150. }
  151. // Reset
  152. func (worker * Worker) Reset() (err os.Error){
  153. job := NewWorkerJob(REQ, RESET_ABILITIES, nil)
  154. return worker.WriteJob(job)
  155. }
  156. // SetId
  157. func (worker * Worker) SetId(id string) (err os.Error) {
  158. job := NewWorkerJob(REQ, SET_CLIENT_ID, []byte(id))
  159. return worker.WriteJob(job)
  160. }
  161. // Exec
  162. func (worker * Worker) exec(job *WorkerJob) (err os.Error) {
  163. jobdata := splitByteArray(job.Data, '\x00')
  164. job.Handle = string(jobdata[0])
  165. funcname := string(jobdata[1])
  166. if job.dataType == JOB_ASSIGN {
  167. job.Data = jobdata[2]
  168. } else {
  169. job.UniqueId = string(jobdata[2])
  170. job.Data = jobdata[3]
  171. }
  172. f := worker.functions[funcname]
  173. if f == nil {
  174. return os.NewError("function is nil")
  175. }
  176. result, err := f(job)
  177. var datatype uint32
  178. if err == nil {
  179. datatype = WORK_COMPLETE
  180. } else{
  181. if result == nil {
  182. datatype = WORK_FAIL
  183. } else {
  184. datatype = WORK_EXCEPTION
  185. }
  186. }
  187. job.magicCode = REQ
  188. job.dataType = datatype
  189. job.Data = result
  190. worker.WriteJob(job)
  191. return
  192. }