func (r *RPC) openNewClient() { ci, err := jsonrpc.Dial(r.network, r.dstServer, r.OnBrokenConnection) if err != nil { r.closeIfOpenNumZero(err) return } r.mu.Lock() defer r.mu.Unlock() if r.closed { ci.Close() return } }
// return a connection(from idle conn lists or newly created) for rpc use func (r *RPC) getConn() (nc *conn, err error) { fmt.Printf("myrpc.RPC.getConn start:r(%+v)\n", *r) defer func() { fmt.Printf("myrpc.RPC.getConn end:r(%+v),err(%+v)\n", *r, err) }() r.mu.Lock() if r.closed { r.mu.Unlock() return nil, errRPCClosed } if r.maxOpen > 0 && r.numOpen >= r.maxOpen && len(r.freeConn) == 0 { // wait a free conn req := make(chan connRequest, 1) r.connRequests = append(r.connRequests, req) r.mu.Unlock() ret := <-req return ret.rc, ret.err } for c := len(r.freeConn); c > 0; { // get one from freeConn list ci := r.freeConn[0] r.freeConn = r.freeConn[1:] fmt.Printf("myrpc.RPC.getConn get from r.freeConn:ci(%+v)\n", *ci) // check if ci is closed already if ci.isClosed() { ci.Close() // Todo:close conn in r.mu.Unlock sucks, but is right here r.numOpen-- c = len(r.freeConn) continue } ci.inUse = true r.mu.Unlock() return ci, nil } // create a new connection r.numOpen++ r.mu.Unlock() ci, err := jsonrpc.Dial(r.network, r.dstServer, r.OnBrokenConnection) if err != nil { r.mu.Lock() r.numOpen-- r.mu.Unlock() // new creation failed, close if qualified r.closeIfOpenNumZero(err) return nil, err } fmt.Printf("myrpc.RPC.getConn create a new connection:r(%p),*r(%+v)\n", r, *r) r.mu.Lock() rc := &conn{ r: r, ci: ci, } rc.inUse = true r.mu.Unlock() return rc, nil }