gearman-go/worker/agent.go

129 lines
2.3 KiB
Go
Raw Normal View History

// Copyright 2011 Xing Xing <mikespook@gmail.com> All rights reserved.
// Use of this source code is governed by a MIT
// license that can be found in the LICENSE file.
package worker
import (
2013-08-30 12:36:57 +08:00
"io"
"net"
)
// The agent of job server.
type agent struct {
2013-08-30 12:36:57 +08:00
conn net.Conn
worker *Worker
in chan []byte
2013-08-30 18:01:10 +08:00
net, addr string
isConn bool
}
// Create the agent of job server.
2013-08-30 18:01:10 +08:00
func newAgent(net, addr string, worker *Worker) (a *agent, err error) {
2013-08-30 12:36:57 +08:00
a = &agent{
2013-08-30 18:01:10 +08:00
net: net,
2013-08-30 12:36:57 +08:00
addr: addr,
2013-08-30 18:01:10 +08:00
worker: worker,
in: make(chan []byte, QUEUE_SIZE),
2013-08-30 12:36:57 +08:00
}
return
}
2013-08-30 18:01:10 +08:00
func (a *agent) Connect() (err error) {
a.conn, err = net.Dial(a.net, a.addr)
if err != nil {
return
2013-08-30 12:36:57 +08:00
}
2013-08-30 18:01:10 +08:00
a.isConn = true
return
}
2013-08-30 18:01:10 +08:00
func (a *agent) Work() {
go a.readLoop()
var resp *Response
var l int
var err error
var data, leftdata []byte
for data = range a.in {
if len(leftdata) > 0 { // some data left for processing
data = append(leftdata, data...)
2013-08-30 12:36:57 +08:00
}
2013-08-30 18:01:10 +08:00
l = len(data)
if l < MIN_PACKET_LEN { // not enough data
leftdata = data
2013-08-30 12:36:57 +08:00
continue
}
2013-08-30 18:01:10 +08:00
if resp, l, err = decodeResponse(data); err != nil {
2013-08-30 12:36:57 +08:00
a.worker.err(err)
continue
}
2013-08-30 18:01:10 +08:00
leftdata = nil
resp.agentId = a.net + a.addr
a.worker.in <- resp
if len(data) > l {
leftdata = data[l:]
}
}
}
// read data from socket
func (a *agent) readLoop() {
var data []byte
var err error
for a.isConn {
if data, err = a.read(BUFFER_SIZE); err != nil {
if err == ErrConnClosed {
break
2013-08-30 12:36:57 +08:00
}
2013-08-30 18:01:10 +08:00
a.worker.err(err)
continue
2013-08-30 12:36:57 +08:00
}
2013-08-30 18:01:10 +08:00
a.in <- data
2013-08-30 12:36:57 +08:00
}
2013-08-30 18:01:10 +08:00
close(a.in)
}
2012-05-28 10:34:16 +08:00
func (a *agent) Close() {
2013-08-30 12:36:57 +08:00
a.conn.Close()
2012-05-28 10:34:16 +08:00
}
2013-08-30 18:01:10 +08:00
// read length bytes from the socket
func (a *agent) read(length int) (data []byte, err error) {
2013-08-30 12:36:57 +08:00
n := 0
2013-08-30 18:01:10 +08:00
buf := getBuffer(BUFFER_SIZE)
2013-08-30 12:36:57 +08:00
// read until data can be unpacked
2013-08-30 18:01:10 +08:00
for i := length; i > 0 || len(data) < MIN_PACKET_LEN; i -= n {
2013-08-30 12:36:57 +08:00
if n, err = a.conn.Read(buf); err != nil {
2013-08-30 18:01:10 +08:00
if !a.isConn {
err = ErrConnClosed
return
}
2013-08-30 12:36:57 +08:00
if err == io.EOF && n == 0 {
if data == nil {
2013-08-30 18:01:10 +08:00
err = ErrConnection
2013-08-30 12:36:57 +08:00
}
}
return
}
data = append(data, buf[0:n]...)
2013-08-30 18:01:10 +08:00
if n < BUFFER_SIZE {
2013-08-30 12:36:57 +08:00
break
}
}
return
2012-12-28 21:19:58 +08:00
}
// Internal write the encoded job.
2013-08-30 18:01:10 +08:00
func (a *agent) write(req *request) (err error) {
2013-08-30 12:36:57 +08:00
var n int
2013-08-30 18:01:10 +08:00
buf := req.Encode()
2013-08-30 12:36:57 +08:00
for i := 0; i < len(buf); i += n {
n, err = a.conn.Write(buf[i:])
if err != nil {
return err
}
}
return
}