func (cch *cache) LookupPod(id string) (Pod, bool) {
	p, ok := cch.Pods[id]
	return p, ok
}
Look up a pod in the cache.
package cache
import (
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"sync"
	v1 "k8s.io/api/core/v1"
	cri "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
	"k8s.io/kubernetes/pkg/kubelet/cm/cpuset"
	"github.com/intel/cri-resource-manager/pkg/apis/resmgr"
	"github.com/intel/cri-resource-manager/pkg/cri/resource-manager/config"
	"github.com/intel/cri-resource-manager/pkg/cri/resource-manager/kubernetes"
	logger "github.com/intel/cri-resource-manager/pkg/log"
	"github.com/intel/cri-resource-manager/pkg/topology"
	idset "github.com/intel/goresctrl/pkg/utils"
)
const (
	CRI = "cri"
	RDT = "rdt"
	BlockIO = "blockio"
	Memory = "memory"
	PageMigration = "page-migration"
	TagAVX512 = "AVX512"
	RDTClassKey = "rdtclass" + "." + kubernetes.ResmgrKeyNamespace
	BlockIOClassKey = "blockioclass" + "." + kubernetes.ResmgrKeyNamespace
	ToptierLimitKey = "toptierlimit" + "." + kubernetes.ResmgrKeyNamespace
	RDTClassPodQoS = "/PodQos"
	ToptierLimitUnset int64 = -1
	TopologyHintsKey = "topologyhints" + "." + kubernetes.ResmgrKeyNamespace
)
var allControllers = []string{CRI, RDT, BlockIO, Memory}
type PodState int32
const (
	PodStateReady = PodState(int32(cri.PodSandboxState_SANDBOX_READY))
	PodStateNotReady = PodState(int32(cri.PodSandboxState_SANDBOX_NOTREADY))
	PodStateStale = PodState(int32(PodStateNotReady) + 1)
)
type PodResourceRequirements struct {
	InitContainers map[string]v1.ResourceRequirements `json:"initContainers"`
	Containers map[string]v1.ResourceRequirements `json:"containers"`
}
type PodStatus struct {
	CgroupParent string  
}
type Pod interface {
	resmgr.Evaluable
	fmt.Stringer
	GetInitContainers() []Container
	GetContainers() []Container
	GetContainer(string) (Container, bool)
	GetID() string
	GetUID() string
	GetName() string
	GetNamespace() string
	GetState() PodState
	GetQOSClass() v1.PodQOSClass
	GetLabelKeys() []string
	GetLabel(string) (string, bool)
	GetResmgrLabelKeys() []string
	GetResmgrLabel(string) (string, bool)
	GetAnnotationKeys() []string
	GetAnnotation(key string) (string, bool)
	GetAnnotationObject(key string, objPtr interface{},
		decode func([]byte, interface{}) error) (bool, error)
	GetResmgrAnnotationKeys() []string
	GetResmgrAnnotation(key string) (string, bool)
	GetResmgrAnnotationObject(key string, objPtr interface{},
		decode func([]byte, interface{}) error) (bool, error)
	GetEffectiveAnnotation(key, container string) (string, bool)
	GetCgroupParentDir() string
	GetPodResourceRequirements() PodResourceRequirements
	GetContainerAffinity(string) []*Affinity
	ScopeExpression() *resmgr.Expression
	GetProcesses(bool) ([]string, error)
	GetTasks(bool) ([]string, error)
}
type pod struct {
	cache        *cache             
	ID           string             
	UID          string             
	Name         string             
	Namespace    string             
	State        PodState           
	QOSClass     v1.PodQOSClass     
	Labels       map[string]string  
	Annotations  map[string]string  
	CgroupParent string             
	containers   map[string]string  
	Resources *PodResourceRequirements  
	Affinity  *podContainerAffinity     
}
type ContainerState int32
const (
	ContainerStateCreated = ContainerState(int32(cri.ContainerState_CONTAINER_CREATED))
	ContainerStateRunning = ContainerState(int32(cri.ContainerState_CONTAINER_RUNNING))
	ContainerStateExited = ContainerState(int32(cri.ContainerState_CONTAINER_EXITED))
	ContainerStateUnknown = ContainerState(int32(cri.ContainerState_CONTAINER_UNKNOWN))
	ContainerStateCreating = ContainerState(int32(ContainerStateUnknown) + 1)
	ContainerStateStale = ContainerState(int32(ContainerStateUnknown) + 2)
)
type Container interface {
	resmgr.Evaluable
	fmt.Stringer
	PrettyName() string
	GetPod() (Pod, bool)
	GetID() string
	GetPodID() string
	GetCacheID() string
	GetName() string
	GetNamespace() string
	UpdateState(ContainerState)
	GetState() ContainerState
	GetQOSClass() v1.PodQOSClass
	GetImage() string
	GetCommand() []string
	GetArgs() []string
	GetLabelKeys() []string
	GetLabel(string) (string, bool)
	GetLabels() map[string]string
	GetResmgrLabelKeys() []string
	GetResmgrLabel(string) (string, bool)
	GetAnnotationKeys() []string
	GetAnnotation(key string, objPtr interface{}) (string, bool)
	GetResmgrAnnotationKeys() []string
	GetResmgrAnnotation(key string, objPtr interface{}) (string, bool)
	GetEffectiveAnnotation(key string) (string, bool)
	GetAnnotations() map[string]string
	GetEnvKeys() []string
	GetEnv(string) (string, bool)
	GetMounts() []Mount
	GetMountByHost(string) *Mount
	GetMountByContainer(string) *Mount
	GetDevices() []Device
	GetDeviceByHost(string) *Device
	GetDeviceByContainer(string) *Device
	GetResourceRequirements() v1.ResourceRequirements
	GetLinuxResources() *cri.LinuxContainerResources
	SetCommand([]string)
	SetArgs([]string)
	SetLabel(string, string)
	DeleteLabel(string)
	SetAnnotation(string, string)
	DeleteAnnotation(string)
	SetEnv(string, string)
	UnsetEnv(string)
	InsertMount(*Mount)
	DeleteMount(string)
	InsertDevice(*Device)
	DeleteDevice(string)
	GetTopologyHints() topology.Hints
	GetCPUPeriod() int64
	GetCPUQuota() int64
	GetCPUShares() int64
	GetMemoryLimit() int64
	GetOomScoreAdj() int64
	GetCpusetCpus() string
	GetCpusetMems() string
	SetLinuxResources(*cri.LinuxContainerResources)
	SetCPUPeriod(int64)
	SetCPUQuota(int64)
	SetCPUShares(int64)
	SetMemoryLimit(int64)
	SetOomScoreAdj(int64)
	SetCpusetCpus(string)
	SetCpusetMems(string)
	GetAffinity() []*Affinity
	GetCgroupDir() string
	SetRDTClass(string)
	GetRDTClass() string
	SetBlockIOClass(string)
	GetBlockIOClass() string
	SetToptierLimit(int64)
	GetToptierLimit() int64
	SetPageMigration(*PageMigrate)
	GetPageMigration() *PageMigrate
	GetProcesses() ([]string, error)
	GetTasks() ([]string, error)
	SetCRIRequest(req interface{}) error
	GetCRIRequest() (interface{}, bool)
	ClearCRIRequest() (interface{}, bool)
	GetCRIEnvs() []*cri.KeyValue
	GetCRIMounts() []*cri.Mount
	GetCRIDevices() []*cri.Device
	GetPending() []string
	HasPending(string) bool
	ClearPending(string)
	GetTag(string) (string, bool)
	SetTag(string, string) (string, bool)
	DeleteTag(string) (string, bool)
}
type container struct {
	cache         *cache              
	ID            string              
	PodID         string              
	CacheID       string              
	Name          string              
	Namespace     string              
	State         ContainerState      
	Image         string              
	Command       []string            
	Args          []string            
	Labels        map[string]string   
	Annotations   map[string]string   
	Env           map[string]string   
	Mounts        map[string]*Mount   
	Devices       map[string]*Device  
	TopologyHints topology.Hints      
	Tags          map[string]string   
	Adjustment    string              
	Resources v1.ResourceRequirements       
	LinuxReq  *cri.LinuxContainerResources  
	req       *interface{}                  
	CgroupDir    string        
	RDTClass     string        
	BlockIOClass string        
	ToptierLimit int64         
	PageMigrate  *PageMigrate  
	pending map[string]struct{}  
	prettyName string  
}
type MountType int32
const (
	MountPrivate MountType = MountType(cri.MountPropagation_PROPAGATION_PRIVATE)
	MountHostToContainer MountType = MountType(cri.MountPropagation_PROPAGATION_HOST_TO_CONTAINER)
	MountBidirectional MountType = MountType(cri.MountPropagation_PROPAGATION_BIDIRECTIONAL)
)
type Mount struct {
	Container string
	Host string
	Readonly bool
	Relabel bool
	Propagation MountType
}
type Device struct {
	Container string
	Host string
	Permissions string
}
type PageMigrate struct {
	SourceNodes idset.IDSet  
	TargetNodes idset.IDSet  
}
func (pm *PageMigrate) Clone() *PageMigrate {
	if pm == nil {
		return nil
	}
	c := &PageMigrate{}
	if pm.SourceNodes != nil {
		c.SourceNodes = pm.SourceNodes.Clone()
	}
	if pm.TargetNodes != nil {
		c.TargetNodes = pm.TargetNodes.Clone()
	}
	return c
}
type Cachable interface {
	Set(value interface{})
	Get() interface{}
}
type Cache interface {
	InsertPod(id string, msg interface{}, status *PodStatus) Pod
	DeletePod(id string) Pod
	LookupPod(id string) (Pod, bool)
	InsertContainer(msg interface{}) (Container, error)
	UpdateContainerID(cacheID string, msg interface{}) (Container, error)
	DeleteContainer(id string) Container
	LookupContainer(id string) (Container, bool)
	LookupContainerByCgroup(path string) (Container, bool)
	GetPendingContainers() []Container
	GetPods() []Pod
	GetContainers() []Container
	GetContainerCacheIds() []string
	GetContainerIds() []string
	FilterScope(*resmgr.Expression) []Container
	EvaluateAffinity(*Affinity) map[string]int32
	AddImplicitAffinities(map[string]*ImplicitAffinity) error
	GetActivePolicy() string
	SetActivePolicy(string) error
	ResetActivePolicy() error
	SetPolicyEntry(string, interface{})
	GetPolicyEntry(string, interface{}) bool
	SetConfig(*config.RawConfig) error
	GetConfig() *config.RawConfig
	ResetConfig() error
	SetAdjustment(*config.Adjustment) (bool, map[string]error)
	Save() error
	RefreshPods(*cri.ListPodSandboxResponse, map[string]*PodStatus) ([]Pod, []Pod, []Container)
	RefreshContainers(*cri.ListContainersResponse) ([]Container, []Container)
	ContainerDirectory(string) string
	OpenFile(string, string, os.FileMode) (*os.File, error)
	WriteFile(string, string, os.FileMode, []byte) error
}
const (
	CacheVersion = "1"
)
type permissions struct {
	prefer os.FileMode  
	reject os.FileMode  
}
var (
	cacheDirPerm  = &permissions{prefer: 0710, reject: 0022}
	cacheFilePerm = &permissions{prefer: 0644, reject: 0022}
	dataDirPerm   = &permissions{prefer: 0755, reject: 0022}
	dataFilePerm  = &permissions{prefer: 0644, reject: 0022}
)
type cache struct {
	sync.Mutex    `json:"-"`  
	logger.Logger `json:"-"`  
	filePath      string      
	dataDir       string      
	Pods       map[string]*pod        
	Containers map[string]*container  
	NextID     uint64                 
	Cfg        *config.RawConfig       
	External   *config.Adjustment      
	PolicyName string                  
	policyData map[string]interface{}  
	PolicyJSON map[string]string       
	pending map[string]struct{}  
	implicit map[string]*ImplicitAffinity  
}
var _ Cache = &cache{}
type Options struct {
	CacheDir string
}
func NewCache(options Options) (Cache, error) {
	cch := &cache{
		filePath:   filepath.Join(options.CacheDir, "cache"),
		dataDir:    filepath.Join(options.CacheDir, "containers"),
		Logger:     logger.NewLogger("cache"),
		Pods:       make(map[string]*pod),
		Containers: make(map[string]*container),
		NextID:     1,
		policyData: make(map[string]interface{}),
		PolicyJSON: make(map[string]string),
		implicit:   make(map[string]*ImplicitAffinity),
	}
	if _, err := cch.checkPerm("cache", cch.filePath, false, cacheFilePerm); err != nil {
		return nil, cacheError("refusing to use existing cache file: %v", err)
	}
	if err := cch.mkdirAll("cache", options.CacheDir, cacheDirPerm); err != nil {
		return nil, err
	}
	if err := cch.mkdirAll("container", cch.dataDir, dataDirPerm); err != nil {
		return nil, err
	}
	if err := cch.Load(); err != nil {
		return nil, err
	}
	return cch, nil
}
func (cch *cache) GetActivePolicy() string {
	return cch.PolicyName
}
func (cch *cache) SetActivePolicy(policy string) error {
	cch.PolicyName = policy
	return cch.Save()
}
func (cch *cache) ResetActivePolicy() error {
	cch.Warn("clearing all data for active policy (%q) from cache...",
		cch.PolicyName)
	cch.PolicyName = ""
	cch.policyData = make(map[string]interface{})
	cch.PolicyJSON = make(map[string]string)
	return cch.Save()
}
func (cch *cache) SetConfig(cfg *config.RawConfig) error {
	old := cch.Cfg
	cch.Cfg = cfg
	if err := cch.Save(); err != nil {
		cch.Cfg = old
		return err
	}
	return nil
}
func (cch *cache) GetConfig() *config.RawConfig {
	return cch.Cfg
}
func (cch *cache) ResetConfig() error {
	old := cch.Cfg
	cch.Cfg = nil
	if err := cch.Save(); err != nil {
		cch.Cfg = old
		return err
	}
	return nil
}
func (cch *cache) SetAdjustment(external *config.Adjustment) (bool, map[string]error) {
	effective := map[*container]string{}
	errors := map[string]error{}
	for id, c := range cch.Containers {
		if id != c.GetCacheID() {
			continue
		}
		adjustments := cch.getApplicableAdjustments(external, c)
		if len(adjustments) == 0 {
			continue
		}
		if len(adjustments) > 1 {
			errors[c.GetID()] = cacheError("conflicting adjustments for %s: %s",
				c.PrettyName(), strings.Join(adjustments, ","))
			continue
		}
		adjust := external.Adjustments[adjustments[0]]
		if c.GetQOSClass() == v1.PodQOSBestEffort {
			if adjust.Resources != nil {
				errors[c.GetID()] = cacheError("%s: can't override resources for BestEffort %s",
					adjustments[0], c.PrettyName())
				continue
			}
		}
		effective[c] = adjustments[0]
	}
	if len(errors) > 0 {
		return false, errors
	}
	for id, c := range cch.Containers {
		if id != c.GetCacheID() {
			continue
		}
		uptodate := effective[c]
		previous := c.setEffectiveAdjustment(uptodate)
		effective[c] = previous
		if previous != uptodate {
			cch.Info("%s effective external adjustment changed from %q to %q",
				c.PrettyName(), previous, uptodate)
		}
		c.markPending(allControllers...)
	}
	if err := cch.Save(); err != nil {
		for id, c := range cch.Containers {
			if id != c.GetCacheID() {
				continue
			}
			c.setEffectiveAdjustment(effective[c])
		}
		return false, map[string]error{"cache": err}
	}
	cch.External = external
	return true, nil
}
func (cch *cache) getApplicableAdjustments(ext *config.Adjustment, c *container) []string {
	if ext == nil {
		return []string{}
	}
	applicable := []string{}
	for name, adjust := range ext.Adjustments {
		if adjust.IsContainerInScope(c) {
			applicable = append(applicable, name)
		}
	}
	return applicable
}
func (cch *cache) setEffectiveAdjustment(effective map[*container]string) {
	for id, c := range cch.Containers {
		if id != c.GetCacheID() {
			continue
		}
		uptodate := effective[c]
		previous := c.setEffectiveAdjustment(uptodate)
		if previous != uptodate {
			cch.Info("%s effective external adjustment changed from %q to %q",
				c.PrettyName(), previous, uptodate)
		}
		for _, ctrl := range allControllers {
			c.markPending(ctrl)
		}
	}
}
func (cch *cache) createCacheID(c *container) string {
	if pod, ok := c.cache.LookupPod(c.PodID); ok {
		uid := pod.GetUID()
		if uid != "" {
			return uid + ":" + c.Name
		}
	}
	cch.Warn("can't find unique id for pod %s, assigning local cache id", c.PodID)
	id := "cache:" + strconv.FormatUint(cch.NextID, 16)
	cch.NextID++
	return id
}
func (cch *cache) InsertPod(id string, msg interface{}, status *PodStatus) Pod {
	var err error
	p := &pod{cache: cch, ID: id}
	switch msg.(type) {
	case *cri.RunPodSandboxRequest:
		err = p.fromRunRequest(msg.(*cri.RunPodSandboxRequest))
	case *cri.PodSandbox:
		err = p.fromListResponse(msg.(*cri.PodSandbox), status)
	default:
		err = fmt.Errorf("cannot create pod from message %T", msg)
	}
	if err != nil {
		cch.Error("failed to insert pod %s: %v", id, err)
		return nil
	}
	cch.Pods[p.ID] = p
	cch.Save()
	return p
}
func (cch *cache) DeletePod(id string) Pod {
	p, ok := cch.Pods[id]
	if !ok {
		return nil
	}
	cch.Debug("removing pod %s (%s)", p.Name, p.ID)
	delete(cch.Pods, id)
	cch.Save()
	return p
}