forked from yuxh/gearman-go
		
	Merge pull request #70 from JessonChan/master
concurrent map bug fixed #70
This commit is contained in:
		
						commit
						b79fee2965
					
				@ -19,8 +19,8 @@ type Client struct {
 | 
				
			|||||||
	sync.Mutex
 | 
						sync.Mutex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	net, addr, lastcall string
 | 
						net, addr, lastcall string
 | 
				
			||||||
	respHandler         map[string]ResponseHandler
 | 
						respHandler         *responseHandlerMap
 | 
				
			||||||
	innerHandler        map[string]ResponseHandler
 | 
						innerHandler        *responseHandlerMap
 | 
				
			||||||
	in                  chan *Response
 | 
						in                  chan *Response
 | 
				
			||||||
	conn                net.Conn
 | 
						conn                net.Conn
 | 
				
			||||||
	rw                  *bufio.ReadWriter
 | 
						rw                  *bufio.ReadWriter
 | 
				
			||||||
@ -30,13 +30,40 @@ type Client struct {
 | 
				
			|||||||
	ErrorHandler ErrorHandler
 | 
						ErrorHandler ErrorHandler
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type responseHandlerMap struct {
 | 
				
			||||||
 | 
						sync.RWMutex
 | 
				
			||||||
 | 
						holder map[string]ResponseHandler
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func newResponseHandlerMap() *responseHandlerMap {
 | 
				
			||||||
 | 
						return &responseHandlerMap{holder: make(map[string]ResponseHandler, queueSize)}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *responseHandlerMap) remove(key string) {
 | 
				
			||||||
 | 
						r.Lock()
 | 
				
			||||||
 | 
						delete(r.holder, key)
 | 
				
			||||||
 | 
						r.Unlock()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (r *responseHandlerMap) get(key string) (ResponseHandler, bool) {
 | 
				
			||||||
 | 
						r.RLock()
 | 
				
			||||||
 | 
						rh, b := r.holder[key]
 | 
				
			||||||
 | 
						r.RUnlock()
 | 
				
			||||||
 | 
						return rh, b
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (r *responseHandlerMap) put(key string, rh ResponseHandler) {
 | 
				
			||||||
 | 
						r.Lock()
 | 
				
			||||||
 | 
						r.holder[key] = rh
 | 
				
			||||||
 | 
						r.Unlock()
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Return a client.
 | 
					// Return a client.
 | 
				
			||||||
func New(network, addr string) (client *Client, err error) {
 | 
					func New(network, addr string) (client *Client, err error) {
 | 
				
			||||||
	client = &Client{
 | 
						client = &Client{
 | 
				
			||||||
		net:             network,
 | 
							net:             network,
 | 
				
			||||||
		addr:            addr,
 | 
							addr:            addr,
 | 
				
			||||||
		respHandler:     make(map[string]ResponseHandler, queueSize),
 | 
							respHandler:     newResponseHandlerMap(),
 | 
				
			||||||
		innerHandler:    make(map[string]ResponseHandler, queueSize),
 | 
							innerHandler:    newResponseHandlerMap(),
 | 
				
			||||||
		in:              make(chan *Response, queueSize),
 | 
							in:              make(chan *Response, queueSize),
 | 
				
			||||||
		ResponseTimeout: DefaultTimeout,
 | 
							ResponseTimeout: DefaultTimeout,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -155,7 +182,7 @@ func (client *Client) processLoop() {
 | 
				
			|||||||
			resp = client.handleResponse(resp.Handle, resp)
 | 
								resp = client.handleResponse(resp.Handle, resp)
 | 
				
			||||||
		case dtWorkComplete, dtWorkFail, dtWorkException:
 | 
							case dtWorkComplete, dtWorkFail, dtWorkException:
 | 
				
			||||||
			client.handleResponse(resp.Handle, resp)
 | 
								client.handleResponse(resp.Handle, resp)
 | 
				
			||||||
			delete(client.respHandler, resp.Handle)
 | 
								client.respHandler.remove(resp.Handle)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -167,7 +194,7 @@ func (client *Client) err(e error) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (client *Client) handleResponse(key string, resp *Response) *Response {
 | 
					func (client *Client) handleResponse(key string, resp *Response) *Response {
 | 
				
			||||||
	if h, ok := client.respHandler[key]; ok {
 | 
						if h, ok := client.respHandler.get(key); ok {
 | 
				
			||||||
		h(resp)
 | 
							h(resp)
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -175,9 +202,9 @@ func (client *Client) handleResponse(key string, resp *Response) *Response {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (client *Client) handleInner(key string, resp *Response) *Response {
 | 
					func (client *Client) handleInner(key string, resp *Response) *Response {
 | 
				
			||||||
	if h, ok := client.innerHandler[key]; ok {
 | 
						if h, ok := client.innerHandler.get(key); ok {
 | 
				
			||||||
		h(resp)
 | 
							h(resp)
 | 
				
			||||||
		delete(client.innerHandler, key)
 | 
							client.innerHandler.remove(key)
 | 
				
			||||||
		return nil
 | 
							return nil
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return resp
 | 
						return resp
 | 
				
			||||||
@ -195,7 +222,7 @@ func (client *Client) do(funcname string, data []byte,
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	var result = make(chan handleOrError, 1)
 | 
						var result = make(chan handleOrError, 1)
 | 
				
			||||||
	client.lastcall = "c"
 | 
						client.lastcall = "c"
 | 
				
			||||||
	client.innerHandler["c"] = func(resp *Response) {
 | 
						client.innerHandler.put("c", func(resp *Response) {
 | 
				
			||||||
		if resp.DataType == dtError {
 | 
							if resp.DataType == dtError {
 | 
				
			||||||
			err = getError(resp.Data)
 | 
								err = getError(resp.Data)
 | 
				
			||||||
			result <- handleOrError{"", err}
 | 
								result <- handleOrError{"", err}
 | 
				
			||||||
@ -203,12 +230,12 @@ func (client *Client) do(funcname string, data []byte,
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
		handle = resp.Handle
 | 
							handle = resp.Handle
 | 
				
			||||||
		result <- handleOrError{handle, nil}
 | 
							result <- handleOrError{handle, nil}
 | 
				
			||||||
	}
 | 
						})
 | 
				
			||||||
	id := IdGen.Id()
 | 
						id := IdGen.Id()
 | 
				
			||||||
	req := getJob(id, []byte(funcname), data)
 | 
						req := getJob(id, []byte(funcname), data)
 | 
				
			||||||
	req.DataType = flag
 | 
						req.DataType = flag
 | 
				
			||||||
	if err = client.write(req); err != nil {
 | 
						if err = client.write(req); err != nil {
 | 
				
			||||||
		delete(client.innerHandler, "c")
 | 
							client.innerHandler.remove("c")
 | 
				
			||||||
		client.lastcall = ""
 | 
							client.lastcall = ""
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -217,7 +244,7 @@ func (client *Client) do(funcname string, data []byte,
 | 
				
			|||||||
	case ret := <-result:
 | 
						case ret := <-result:
 | 
				
			||||||
		return ret.handle, ret.err
 | 
							return ret.handle, ret.err
 | 
				
			||||||
	case <-timer:
 | 
						case <-timer:
 | 
				
			||||||
		delete(client.innerHandler, "c")
 | 
							client.innerHandler.remove("c")
 | 
				
			||||||
		client.lastcall = ""
 | 
							client.lastcall = ""
 | 
				
			||||||
		return "", ErrLostConn
 | 
							return "", ErrLostConn
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -239,7 +266,7 @@ func (client *Client) Do(funcname string, data []byte,
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	handle, err = client.do(funcname, data, datatype)
 | 
						handle, err = client.do(funcname, data, datatype)
 | 
				
			||||||
	if err == nil && h != nil {
 | 
						if err == nil && h != nil {
 | 
				
			||||||
		client.respHandler[handle] = h
 | 
							client.respHandler.put(handle, h)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@ -272,14 +299,14 @@ func (client *Client) Status(handle string) (status *Status, err error) {
 | 
				
			|||||||
	var mutex sync.Mutex
 | 
						var mutex sync.Mutex
 | 
				
			||||||
	mutex.Lock()
 | 
						mutex.Lock()
 | 
				
			||||||
	client.lastcall = "s" + handle
 | 
						client.lastcall = "s" + handle
 | 
				
			||||||
	client.innerHandler["s"+handle] = func(resp *Response) {
 | 
						client.innerHandler.put("s"+handle, func(resp *Response) {
 | 
				
			||||||
		defer mutex.Unlock()
 | 
							defer mutex.Unlock()
 | 
				
			||||||
		var err error
 | 
							var err error
 | 
				
			||||||
		status, err = resp._status()
 | 
							status, err = resp._status()
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			client.err(err)
 | 
								client.err(err)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						})
 | 
				
			||||||
	req := getRequest()
 | 
						req := getRequest()
 | 
				
			||||||
	req.DataType = dtGetStatus
 | 
						req.DataType = dtGetStatus
 | 
				
			||||||
	req.Data = []byte(handle)
 | 
						req.Data = []byte(handle)
 | 
				
			||||||
@ -295,10 +322,10 @@ func (client *Client) Echo(data []byte) (echo []byte, err error) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	var mutex sync.Mutex
 | 
						var mutex sync.Mutex
 | 
				
			||||||
	mutex.Lock()
 | 
						mutex.Lock()
 | 
				
			||||||
	client.innerHandler["e"] = func(resp *Response) {
 | 
						client.innerHandler.put("e", func(resp *Response) {
 | 
				
			||||||
		echo = resp.Data
 | 
							echo = resp.Data
 | 
				
			||||||
		mutex.Unlock()
 | 
							mutex.Unlock()
 | 
				
			||||||
	}
 | 
						})
 | 
				
			||||||
	req := getRequest()
 | 
						req := getRequest()
 | 
				
			||||||
	req.DataType = dtEchoReq
 | 
						req.DataType = dtEchoReq
 | 
				
			||||||
	req.Data = data
 | 
						req.Data = data
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user