2011-03-15 20:21:42 +08:00
|
|
|
package gearman
|
|
|
|
|
|
|
|
import(
|
2011-05-16 17:26:32 +08:00
|
|
|
"os"
|
2011-05-17 18:12:40 +08:00
|
|
|
"sync"
|
|
|
|
"log"
|
2011-03-15 20:21:42 +08:00
|
|
|
)
|
|
|
|
|
2011-05-17 18:12:40 +08:00
|
|
|
type JobFunction func(job *Job) []byte
|
|
|
|
|
2011-05-16 17:26:32 +08:00
|
|
|
type Worker struct {
|
2011-05-17 18:12:40 +08:00
|
|
|
servers []*JobClient
|
|
|
|
functions map[string]JobFunction
|
2011-05-16 17:26:32 +08:00
|
|
|
|
2011-05-17 18:12:40 +08:00
|
|
|
running bool
|
|
|
|
incoming chan *Job
|
|
|
|
mutex sync.Mutex
|
|
|
|
queue chan *Job
|
2011-03-15 20:21:42 +08:00
|
|
|
}
|
|
|
|
|
2011-05-16 17:26:32 +08:00
|
|
|
func NewWorker() (worker *Worker) {
|
2011-05-17 18:12:40 +08:00
|
|
|
worker = &Worker{servers:make([]*JobClient, 0, WORKER_SERVER_CAP),
|
|
|
|
functions: make(map[string]JobFunction),
|
|
|
|
incoming: make(chan *Job, 512),
|
|
|
|
queue: make(chan *Job, 512),
|
|
|
|
running: true,}
|
2011-03-15 20:21:42 +08:00
|
|
|
return worker
|
|
|
|
}
|
|
|
|
|
|
|
|
// add server
|
2011-05-16 17:26:32 +08:00
|
|
|
// worker.AddServer("127.0.0.1:4730")
|
|
|
|
func (worker * Worker) AddServer(addr string) (err os.Error) {
|
2011-05-17 18:12:40 +08:00
|
|
|
worker.mutex.Lock()
|
|
|
|
defer worker.mutex.Unlock()
|
|
|
|
|
2011-05-16 17:26:32 +08:00
|
|
|
if len(worker.servers) == cap(worker.servers) {
|
|
|
|
return os.NewError("There were too many servers.")
|
2011-03-15 20:21:42 +08:00
|
|
|
}
|
2011-05-17 18:12:40 +08:00
|
|
|
|
|
|
|
// Create a new job server's client as a agent of server
|
|
|
|
server, err := NewJobClient(addr, worker.incoming)
|
2011-05-16 17:26:32 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2011-05-17 18:12:40 +08:00
|
|
|
|
2011-05-16 17:26:32 +08:00
|
|
|
n := len(worker.servers)
|
|
|
|
worker.servers = worker.servers[0: n + 1]
|
2011-05-17 18:12:40 +08:00
|
|
|
worker.servers[n] = server
|
|
|
|
return
|
2011-03-15 20:21:42 +08:00
|
|
|
}
|
2011-05-17 18:12:40 +08:00
|
|
|
|
2011-03-15 20:21:42 +08:00
|
|
|
|
|
|
|
// add function
|
2011-05-17 18:12:40 +08:00
|
|
|
func (worker * Worker) AddFunction(funcname string,
|
|
|
|
f JobFunction) (err os.Error) {
|
|
|
|
worker.mutex.Lock()
|
|
|
|
defer worker.mutex.Unlock()
|
2011-05-16 17:26:32 +08:00
|
|
|
|
2011-05-17 18:12:40 +08:00
|
|
|
if f == nil {
|
|
|
|
return os.NewError("Job function should not be nil.")
|
|
|
|
}
|
|
|
|
worker.functions[funcname] = f
|
|
|
|
return
|
2011-03-15 20:21:42 +08:00
|
|
|
}
|
|
|
|
// work
|
2011-05-17 18:12:40 +08:00
|
|
|
func (worker * Worker) Work() {
|
2011-05-17 20:32:36 +08:00
|
|
|
for k, _ := range worker.functions {
|
|
|
|
job := NewJob(nil, REQ, CAN_DO, []byte(k))
|
|
|
|
worker.Write(job)
|
|
|
|
}
|
|
|
|
|
2011-05-17 18:12:40 +08:00
|
|
|
for _, v := range worker.servers {
|
|
|
|
go v.Work()
|
|
|
|
}
|
|
|
|
for worker.running {
|
|
|
|
select {
|
|
|
|
case job := <-worker.incoming:
|
2011-05-17 20:32:36 +08:00
|
|
|
if job == nil {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
switch job.DataType {
|
|
|
|
case ERROR:
|
|
|
|
log.Panicln(string(job.Data))
|
|
|
|
default:
|
|
|
|
if err := worker.Exec(job); err != nil {
|
|
|
|
log.Panicln(err)
|
|
|
|
}
|
2011-05-17 18:12:40 +08:00
|
|
|
}
|
|
|
|
worker.queue <- job
|
|
|
|
}
|
2011-03-15 20:21:42 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-05-17 18:12:40 +08:00
|
|
|
func (worker * Worker) Result() (job *Job) {
|
|
|
|
if l := len(worker.queue); l != 1 {
|
|
|
|
if l == 0 {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
for i := 0; i < l - 1; i ++ {
|
|
|
|
<-worker.queue
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return <-worker.queue
|
|
|
|
}
|
|
|
|
|
2011-05-16 17:26:32 +08:00
|
|
|
// Close
|
2011-03-15 20:21:42 +08:00
|
|
|
// should used as defer
|
2011-05-17 18:12:40 +08:00
|
|
|
func (worker * Worker) Close() (err os.Error){
|
|
|
|
worker.running = false
|
|
|
|
for _, v := range worker.servers {
|
|
|
|
err = v.Close()
|
|
|
|
}
|
|
|
|
close(worker.incoming)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
2011-05-17 20:32:36 +08:00
|
|
|
func (worker * Worker) Write(job *Job) (err os.Error) {
|
2011-05-17 18:12:40 +08:00
|
|
|
e := make(chan os.Error)
|
|
|
|
for _, v := range worker.servers {
|
|
|
|
go func() {
|
2011-05-17 20:32:36 +08:00
|
|
|
job.client = v
|
|
|
|
e <- v.WriteJob(job)
|
2011-05-17 18:12:40 +08:00
|
|
|
}()
|
|
|
|
}
|
|
|
|
return <- e
|
|
|
|
}
|
|
|
|
|
2011-05-17 20:32:36 +08:00
|
|
|
// Echo
|
|
|
|
func (worker * Worker) Echo(data []byte) (err os.Error) {
|
|
|
|
job := NewJob(nil, REQ, ECHO_REQ, data)
|
|
|
|
return worker.Write(job)
|
|
|
|
}
|
|
|
|
|
2011-05-17 18:12:40 +08:00
|
|
|
// Exec
|
|
|
|
func (worker * Worker) Exec(job *Job) (err os.Error) {
|
|
|
|
return
|
2011-03-15 20:21:42 +08:00
|
|
|
}
|