// TODO remove change subscribers, give Threadsafes directly to the things that need them. If they only set vars, and don't actually do work on change. func opsConfigManagerListen(opsConfig OpsConfigThreadsafe, opsConfigChannel <-chan handler.OpsConfig, dr chan<- http_server.DataRequest, toSession towrap.ITrafficOpsSession, toData todata.TODataThreadsafe, opsConfigChangeSubscribers []chan<- handler.OpsConfig, toChangeSubscribers []chan<- towrap.ITrafficOpsSession) { httpServer := http_server.Server{} errorCount := 0 // TODO make threadsafe and a pointer to errorcount in the main manager? for { select { case newOpsConfig := <-opsConfigChannel: var err error opsConfig.Set(newOpsConfig) listenAddress := ":80" // default if newOpsConfig.HttpListener != "" { listenAddress = newOpsConfig.HttpListener } handleErr := func(err error) { errorCount++ log.Errorf("OpsConfigManager: %v\n", err) } err = httpServer.Run(dr, listenAddress) if err != nil { handleErr(fmt.Errorf("MonitorConfigPoller: error creating HTTP server: %s\n", err)) continue } realToSession, err := to.Login(newOpsConfig.Url, newOpsConfig.Username, newOpsConfig.Password, newOpsConfig.Insecure) if err != nil { handleErr(fmt.Errorf("MonitorConfigPoller: error instantiating Session with traffic_ops: %s\n", err)) continue } toSession = towrap.NewTrafficOpsSessionThreadsafe(realToSession) if err := toData.Fetch(toSession, newOpsConfig.CdnName); err != nil { handleErr(fmt.Errorf("Error getting Traffic Ops data: %v\n", err)) continue } // These must be in a goroutine, because the monitorConfigPoller tick sends to a channel this select listens for. Thus, if we block on sends to the monitorConfigPoller, we have a livelock race condition. // More generically, we're using goroutines as an infinite chan buffer, to avoid potential livelocks for _, subscriber := range opsConfigChangeSubscribers { go func() { subscriber <- newOpsConfig // this is needed for cdnName }() } for _, subscriber := range toChangeSubscribers { go func() { subscriber <- toSession }() } } } }
// // Kicks off the pollers and handlers // func Start(opsConfigFile string, cfg config.Config, staticAppData StaticAppData) { toSession := towrap.ITrafficOpsSession(towrap.NewTrafficOpsSessionThreadsafe(nil)) counters := fetcher.Counters{ Success: gmx.NewCounter("fetchSuccess"), Fail: gmx.NewCounter("fetchFail"), Pending: gmx.NewGauge("fetchPending"), } // TODO investigate whether a unique client per cache to be polled is faster sharedClient := &http.Client{ Timeout: cfg.HttpTimeout, Transport: &http.Transport{TLSClientConfig: &tls.Config{InsecureSkipVerify: true}}, } localStates := peer.NewCRStatesThreadsafe() // this is the local state as discoverer by this traffic_monitor peerStates := peer.NewCRStatesPeersThreadsafe() // each peer's last state is saved in this map fetchCount := NewUintThreadsafe() // note this is the number of individual caches fetched from, not the number of times all the caches were polled. healthIteration := NewUintThreadsafe() errorCount := NewUintThreadsafe() toData := todata.NewThreadsafe() cacheHealthHandler := cache.NewHandler() cacheHealthPoller := poller.NewHTTP(cfg.CacheHealthPollingInterval, true, sharedClient, counters, cacheHealthHandler) cacheStatHandler := cache.NewPrecomputeHandler(toData, peerStates) // TODO figure out if this is necessary, with the CacheHealthPoller cacheStatPoller := poller.NewHTTP(cfg.CacheStatPollingInterval, false, sharedClient, counters, cacheStatHandler) monitorConfigPoller := poller.NewMonitorConfig(cfg.MonitorConfigPollingInterval) peerHandler := peer.NewHandler() peerPoller := poller.NewHTTP(cfg.PeerPollingInterval, false, sharedClient, counters, peerHandler) go monitorConfigPoller.Poll() go cacheHealthPoller.Poll() go cacheStatPoller.Poll() go peerPoller.Poll() cachesChanged := make(chan struct{}) monitorConfig := StartMonitorConfigManager( monitorConfigPoller.ConfigChannel, localStates, cacheStatPoller.ConfigChannel, cacheHealthPoller.ConfigChannel, peerPoller.ConfigChannel, cachesChanged, cfg, staticAppData, ) combinedStates := StartPeerManager( peerHandler.ResultChannel, localStates, peerStates, ) statHistory, _, lastKbpsStats, dsStats, unpolledCaches := StartStatHistoryManager( cacheStatHandler.ResultChannel, localStates, combinedStates, toData, cachesChanged, errorCount, cfg, monitorConfig, ) lastHealthDurations, events, localCacheStatus := StartHealthResultManager( cacheHealthHandler.ResultChannel, toData, localStates, statHistory, monitorConfig, peerStates, combinedStates, fetchCount, errorCount, cfg, ) StartOpsConfigManager( opsConfigFile, toSession, toData, []chan<- handler.OpsConfig{monitorConfigPoller.OpsConfigChannel}, []chan<- towrap.ITrafficOpsSession{monitorConfigPoller.SessionChannel}, localStates, peerStates, combinedStates, statHistory, lastKbpsStats, dsStats, events, staticAppData, cacheHealthPoller.Config.Interval, lastHealthDurations, fetchCount, healthIteration, errorCount, localCacheStatus, unpolledCaches, ) healthTickListener(cacheHealthPoller.TickChan, healthIteration) }