Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

13 лет назад
13 лет назад
13 лет назад
13 лет назад
13 лет назад
13 лет назад
13 лет назад
13 лет назад
13 лет назад
13 лет назад
13 лет назад
13 лет назад
13 лет назад
13 лет назад
13 лет назад
13 лет назад
13 лет назад
13 лет назад
13 лет назад
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  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. }