func (h *Handler) daemonSyncMaster() { var last *conn wait := make(chan int, 0) for exit := false; !exit; { var c *conn select { case <-wait: last = nil case <-h.signal: exit = true case c = <-h.master: } if last != nil { last.Close() <-wait } last = c if c != nil { go func() { defer func() { wait <- 0 }() defer c.Close() err := h.doSyncTo(c) log.InfoErrorf(err, "stop sync: %s", c.summ) }() h.syncto = c.nc.RemoteAddr().String() log.Infof("sync to %s", h.syncto) } else { h.syncto = "" log.Infof("sync to no one") } } }
func putSockConn(addr string, c *conn) { if c.err != nil { c.sock.Close() log.InfoErrorf(c.err, "close error connection %s : %s", addr, c.summ) } else { poolmap.Lock() pool := poolmap.m[addr] if pool == nil { pool = list.New() poolmap.m[addr] = pool } pool.PushFront(c) poolmap.Unlock() } }
func Serve(config *Config, bl *rpdb.Rpdb) error { h := &Handler{ config: config, master: make(chan *conn, 0), signal: make(chan int, 0), } defer func() { close(h.signal) }() l, err := net.Listen("tcp", config.Listen) if err != nil { return errors.Trace(err) } defer l.Close() if h.htable, err = redis.NewHandlerTable(h); err != nil { return err } else { go h.daemonSyncMaster() } log.Infof("open listen address '%s' and start service", l.Addr()) for { if nc, err := l.Accept(); err != nil { return errors.Trace(err) } else { h.counters.clientsAccepted.Add(1) go func() { h.counters.clients.Add(1) defer h.counters.clients.Sub(1) c := newConn(nc, bl, h.config.ConnTimeout) defer c.Close() log.Infof("new connection: %s", c.summ) if err := c.serve(h); err != nil { if errors.Equal(err, io.EOF) { log.Infof("connection lost: %s [io.EOF]", c.summ) } else { log.InfoErrorf(err, "connection lost: %s", c.summ) } } else { log.Infof("connection exit: %s", c.summ) } }() } } }