func (z *ZkConn) ManageTree(node string, callbacks ...EventCallbacks) { if len(callbacks) == 0 { return } children, _, eventCh, err := z.Conn.ChildrenW(node) if err != nil { logger.Errorf("[zkconn %d] ChildrenW(%s): %s", z, node, err) return } for _, child := range children { childNode := path.Join(node, child) z.ManageNode(childNode, callbacks[0]) if len(callbacks) > 1 { go z.ManageTree(childNode, callbacks[1:]...) } } for { ev := <-eventCh if ev.State == zookeeper.STATE_CLOSED { // shutdown was called on ZkConn? return } if ev.State == zookeeper.STATE_EXPIRED_SESSION || ev.State == zookeeper.STATE_CONNECTING { logger.Printf("[zkconn %d] connection lost, stop watching %s", z, node) return } switch ev.Type { case zookeeper.EVENT_DELETED: logger.Printf("[zkconn %d] node deleted, stop watching %s", z, node) return case zookeeper.EVENT_CHILD: prev := children children, _, eventCh, err = z.Conn.ChildrenW(node) if err != nil { logger.Errorf("[zkconn %d] ChildrenW(%s): %s", z, node, err) return } for _, child := range ArrayDiff(children, prev) { childNode := path.Join(node, child) z.ManageNode(childNode, callbacks[0]) if len(callbacks) > 1 { go z.ManageTree(childNode, callbacks[1:]...) } } } } }
func (s *Server) CheckStatus(tout time.Duration) { r, _ := http.NewRequest("GET", "http://"+s.Address+"/healthz", nil) resErrCh := make(chan ResponseError) go s.RoundTrip(r, resErrCh) select { case resErr := <-resErrCh: if resErr.Error == nil { defer resErr.Response.Body.Close() //if status has changed then log if s.Status.ParseAndSet(resErr.Response) { logger.Printf("[server %s] status code changed to %d\n", s.Address, resErr.Response.StatusCode) } } else { //if status has changed then log if s.Status.Set(StatusCritical) { logger.Errorf("[server %s] status set to critical! : %s\n", s.Address, resErr.Error) } } case <-time.After(tout): s.Transport.CancelRequest(r) if s.Status.Set(StatusCritical) { logger.Errorf("[server %s] status set to critical due to timeout!\n", s.Address) } } }
func (z *ZkConn) dialExclusive() { z.Lock() for err := z.dial(); err != nil; { logger.Printf("[zkconn %p] z.dial(): %s", z, err) } z.Unlock() z.ResetCh <- true }
func (p *Pool) Handle(logRecord *logger.HAProxyLogRecord) { pTime := time.Now() if p.Dummy { logger.Printf("[pool %s] Dummy", p.Name) logRecord.Error(logger.BadGatewayMsg, http.StatusBadGateway) logRecord.Terminate("Pool: " + logger.BadGatewayMsg) return } p.Metrics.ConnectionStart() defer p.Metrics.ConnectionDone() server := p.Next() if server == nil { // reachable when all servers in pool report StatusMaintenance logger.Printf("[pool %s] no server", p.Name) logRecord.Error(logger.ServiceUnavailableMsg, http.StatusServiceUnavailable) logRecord.Terminate("Pool: " + logger.ServiceUnavailableMsg) return } logRecord.PoolUpdateRecord(p.Name, p.Metrics.GetActiveConnections(), p.Metrics.GetTotalConnections(), pTime) server.Handle(logRecord, p.Config.RequestTimeout) }
func (z *ZkConn) waitOnConnect() error { for { ev := <-z.eventCh logger.Printf("[zkconn %p] eventCh-> %d %s in waitOnConnect", z, ev.State, ev) switch ev.State { case zookeeper.STATE_CONNECTED: return nil case zookeeper.STATE_CONNECTING: continue default: return errors.New(ev.String()) } } }
func (z *ZkConn) monitorEventCh() { for { select { case ev := <-z.eventCh: logger.Printf("[zkconn %p] eventCh -> %d %s in monitorEventCh", z, ev.State, ev) lastEvent = ev if ev.State == zookeeper.STATE_EXPIRED_SESSION || ev.State == zookeeper.STATE_CONNECTING { z.dialExclusive() return } case <-z.killCh: return } } }
func (z *ZkConn) ManageNode(node string, callbacks EventCallbacks) error { content, _, eventCh, err := z.Conn.GetW(node) if err != nil { logger.Errorf("[zkconn %d] GetW(%s): %s", z, node, err) return err } callbacks.Created(node, content) go func() { for { ev := <-eventCh if ev.State == zookeeper.STATE_CLOSED { // shutdown was called on ZkConn? return } if ev.State == zookeeper.STATE_EXPIRED_SESSION || ev.State == zookeeper.STATE_CONNECTING { logger.Printf("[zkconn %d] connection lost, stop watching %s", z, node) return } switch ev.Type { case zookeeper.EVENT_DELETED: callbacks.Deleted(node) return case zookeeper.EVENT_CHANGED: content, _, eventCh, err = z.Conn.GetW(node) if err != nil { logger.Errorf("[zkconn %d] GetW(%s): %s", z, node, err) return } callbacks.Changed(node, content) } } }() return nil }
func (s *Server) Handle(logRecord *logger.HAProxyLogRecord, tout time.Duration) { sTime := time.Now() s.Metrics.RequestStart() defer s.Metrics.RequestDone() // X-Forwarded-For; we are a proxy. ip := strings.Split(logRecord.Request.RemoteAddr, ":")[0] logRecord.Request.Header.Add("X-Forwarded-For", ip) logRecord.ServerUpdateRecord(s.Address, s.Metrics.RequestsServiced, s.Metrics.Cost(), sTime) resErrCh := make(chan ResponseError) tstart := time.Now() go s.RoundTrip(logRecord.Request, resErrCh) tend := time.Now() logRecord.UpdateTr(tstart, tend) select { case resErr := <-resErrCh: if resErr.Error == nil { defer resErr.Response.Body.Close() logRecord.CopyHeaders(resErr.Response.Header) logRecord.WriteHeader(resErr.Response.StatusCode) err := logRecord.Copy(resErr.Response.Body) if err != nil { logger.Errorf("[server %s] failed attempting to copy response body: %s\n", s.Address, err) } else { logRecord.Log() } } else { logger.Errorf("[server %s] failed attempting the roundtrip: %s\n", s.Address, resErr.Error) logRecord.Error(logger.BadGatewayMsg, http.StatusBadGateway) logRecord.Terminate("Server: " + logger.BadGatewayMsg) } case <-time.After(tout): s.Transport.CancelRequest(logRecord.Request) logger.Printf("[server %s] round trip timed out!", s.Address) logRecord.Error(logger.GatewayTimeoutMsg, http.StatusGatewayTimeout) logRecord.Terminate("Server: " + logger.GatewayTimeoutMsg) } }