Esempio n. 1
0
func Dial(addr string) (*Client, os.Error) {
	c, err := net.Dial("tcp", "", addr)
	if err != nil {
		return nil, err
	}
	pr := proto.NewConn(c)
	go pr.ReadResponses()
	return &Client{pr: pr, lg: util.NewLogger(addr)}, nil
}
Esempio n. 2
0
// This is a little subtle. We want to follow redirects while still pipelining
// requests, and we want to allow as many requests as possible to succeed
// without retrying unnecessarily.
//
// In particular, reads never need to redirect, and writes must always go to
// the leader. So we want that read requests never retry, and write requests
// retry if and only if necessary. Here's how it works:
//
// In the proto.Conn, when we get a redirect response, we raise a flag noting
// the new address. This flag only goes up, never down. This flag effectively
// means the connection is deprecated. Any pending requests can go ahead, but
// new requests should use the new address.
//
// In the Client, when we notice that a redirect has occurred (i.e. the flag is
// set), we establish a new connection to the new address. Calls in the future
// will use the new connection. But we also allow the old connection to
// continue functioning as it was. Any writes on the old connection will retry,
// and then they are guaranteed to pick up the new connection. Any reads on the
// old connection will just succeed directly.
func (cl *Client) proto() (*proto.Conn, os.Error) {
	cl.lk.Lock()
	defer cl.lk.Unlock()

	if cl.pr.RedirectAddr != "" {
		conn, err := net.Dial("tcp", "", cl.pr.RedirectAddr)
		if err != nil {
			return nil, err
		}
		cl.lg = util.NewLogger(cl.pr.RedirectAddr)
		cl.pr = proto.NewConn(conn)
		go cl.pr.ReadResponses()
	}

	return cl.pr, nil
}
Esempio n. 3
0
func (s *Server) Serve(l net.Listener, cal chan int) os.Error {
	for {
		rw, err := l.Accept()
		if err != nil {
			log.Printf("%#v", err)
			if e, ok := err.(*net.OpError); ok && e.Error == os.EINVAL {
				return nil
			}
			return err
		}
		c := &conn{proto.NewConn(rw), rw, s, closed(cal)}
		go c.serve()
	}

	panic("unreachable")
}