func (m *IntelRdtManager) GetPath() string {
	if m.Path == "" {
		m.Path, _ = GetIntelRdtPath(m.Id)
	}
	return m.Path
}
Returns Intel RDT path to save in a state file and to be able to
restore the object later
package intelrdt
import (
	"bufio"
	"fmt"
	"io/ioutil"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"sync"
	"github.com/opencontainers/runc/libcontainer/configs"
)
type Manager interface {
	Apply(pid int) error
	GetStats() (*Stats, error)
	Destroy() error
	GetPath() string
	Set(container *configs.Config) error
}
type IntelRdtManager struct {
	mu     sync.Mutex
	Config *configs.Config
	Id     string
	Path   string
}
const (
	IntelRdtTasks = "tasks"
)
var (
	intelRdtRoot     string
	intelRdtRootLock sync.Mutex
	isEnabled bool
)
type intelRdtData struct {
	root   string
	config *configs.Config
	pid    int
}
func init() {
	isFlagSet, err := parseCpuInfoFile("/proc/cpuinfo")
	if !isFlagSet || err != nil {
		isEnabled = false
		return
	}
	isEnabled = isIntelRdtMounted()
}
func findIntelRdtMountpointDir() (string, error) {
	f, err := os.Open("/proc/self/mountinfo")
	if err != nil {
		return "", err
	}
	defer f.Close()
	s := bufio.NewScanner(f)
	for s.Scan() {
		text := s.Text()
		fields := strings.Split(text, " ")
		index := strings.Index(text, " - ")
		postSeparatorFields := strings.Fields(text[index+3:])
		numPostFields := len(postSeparatorFields)
		if numPostFields == 0 {
			return "", fmt.Errorf("Found no fields post '-' in %q", text)
		}
		if postSeparatorFields[0] == "resctrl" {
			if numPostFields < 3 {
				return "", fmt.Errorf("Error found less than 3 fields post '-' in %q", text)
			}
			return fields[4], nil
		}
	}
	if err := s.Err(); err != nil {
		return "", err
	}
	return "", NewNotFoundError("Intel RDT")
}
func getIntelRdtRoot() (string, error) {
	intelRdtRootLock.Lock()
	defer intelRdtRootLock.Unlock()
	if intelRdtRoot != "" {
		return intelRdtRoot, nil
	}
	root, err := findIntelRdtMountpointDir()
	if err != nil {
		return "", err
	}
	if _, err := os.Stat(root); err != nil {
		return "", err
	}
	intelRdtRoot = root
	return intelRdtRoot, nil
}
func isIntelRdtMounted() bool {
	_, err := getIntelRdtRoot()
	if err != nil {
		return false
	}
	return true
}
func parseCpuInfoFile(path string) (bool, error) {
	f, err := os.Open(path)
	if err != nil {
		return false, err
	}
	defer f.Close()
	s := bufio.NewScanner(f)
	for s.Scan() {
		if err := s.Err(); err != nil {
			return false, err
		}
		text := s.Text()
		flags := strings.Split(text, " ")
		for _, flag := range flags {
			if flag == "cat_l3" {
				return true, nil
			}
		}
	}
	return false, nil
}
func parseUint(s string, base, bitSize int) (uint64, error) {
	value, err := strconv.ParseUint(s, base, bitSize)
	if err != nil {
		intValue, intErr := strconv.ParseInt(s, base, bitSize)
		if intErr == nil && intValue < 0 {
			return 0, nil
		} else if intErr != nil && intErr.(*strconv.NumError).Err == strconv.ErrRange && intValue < 0 {
			return 0, nil
		}
		return value, err
	}
	return value, nil
}
func getIntelRdtParamUint(path, file string) (uint64, error) {
	fileName := filepath.Join(path, file)
	contents, err := ioutil.ReadFile(fileName)
	if err != nil {
		return 0, err
	}
	res, err := parseUint(strings.TrimSpace(string(contents)), 10, 64)
	if err != nil {
		return res, fmt.Errorf("unable to parse %q as a uint from file %q", string(contents), fileName)
	}
	return res, nil
}
func getIntelRdtParamString(path, file string) (string, error) {
	contents, err := ioutil.ReadFile(filepath.Join(path, file))
	if err != nil {
		return "", err
	}
	return strings.TrimSpace(string(contents)), nil
}
func readTasksFile(dir string) ([]int, error) {
	f, err := os.Open(filepath.Join(dir, IntelRdtTasks))
	if err != nil {
		return nil, err
	}
	defer f.Close()
	var (
		s   = bufio.NewScanner(f)
		out = []int{}
	)
	for s.Scan() {
		if t := s.Text(); t != "" {
			pid, err := strconv.Atoi(t)
			if err != nil {
				return nil, err
			}
			out = append(out, pid)
		}
	}
	return out, nil
}
func writeFile(dir, file, data string) error {
	if dir == "" {
		return fmt.Errorf("no such directory for %s", file)
	}
	if err := ioutil.WriteFile(filepath.Join(dir, file), []byte(data+"\n"), 0700); err != nil {
		return fmt.Errorf("failed to write %v to %v: %v", data, file, err)
	}
	return nil
}
func getIntelRdtData(c *configs.Config, pid int) (*intelRdtData, error) {
	rootPath, err := getIntelRdtRoot()
	if err != nil {
		return nil, err
	}
	return &intelRdtData{
		root:   rootPath,
		config: c,
		pid:    pid,
	}, nil
}
func getL3CacheInfo() (*L3CacheInfo, error) {
	l3CacheInfo := &L3CacheInfo{}
	rootPath, err := getIntelRdtRoot()
	if err != nil {
		return l3CacheInfo, err
	}
	path := filepath.Join(rootPath, "info", "L3")
	cbmMask, err := getIntelRdtParamString(path, "cbm_mask")
	if err != nil {
		return l3CacheInfo, err
	}
	minCbmBits, err := getIntelRdtParamUint(path, "min_cbm_bits")
	if err != nil {
		return l3CacheInfo, err
	}
	numClosids, err := getIntelRdtParamUint(path, "num_closids")
	if err != nil {
		return l3CacheInfo, err
	}
	l3CacheInfo.CbmMask = cbmMask
	l3CacheInfo.MinCbmBits = minCbmBits
	l3CacheInfo.NumClosids = numClosids
	return l3CacheInfo, nil
}
func WriteIntelRdtTasks(dir string, pid int) error {
	if dir == "" {
		return fmt.Errorf("no such directory for %s", IntelRdtTasks)
	}
	if pid != -1 {
		if err := ioutil.WriteFile(filepath.Join(dir, IntelRdtTasks), []byte(strconv.Itoa(pid)), 0700); err != nil {
			return fmt.Errorf("failed to write %v to %v: %v", pid, IntelRdtTasks, err)
		}
	}
	return nil
}
func IsEnabled() bool {
	return isEnabled
}
func GetIntelRdtPath(id string) (string, error) {
	rootPath, err := getIntelRdtRoot()
	if err != nil {
		return "", err
	}
	path := filepath.Join(rootPath, id)
	return path, nil
}
func (m *IntelRdtManager) Apply(pid int) (err error) {
	if m.Config.IntelRdt == nil {
		return nil
	}
	d, err := getIntelRdtData(m.Config, pid)
	if err != nil && !IsNotFound(err) {
		return err
	}
	m.mu.Lock()
	defer m.mu.Unlock()
	path, err := d.join(m.Id)
	if err != nil {
		return err
	}
	m.Path = path
	return nil
}
func (m *IntelRdtManager) Destroy() error {
	m.mu.Lock()
	defer m.mu.Unlock()
	if err := os.RemoveAll(m.Path); err != nil {
		return err
	}
	m.Path = ""
	return nil
}