fixed the infinite loop of client
This commit is contained in:
		
							parent
							
								
									16a965f52d
								
							
						
					
					
						commit
						af05460727
					
				@ -193,15 +193,15 @@ func (client *Client) inLoop() {
 | 
				
			|||||||
        if err != nil {
 | 
					        if err != nil {
 | 
				
			||||||
            if err == common.ErrConnection {
 | 
					            if err == common.ErrConnection {
 | 
				
			||||||
                client.Close()
 | 
					                client.Close()
 | 
				
			||||||
                break
 | 
					 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            client.err(err)
 | 
					            client.err(err)
 | 
				
			||||||
            continue
 | 
					            break
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        job, err := decodeJob(rel)
 | 
					        job, err := decodeJob(rel)
 | 
				
			||||||
        if err != nil {
 | 
					        if err != nil {
 | 
				
			||||||
            client.err(err)
 | 
					            client.err(err)
 | 
				
			||||||
            continue
 | 
					            continue
 | 
				
			||||||
 | 
					            //break
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        switch job.DataType {
 | 
					        switch job.DataType {
 | 
				
			||||||
        case common.ERROR:
 | 
					        case common.ERROR:
 | 
				
			||||||
@ -216,6 +216,8 @@ func (client *Client) inLoop() {
 | 
				
			|||||||
            client.handleCreated(job)
 | 
					            client.handleCreated(job)
 | 
				
			||||||
        case common.STATUS_RES:
 | 
					        case common.STATUS_RES:
 | 
				
			||||||
            client.handleStatus(job)
 | 
					            client.handleStatus(job)
 | 
				
			||||||
 | 
					        default:
 | 
				
			||||||
 | 
					            break
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -350,12 +352,11 @@ func (client *Client) Echo(data []byte) (r []byte) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Close
 | 
					// Close
 | 
				
			||||||
func (client *Client) Close() (err error) {
 | 
					func (client *Client) Close() (err error) {
 | 
				
			||||||
//    close(client.in)
 | 
					    close(client.in)
 | 
				
			||||||
    close(client.out)
 | 
					    close(client.out)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    close(client.echo)
 | 
					    close(client.echo)
 | 
				
			||||||
    close(client.created)
 | 
					    close(client.created)
 | 
				
			||||||
    close(client.status)
 | 
					    close(client.status)
 | 
				
			||||||
 | 
					 | 
				
			||||||
    return client.conn.Close();
 | 
					    return client.conn.Close();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										121
									
								
								client/pool.go
									
									
									
									
									
								
							
							
						
						
									
										121
									
								
								client/pool.go
									
									
									
									
									
								
							@ -6,55 +6,35 @@
 | 
				
			|||||||
package client
 | 
					package client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
    "fmt"
 | 
					    "sync"
 | 
				
			||||||
    "time"
 | 
					 | 
				
			||||||
    "errors"
 | 
					 | 
				
			||||||
    "math/rand"
 | 
					    "math/rand"
 | 
				
			||||||
    "github.com/mikespook/gearman-go/common"
 | 
					    "github.com/mikespook/gearman-go/common"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
    PoolSize = 10
 | 
					    PoolSize = 10
 | 
				
			||||||
    DefaultRetry = 5
 | 
					 | 
				
			||||||
    DefaultTimeout = 30 * time.Second
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					type poolClient struct {
 | 
				
			||||||
    ErrTooMany = errors.New("Too many errors occurred.")
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type poolItem struct {
 | 
					 | 
				
			||||||
    *Client
 | 
					    *Client
 | 
				
			||||||
    Rate int
 | 
					    Rate int
 | 
				
			||||||
    Addr string
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (item *poolItem) connect(pool *Pool) (err error) {
 | 
					type SelectionHandler func(map[string]*poolClient, string) string
 | 
				
			||||||
    if item.Client, err = New(item.Addr); err != nil {
 | 
					 | 
				
			||||||
        return
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    if pool.ErrHandler != nil {
 | 
					 | 
				
			||||||
        item.ErrHandler = pool.ErrHandler
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    return
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func SelectWithRate(pool map[string]*poolClient,
 | 
				
			||||||
type SelectionHandler func(map[string]*poolItem, string) string
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func SelectWithRate(pool map[string]*poolItem,
 | 
					 | 
				
			||||||
last string) (addr string) {
 | 
					last string) (addr string) {
 | 
				
			||||||
    total := 0
 | 
					    total := 0
 | 
				
			||||||
    for _, item := range pool {
 | 
					    for _, item := range pool {
 | 
				
			||||||
        total += item.Rate
 | 
					        total += item.Rate
 | 
				
			||||||
        if rand.Intn(total) < item.Rate {
 | 
					        if rand.Intn(total) < item.Rate {
 | 
				
			||||||
            return item.Addr
 | 
					            return item.addr
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return last
 | 
					    return last
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func SelectRandom(pool map[string]*poolItem,
 | 
					func SelectRandom(pool map[string]*poolClient,
 | 
				
			||||||
last string) (addr string) {
 | 
					last string) (addr string) {
 | 
				
			||||||
    r := rand.Intn(len(pool))
 | 
					    r := rand.Intn(len(pool))
 | 
				
			||||||
    i := 0
 | 
					    i := 0
 | 
				
			||||||
@ -72,73 +52,50 @@ last string) (addr string) {
 | 
				
			|||||||
type Pool struct {
 | 
					type Pool struct {
 | 
				
			||||||
    SelectionHandler SelectionHandler
 | 
					    SelectionHandler SelectionHandler
 | 
				
			||||||
    ErrHandler common.ErrorHandler
 | 
					    ErrHandler common.ErrorHandler
 | 
				
			||||||
    JobHandler JobHandler
 | 
					    clients map[string]*poolClient
 | 
				
			||||||
    StatusHandler StatusHandler
 | 
					    mutex sync.Mutex
 | 
				
			||||||
    TimeOut time.Duration
 | 
					 | 
				
			||||||
    Retry int
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    items map[string]*poolItem
 | 
					 | 
				
			||||||
    last string
 | 
					 | 
				
			||||||
    handles map[string]string
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Create a new pool.
 | 
					// Create a new pool.
 | 
				
			||||||
func NewPool() (pool *Pool) {
 | 
					func NewPool() (pool *Pool) {
 | 
				
			||||||
    return &Pool{
 | 
					    return &Pool{
 | 
				
			||||||
        items: make(map[string]*poolItem, PoolSize),
 | 
					        clients: make(map[string]*poolClient, PoolSize),
 | 
				
			||||||
        Retry: DefaultRetry,
 | 
					 | 
				
			||||||
        SelectionHandler: SelectWithRate,
 | 
					        SelectionHandler: SelectWithRate,
 | 
				
			||||||
        TimeOut: DefaultTimeout,
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Add a server with rate.
 | 
					// Add a server with rate.
 | 
				
			||||||
func (pool *Pool) Add(addr string, rate int) (err error) {
 | 
					func (pool *Pool) Add(addr string, rate int) (err error) {
 | 
				
			||||||
    var item *poolItem
 | 
					    pool.mutex.Lock()
 | 
				
			||||||
 | 
					    defer pool.mutex.Unlock()
 | 
				
			||||||
 | 
					    var item *poolClient
 | 
				
			||||||
    var ok bool
 | 
					    var ok bool
 | 
				
			||||||
    if item, ok = pool.items[addr]; ok {
 | 
					    if item, ok = pool.clients[addr]; ok {
 | 
				
			||||||
        item.Rate = rate
 | 
					        item.Rate = rate
 | 
				
			||||||
    } else {
 | 
					    } else {
 | 
				
			||||||
        item = &poolItem{Rate: rate, Addr: addr}
 | 
					        var client *Client
 | 
				
			||||||
        if err = item.connect(pool); err != nil {
 | 
					        client, err = New(addr)
 | 
				
			||||||
            return
 | 
					        item = &poolClient{Client: client, Rate: rate}
 | 
				
			||||||
        }
 | 
					        err = item.connect()
 | 
				
			||||||
        pool.items[addr] = item
 | 
					        pool.clients[addr] = item
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    return
 | 
					    return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Remove a server.
 | 
				
			||||||
 | 
					func (pool *Pool) Remove(addr string) {
 | 
				
			||||||
 | 
					    pool.mutex.Lock()
 | 
				
			||||||
 | 
					    defer pool.mutex.Unlock()
 | 
				
			||||||
 | 
					    delete(pool.clients, addr)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (pool *Pool) Do(funcname string, data []byte,
 | 
					func (pool *Pool) Do(funcname string, data []byte,
 | 
				
			||||||
flag byte, h JobHandler) (addr, handle string, err error) {
 | 
					flag byte, h JobHandler) (handle string, err error) {
 | 
				
			||||||
    for i := 0; i < pool.Retry; i ++ {
 | 
					 | 
				
			||||||
        addr = pool.SelectionHandler(pool.items, pool.last)
 | 
					 | 
				
			||||||
        item, ok := pool.items[addr]
 | 
					 | 
				
			||||||
        if ok {
 | 
					 | 
				
			||||||
            pool.last = addr
 | 
					 | 
				
			||||||
            handle = item.Do(funcname, data, flag, h)
 | 
					 | 
				
			||||||
            // error handling
 | 
					 | 
				
			||||||
            // mapping the handle to the server
 | 
					 | 
				
			||||||
            return
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    err = ErrTooMany
 | 
					 | 
				
			||||||
    return
 | 
					    return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (pool *Pool) DoBg(funcname string, data []byte,
 | 
					func (pool *Pool) DoBg(funcname string, data []byte,
 | 
				
			||||||
flag byte) (addr, handle string, err error) {
 | 
					flag byte) (handle string, err error) {
 | 
				
			||||||
    for i := 0; i < pool.Retry; i ++ {
 | 
					 | 
				
			||||||
        addr = pool.SelectionHandler(pool.items, pool.last)
 | 
					 | 
				
			||||||
        item, ok := pool.items[addr]
 | 
					 | 
				
			||||||
        if ok {
 | 
					 | 
				
			||||||
            pool.last = addr
 | 
					 | 
				
			||||||
            handle = item.DoBg(funcname, data, flag)
 | 
					 | 
				
			||||||
            // error handling
 | 
					 | 
				
			||||||
            // mapping the handle to the server
 | 
					 | 
				
			||||||
            return
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    err = ErrTooMany
 | 
					 | 
				
			||||||
    return
 | 
					    return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -146,32 +103,20 @@ flag byte) (addr, handle string, err error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// Get job status from job server.
 | 
					// Get job status from job server.
 | 
				
			||||||
// !!!Not fully tested.!!!
 | 
					// !!!Not fully tested.!!!
 | 
				
			||||||
func (pool *Pool) Status(addr, handle string) {
 | 
					func (pool *Pool) Status(handle string) (status *Status) {
 | 
				
			||||||
    if item, ok := pool.items[addr]; ok {
 | 
					    return
 | 
				
			||||||
        item.Status(handle)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Send a something out, get the samething back.
 | 
					// Send a something out, get the samething back.
 | 
				
			||||||
func (pool *Pool) Echo(data []byte) {
 | 
					func (pool *Pool) Echo(data []byte) (r []byte) {
 | 
				
			||||||
    for i := 0; i < pool.Retry; i ++ {
 | 
					    return
 | 
				
			||||||
        addr := pool.SelectionHandler(pool.items, pool.last)
 | 
					 | 
				
			||||||
        item, ok := pool.items[addr]
 | 
					 | 
				
			||||||
        if ok {
 | 
					 | 
				
			||||||
            pool.last = addr
 | 
					 | 
				
			||||||
            item.Echo(data)
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Close
 | 
					// Close
 | 
				
			||||||
func (pool *Pool) Close() (err map[string]error) {
 | 
					func (pool *Pool) Close() (err map[string]error) {
 | 
				
			||||||
    err = make(map[string]error)
 | 
					    err = make(map[string]error)
 | 
				
			||||||
    for _, c := range pool.items {
 | 
					    for _, c := range pool.clients {
 | 
				
			||||||
        fmt.Printf("begin")
 | 
					        err[c.addr] = c.Close()
 | 
				
			||||||
        err[c.Addr] = c.Close()
 | 
					 | 
				
			||||||
        fmt.Printf("end")
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    fmt.Print("end-for")
 | 
					 | 
				
			||||||
    return
 | 
					    return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,17 +1,14 @@
 | 
				
			|||||||
package client
 | 
					package client
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
//    "errors"
 | 
					    "testing"
 | 
				
			||||||
//    "testing"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
    pool = NewPool()
 | 
					    pool = NewPool()
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestPoolAdd(t *testing.T) {
 | 
					func TestPoolAdd(t *testing.T) {
 | 
				
			||||||
    return
 | 
					 | 
				
			||||||
    t.Log("Add servers")
 | 
					    t.Log("Add servers")
 | 
				
			||||||
    if err := pool.Add("127.0.0.1:4730", 1); err != nil {
 | 
					    if err := pool.Add("127.0.0.1:4730", 1); err != nil {
 | 
				
			||||||
        t.Error(err)
 | 
					        t.Error(err)
 | 
				
			||||||
@ -19,10 +16,11 @@ func TestPoolAdd(t *testing.T) {
 | 
				
			|||||||
    if err := pool.Add("127.0.0.2:4730", 1); err != nil {
 | 
					    if err := pool.Add("127.0.0.2:4730", 1); err != nil {
 | 
				
			||||||
        t.Error(err)
 | 
					        t.Error(err)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    if len(pool.items) != 2 {
 | 
					    if len(pool.clients) != 2 {
 | 
				
			||||||
        t.Error(errors.New("2 servers expected"))
 | 
					        t.Errorf("2 servers expected, %d got.", len(pool.clients))
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestPoolEcho(t *testing.T) {
 | 
					func TestPoolEcho(t *testing.T) {
 | 
				
			||||||
    pool.JobHandler = func(job *Job) error {
 | 
					    pool.JobHandler = func(job *Job) error {
 | 
				
			||||||
@ -36,8 +34,7 @@ func TestPoolEcho(t *testing.T) {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
    pool.Echo([]byte("Hello world"))
 | 
					    pool.Echo([]byte("Hello world"))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
*/
 | 
					
 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
func TestPoolDo(t *testing.T) {
 | 
					func TestPoolDo(t *testing.T) {
 | 
				
			||||||
    if addr, handle, err := pool.Do("ToUpper", []byte("abcdef"), JOB_LOW|JOB_BG); err != nil {
 | 
					    if addr, handle, err := pool.Do("ToUpper", []byte("abcdef"), JOB_LOW|JOB_BG); err != nil {
 | 
				
			||||||
        t.Error(err)
 | 
					        t.Error(err)
 | 
				
			||||||
@ -45,10 +42,11 @@ func TestPoolDo(t *testing.T) {
 | 
				
			|||||||
        t.Log(handle)
 | 
					        t.Log(handle)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
func TestPoolClose(t *testing.T) {
 | 
					func TestPoolClose(t *testing.T) {
 | 
				
			||||||
    return
 | 
					    return
 | 
				
			||||||
    if err := pool.Close(); err != nil {
 | 
					    if err := pool.Close(); err != nil {
 | 
				
			||||||
        t.Error(err)
 | 
					        t.Error(err)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
*/
 | 
					 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user