2012-03-26 13:32:59 +08:00
|
|
|
package worker
|
|
|
|
|
|
|
|
import (
|
2014-01-09 17:58:02 +08:00
|
|
|
"bufio"
|
2014-09-30 09:01:50 +08:00
|
|
|
"encoding/binary"
|
2013-08-30 12:36:57 +08:00
|
|
|
"net"
|
2013-12-26 12:06:47 +08:00
|
|
|
"sync"
|
2012-03-26 13:32:59 +08:00
|
|
|
)
|
|
|
|
|
|
|
|
// The agent of job server.
|
2012-05-24 16:49:35 +08:00
|
|
|
type agent struct {
|
2013-12-26 12:06:47 +08:00
|
|
|
sync.Mutex
|
2013-12-23 17:05:42 +08:00
|
|
|
conn net.Conn
|
2014-01-09 17:58:02 +08:00
|
|
|
rw *bufio.ReadWriter
|
2013-12-23 17:05:42 +08:00
|
|
|
worker *Worker
|
|
|
|
in chan []byte
|
|
|
|
net, addr string
|
2012-03-26 13:32:59 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// 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-12-23 17:05:42 +08:00
|
|
|
net: net,
|
2013-08-30 12:36:57 +08:00
|
|
|
addr: addr,
|
2013-08-30 18:01:10 +08:00
|
|
|
worker: worker,
|
2013-12-26 12:32:27 +08:00
|
|
|
in: make(chan []byte, queueSize),
|
2013-08-30 12:36:57 +08:00
|
|
|
}
|
|
|
|
return
|
2012-05-24 16:49:35 +08:00
|
|
|
}
|
|
|
|
|
2013-08-30 18:01:10 +08:00
|
|
|
func (a *agent) Connect() (err error) {
|
2013-12-26 12:06:47 +08:00
|
|
|
a.Lock()
|
|
|
|
defer a.Unlock()
|
2013-08-30 18:01:10 +08:00
|
|
|
a.conn, err = net.Dial(a.net, a.addr)
|
|
|
|
if err != nil {
|
|
|
|
return
|
2013-08-30 12:36:57 +08:00
|
|
|
}
|
2014-01-09 16:16:34 +08:00
|
|
|
a.rw = bufio.NewReadWriter(bufio.NewReader(a.conn),
|
|
|
|
bufio.NewWriter(a.conn))
|
2013-12-24 14:35:33 +08:00
|
|
|
go a.work()
|
2013-08-30 18:01:10 +08:00
|
|
|
return
|
2012-05-24 16:49:35 +08:00
|
|
|
}
|
|
|
|
|
2013-12-24 14:35:33 +08:00
|
|
|
func (a *agent) work() {
|
2013-12-29 17:09:06 +08:00
|
|
|
defer func() {
|
|
|
|
if err := recover(); err != nil {
|
|
|
|
a.worker.err(err.(error))
|
|
|
|
}
|
|
|
|
}()
|
2013-12-21 11:09:13 +08:00
|
|
|
var inpack *inPack
|
2013-08-30 18:01:10 +08:00
|
|
|
var l int
|
|
|
|
var err error
|
|
|
|
var data, leftdata []byte
|
2013-12-24 14:35:33 +08:00
|
|
|
for {
|
2013-12-26 12:32:27 +08:00
|
|
|
if data, err = a.read(bufferSize); err != nil {
|
2014-03-03 14:45:35 +08:00
|
|
|
if opErr, ok := err.(*net.OpError); ok {
|
|
|
|
if opErr.Timeout() {
|
|
|
|
a.worker.err(err)
|
|
|
|
}
|
|
|
|
if opErr.Temporary() {
|
|
|
|
continue
|
|
|
|
}
|
2013-12-26 12:06:47 +08:00
|
|
|
break
|
|
|
|
}
|
2013-12-26 15:55:16 +08:00
|
|
|
a.worker.err(err)
|
2013-12-26 12:06:47 +08:00
|
|
|
// If it is unexpected error and the connection wasn't
|
2013-12-26 15:28:42 +08:00
|
|
|
// closed by Gearmand, the agent should close the conection
|
2013-12-26 12:06:47 +08:00
|
|
|
// and reconnect to job server.
|
2013-12-26 15:28:42 +08:00
|
|
|
a.Close()
|
2013-12-26 12:06:47 +08:00
|
|
|
a.conn, err = net.Dial(a.net, a.addr)
|
|
|
|
if err != nil {
|
|
|
|
a.worker.err(err)
|
2013-12-21 11:09:13 +08:00
|
|
|
break
|
|
|
|
}
|
2014-01-09 16:16:34 +08:00
|
|
|
a.rw = bufio.NewReadWriter(bufio.NewReader(a.conn),
|
|
|
|
bufio.NewWriter(a.conn))
|
2013-12-21 11:09:13 +08:00
|
|
|
}
|
2013-08-30 18:01:10 +08:00
|
|
|
if len(leftdata) > 0 { // some data left for processing
|
|
|
|
data = append(leftdata, data...)
|
2013-08-30 12:36:57 +08:00
|
|
|
}
|
2014-09-30 09:01:50 +08:00
|
|
|
length := len(data) - minPacketLength
|
|
|
|
if length < 0 || length < int(binary.BigEndian.Uint32(data[8:12])) {
|
2013-08-30 18:01:10 +08:00
|
|
|
leftdata = data
|
2013-08-30 12:36:57 +08:00
|
|
|
continue
|
|
|
|
}
|
2013-12-21 11:09:13 +08:00
|
|
|
if inpack, l, err = decodeInPack(data); err != nil {
|
2013-08-30 12:36:57 +08:00
|
|
|
a.worker.err(err)
|
2014-01-15 00:06:20 +08:00
|
|
|
leftdata = data
|
2013-08-30 12:36:57 +08:00
|
|
|
continue
|
|
|
|
}
|
2013-08-30 18:01:10 +08:00
|
|
|
leftdata = nil
|
2013-12-21 11:09:13 +08:00
|
|
|
inpack.a = a
|
|
|
|
a.worker.in <- inpack
|
2013-08-30 18:01:10 +08:00
|
|
|
if len(data) > l {
|
|
|
|
leftdata = data[l:]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-05-28 10:34:16 +08:00
|
|
|
func (a *agent) Close() {
|
2013-12-26 12:06:47 +08:00
|
|
|
a.Lock()
|
|
|
|
defer a.Unlock()
|
|
|
|
if a.conn != nil {
|
|
|
|
a.conn.Close()
|
|
|
|
a.conn = nil
|
|
|
|
}
|
2013-12-23 17:01:01 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
func (a *agent) Grab() {
|
2013-12-26 12:06:47 +08:00
|
|
|
a.Lock()
|
|
|
|
defer a.Unlock()
|
2013-12-23 17:01:01 +08:00
|
|
|
outpack := getOutPack()
|
2013-12-26 12:32:27 +08:00
|
|
|
outpack.dataType = dtGrabJobUniq
|
2013-12-23 17:01:01 +08:00
|
|
|
a.write(outpack)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (a *agent) PreSleep() {
|
2013-12-26 12:06:47 +08:00
|
|
|
a.Lock()
|
|
|
|
defer a.Unlock()
|
2013-12-23 17:01:01 +08:00
|
|
|
outpack := getOutPack()
|
2013-12-26 12:32:27 +08:00
|
|
|
outpack.dataType = dtPreSleep
|
2013-12-23 17:01:01 +08:00
|
|
|
a.write(outpack)
|
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-12-26 12:32:27 +08:00
|
|
|
buf := getBuffer(bufferSize)
|
2013-08-30 12:36:57 +08:00
|
|
|
// read until data can be unpacked
|
2013-12-26 12:32:27 +08:00
|
|
|
for i := length; i > 0 || len(data) < minPacketLength; i -= n {
|
2014-01-09 16:16:34 +08:00
|
|
|
if n, err = a.rw.Read(buf); err != nil {
|
2013-08-30 12:36:57 +08:00
|
|
|
return
|
|
|
|
}
|
|
|
|
data = append(data, buf[0:n]...)
|
2013-12-26 12:32:27 +08:00
|
|
|
if n < bufferSize {
|
2013-08-30 12:36:57 +08:00
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return
|
2012-12-28 21:19:58 +08:00
|
|
|
}
|
|
|
|
|
2012-03-26 13:32:59 +08:00
|
|
|
// Internal write the encoded job.
|
2013-12-21 11:09:13 +08:00
|
|
|
func (a *agent) write(outpack *outPack) (err error) {
|
2013-08-30 12:36:57 +08:00
|
|
|
var n int
|
2013-12-21 11:09:13 +08:00
|
|
|
buf := outpack.Encode()
|
2013-08-30 12:36:57 +08:00
|
|
|
for i := 0; i < len(buf); i += n {
|
2014-01-09 16:16:34 +08:00
|
|
|
n, err = a.rw.Write(buf[i:])
|
2013-08-30 12:36:57 +08:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
2014-01-09 16:16:34 +08:00
|
|
|
return a.rw.Flush()
|
2012-03-26 13:32:59 +08:00
|
|
|
}
|