func (m *resmgr) loadConfig() error {
	if opt.ForceConfig != "" {
		m.Info("using forced configuration %s...", opt.ForceConfig)
		if err := pkgcfg.SetConfigFromFile(opt.ForceConfig); err != nil {
			return resmgrError("failed to load forced configuration %s: %v",
				opt.ForceConfig, err)
		}
		return m.setupConfigSignal(opt.ForceConfigSignal)
	}
	m.Info("trying configuration from agent...")
	if conf, err := m.agent.GetConfig(1 * time.Second); err == nil {
		if err = pkgcfg.SetConfig(conf.Data); err == nil {
			m.conf = conf  
			return nil
		}
		m.Error("configuration from agent failed to apply: %v", err)
	}
	m.Info("trying last cached configuration...")
	if conf := m.cache.GetConfig(); conf != nil {
		err := pkgcfg.SetConfig(conf.Data)
		if err == nil {
			return nil
		}
		m.Error("failed to activate cached configuration: %v", err)
	}
	if opt.FallbackConfig != "" {
		m.Info("using fallback configuration %s...", opt.FallbackConfig)
		if err := pkgcfg.SetConfigFromFile(opt.FallbackConfig); err != nil {
			return resmgrError("failed to load fallback configuration %s: %v",
				opt.FallbackConfig, err)
		}
		return nil
	}
	m.Warn("no initial configuration found")
	return nil
}
loadConfig tries to pick and load (initial) configuration from a number of sources.
package resmgr
import (
	"golang.org/x/sys/unix"
	"os"
	"os/signal"
	"path/filepath"
	"strings"
	"sync"
	"time"
	pkgcfg "github.com/intel/cri-resource-manager/pkg/config"
	"github.com/intel/cri-resource-manager/pkg/cri/relay"
	"github.com/intel/cri-resource-manager/pkg/cri/resource-manager/agent"
	"github.com/intel/cri-resource-manager/pkg/cri/resource-manager/cache"
	config "github.com/intel/cri-resource-manager/pkg/cri/resource-manager/config"
	"github.com/intel/cri-resource-manager/pkg/cri/resource-manager/control"
	"github.com/intel/cri-resource-manager/pkg/cri/resource-manager/introspect"
	"github.com/intel/cri-resource-manager/pkg/cri/resource-manager/metrics"
	"github.com/intel/cri-resource-manager/pkg/cri/resource-manager/policy"
	"github.com/intel/cri-resource-manager/pkg/cri/resource-manager/visualizer"
	"github.com/intel/cri-resource-manager/pkg/instrumentation"
	logger "github.com/intel/cri-resource-manager/pkg/log"
	"github.com/intel/cri-resource-manager/pkg/utils"
)
type ResourceManager interface {
	Start() error
	Stop()
	SetConfig(*config.RawConfig) error
	SetAdjustment(*config.Adjustment) map[string]error
	SendEvent(event interface{}) error
	ResourceManagerTestAPI
}
type resmgr struct {
	logger.Logger
	sync.RWMutex
	relay        relay.Relay         
	cache        cache.Cache         
	policy       policy.Policy       
	policySwitch bool                
	configServer config.Server       
	control      control.Control     
	agent        agent.Interface     
	conf         *config.RawConfig   
	metrics      *metrics.Metrics    
	events       chan interface{}    
	stop         chan interface{}    
	signals      chan os.Signal      
	introspect   *introspect.Server  
}
func NewResourceManager() (ResourceManager, error) {
	m := &resmgr{Logger: logger.NewLogger("resource-manager")}
	if err := m.setupCache(); err != nil {
		return nil, err
	}
	switch {
	case opt.ResetPolicy && opt.ResetConfig:
		os.Exit(m.resetCachedPolicy() + m.resetCachedConfig())
	case opt.ResetPolicy:
		os.Exit(m.resetCachedPolicy())
	case opt.ResetConfig:
		os.Exit(m.resetCachedConfig())
	}
	if err := m.checkOpts(); err != nil {
		return nil, err
	}
	if err := m.setupAgentInterface(); err != nil {
		return nil, err
	}
	if err := m.loadConfig(); err != nil {
		return nil, err
	}
	if err := m.setupConfigServer(); err != nil {
		return nil, err
	}
	if err := m.setupPolicy(); err != nil {
		return nil, err
	}
	if err := m.setupRelay(); err != nil {
		return nil, err
	}
	if err := m.setupRequestProcessing(); err != nil {
		return nil, err
	}
	if err := m.setupEventProcessing(); err != nil {
		return nil, err
	}
	if err := m.setupControllers(); err != nil {
		return nil, err
	}
	if err := m.setupIntrospection(); err != nil {
		return nil, err
	}
	return m, nil
}
func (m *resmgr) Start() error {
	m.Info("starting...")
	m.Lock()
	defer m.Unlock()
	if err := m.startControllers(); err != nil {
		return err
	}
	if err := m.startRequestProcessing(); err != nil {
		return err
	}
	if err := m.startEventProcessing(); err != nil {
		return err
	}
	m.startIntrospection()
	if err := m.relay.Start(); err != nil {
		return resmgrError("failed to start CRI relay: %v", err)
	}
	if opt.ForceConfig == "" {
		if err := m.configServer.Start(opt.ConfigSocket); err != nil {
			return resmgrError("failed to start configuration server: %v", err)
		}
		if m.conf != nil {
			m.cache.SetConfig(m.conf)
			m.conf = nil
		}
	}
	m.Info("up and running")
	return nil
}
func (m *resmgr) Stop() {
	m.Info("shutting down...")
	m.Lock()
	defer m.Unlock()
	if m.signals != nil {
		close(m.signals)
		m.signals = nil
	}
	m.configServer.Stop()
	m.relay.Stop()
	m.stopIntrospection()
	m.stopEventProcessing()
}
func (m *resmgr) SetConfig(conf *config.RawConfig) error {
	m.Info("applying new configuration from agent...")
	return m.setConfig(conf)
}
func (m *resmgr) SetAdjustment(adjustment *config.Adjustment) map[string]error {
	m.Info("applying new adjustments from agent...")
	m.Lock()
	defer m.Unlock()
	return m.setAdjustment(adjustment)
}
func (m *resmgr) setConfigFromFile(path string) error {
	m.Info("applying new configuration from file %s...", path)
	return m.setConfig(path)
}
func (m *resmgr) setAdjustment(adjustments *config.Adjustment) map[string]error {
	m.Info("applying new external adjustments from agent...")
	rebalance, errors := m.cache.SetAdjustment(adjustments)
	if rebalance {
		m.rebalance("setAdjustment")
	}
	return errors
}
func (m *resmgr) resetCachedPolicy() int {
	m.Info("resetting active policy stored in cache...")
	defer logger.Flush()
	if utils.ServerActiveAt(opt.RelaySocket) {
		m.Error("refusing to reset, looks like an instance of %q is active at socket %q...",
			filepath.Base(os.Args[0]), opt.RelaySocket)
		return 1
	}
	if err := m.cache.ResetActivePolicy(); err != nil {
		m.Error("failed to reset active policy: %v", err)
		return 1
	}
	return 0
}
func (m *resmgr) resetCachedConfig() int {
	m.Info("resetting cached configuration...")
	defer logger.Flush()
	if utils.ServerActiveAt(opt.RelaySocket) {
		m.Error("refusing to reset, looks like an instance of %q is active at socket %q...",
			filepath.Base(os.Args[0]), opt.RelaySocket)
		return 1
	}
	if err := m.cache.ResetConfig(); err != nil {
		m.Error("failed to reset cached configuration: %v", err)
		return 1
	}
	return 0
}
func (m *resmgr) setupCache() error {
	var err error
	options := cache.Options{CacheDir: opt.RelayDir}
	if m.cache, err = cache.NewCache(options); err != nil {
		return resmgrError("failed to create cache: %v", err)
	}
	return nil
}
func (m *resmgr) setupAgentInterface() error {
	var err error
	if m.agent, err = agent.NewAgentInterface(opt.AgentSocket); err != nil {
		return err
	}
	return nil
}
func (m *resmgr) setupConfigServer() error {
	var err error
	if m.configServer, err = config.NewConfigServer(m.SetConfig, m.SetAdjustment); err != nil {
		return resmgrError("failed to create configuration notification server: %v", err)
	}
	return nil
}
func (m *resmgr) checkOpts() error {
	if opt.ForceConfig != "" && opt.FallbackConfig != "" {
		return resmgrError("both fallback (%s) and forced (%s) configurations given",
			opt.FallbackConfig, opt.ForceConfig)
	}
	return nil
}