示例#1
0
文件: netch.go 项目: fedgrant/tonika
// Channel returns net.Conn or os.Error. It receives anything to mean close.
func Listen(addr string, fdlim *http.FDLimiter) (chan interface{}, os.Error) {
	l, err := net.Listen("tcp", addr)
	if err != nil {
		return nil, err
	}
	cc := make(chan interface{})
	go func() {
		for {
			_, sig := <-cc
			if sig || closed(cc) {
				l.Close()
				return
			}
			if fdlim == nil || fdlim.LockOrTimeout(10e9) == nil {
				c, err := l.Accept()
				if err != nil {
					if c != nil {
						c.Close()
					}
					if fdlim != nil {
						fdlim.Unlock()
					}
					l.Close()
					cc <- err
					return
				}
				if fdlim != nil {
					cc <- http.NewConnRunOnClose(c, func() { fdlim.Unlock() })
				} else {
					cc <- c
				}
			} else {
				log.Stderrf("accept, fd starvation\n")
			}
		} // for
	}()
	return cc, nil
}
示例#2
0
文件: conn.go 项目: fedgrant/tonika
func (y *Conn) Connect(addr string, fdlim *http.FDLimiter) (err os.Error) {
	var alrm <-chan int
	backoff := backoff.Backoff{
		Lo:      backoffLo,
		Hi:      backoffHi,
		Ratio:   backoffRatio,
		Current: backoffLo,
		Attempt: 0,
	}
	for {
		if err = y.setRegime(regimeConnect); err != nil {
			return err
		}
		if alrm != nil {
			<-alrm
			alrm = nil
		}
		var conn net.Conn
		if fdlim.LockOrTimeout(timeForFD) == nil {
			conn, err = net.Dial("tcp", "", addr)
			if err == nil {
				//fmt.Printf(term.FgGreen+"d·conn[%#p] —— connected\n"+term.Reset, y)
				if err := conn.(*net.TCPConn).SetKeepAlive(true); err != nil {
					//log.Stderrf("%#p d·conn —— cannot set tcp keepalive: %s", y, err)
					fmt.Fprintf(os.Stderr, "tonika: warn: cannot set tcp keepalive\n")
				}
				conn = http.NewConnRunOnClose(conn, func() { fdlim.Unlock() })
				if err = y.Attach(conn); err != nil {
					conn.Close()
				}
				return err
			}
			fdlim.Unlock()
		}
		alrm = alarm.Ignite(backoff.Inc())
	}
	panic("unreachable")
}