예제 #1
0
파일: pubsub_tcp.go 프로젝트: humortian/im
func tcpListen(bind string) {
	addr, err := net.ResolveTCPAddr("tcp", bind)
	if err != nil {
		log.Error("net.ResolveTCPAddr(\"tcp\"), %s) error(%v)", bind, err)
		panic(err)
	}
	l, err := net.ListenTCP("tcp", addr)
	if err != nil {
		log.Error("net.ListenTCP(\"tcp4\", \"%s\") error(%v)", bind, err)
		panic(err)
	}
	// free the listener resource
	defer func() {
		log.Info("tcp addr: \"%s\" close", bind)
		if err := l.Close(); err != nil {
			log.Error("listener.Close() error(%v)", err)
		}
	}()
	// init reader buffer instance
	rb := newtcpBufCache()
	for {
		log.Trace("start accept")
		conn, err := l.AcceptTCP()
		if err != nil {
			log.Error("listener.AcceptTCP() error(%v)", err)
			continue
		}
		if err = conn.SetKeepAlive(Conf.TCPKeepalive); err != nil {
			log.Error("conn.SetKeepAlive() error(%v)", err)
			conn.Close()
			continue
		}
		if err = conn.SetReadBuffer(Conf.RcvbufSize); err != nil {
			log.Error("conn.SetReadBuffer(%d) error(%v)", Conf.RcvbufSize, err)
			conn.Close()
			continue
		}
		if err = conn.SetWriteBuffer(Conf.SndbufSize); err != nil {
			log.Error("conn.SetWriteBuffer(%d) error(%v)", Conf.SndbufSize, err)
			conn.Close()
			continue
		}
		// first packet must sent by client in specified seconds
		if err = conn.SetReadDeadline(time.Now().Add(fitstPacketTimedoutSec)); err != nil {
			log.Error("conn.SetReadDeadLine() error(%v)", err)
			conn.Close()
			continue
		}
		rc := rb.Get()
		// one connection one routine
		go handleTCPConn(conn, rc)
		log.Trace("accept finished")
	}
}
예제 #2
0
파일: pool.go 프로젝트: humortian/im
// Get gets a connection. The application must close the returned connection.
// This method always returns a valid connection so that applications can defer
// error handling to the first use of the connection.
func (p *Pool) Get() (interface{}, error) {
	if p.closed {
		return nil, ErrPoolClosed
	}

	log.Trace("")
	if timeout := p.IdleTimeout; timeout > 0 {
		log.Trace("check expire conn start")
		go func() { //check expire connection
			for e := p.idle.Front(); e != nil; e = e.Next() {
				ic := e.Value.(idleConn)
				if ic.t.Add(timeout).After(time.Now()) {
					p.mu.Lock()
					p.idle.Remove(e)
					p.active -= 1
					p.mu.Unlock()
					p.Close(ic.c)
				}
			}
		}()
	}

	log.Trace("Get idle connection")
	// Get idle connection.
	for e := p.idle.Back(); e != nil; e = e.Prev() {

		p.mu.Lock()
		c := p.idle.Remove(e).(idleConn).c
		p.mu.Unlock()
		log.Trace("TestOnBorrow before return old thrift client.")
		if p.TestOnBorrow(c) != nil {
			p.active -= 1
			p.Close(c)
			continue
		} else {
			log.Trace("return old thrift client.")
			return c, nil
		}
	}

	log.Trace("exhaust if active count more than MaxActive")
	// No idle connection, pool exhaust if active count more than MaxActive
	if p.active >= p.MaxActive {
		p.mu.Unlock()
		return nil, ErrPoolExhausted
	}

	log.Trace("No idle connection, create new.")
	// No idle connection, create new.
	dial := p.Dial
	p.active += 1
	c, err := dial()
	if err != nil {
		p.mu.Lock()
		p.active -= 1
		p.mu.Unlock()
		c = nil
	}

	log.Trace("return new thrift client.")
	return c, err
}