func NewSchedulerLoadReader() (SchedulerLoadReader, error) { schedDebug, err := fs.Open("/proc/sched_debug") if err != nil { return nil, err } scanner := bufio.NewScanner(schedDebug) stateMachine := newSchedDebugReader() for scanner.Scan() { line := scanner.Text() err = stateMachine.ProcessLine(line) if err != nil { return nil, err } } if err = scanner.Err(); err != nil { return nil, err } return stateMachine.Load() }
// Given a container name, returns the parent and name of the container to be fed to libcontainer. func SplitName(containerName string) (string, string, error) { parent, id := path.Split(containerName) cgroupSelf, err := fs.Open("/proc/1/cgroup") if err != nil { return "", "", err } scanner := bufio.NewScanner(cgroupSelf) // Find how nested we are. Libcontainer takes container names relative to the current process. subsys := []string{"memory", "cpu"} nestedLevels := 0 for scanner.Scan() { line := scanner.Text() elems := strings.Split(line, ":") if len(elems) < 3 { continue } for _, s := range subsys { if elems[1] == s { if elems[2] == "/" { // We're running at root, no nesting. nestedLevels = 0 } else { // Count how deeply nested we are. nestedLevels = strings.Count(elems[2], "/") } break } } } if nestedLevels > 0 { // we are running inside a docker container upperLevel := strings.Repeat("../", nestedLevels) parent = filepath.Join(upperLevel, parent) } // Strip the last "/" if parent[len(parent)-1] == '/' { parent = parent[:len(parent)-1] } return parent, id, nil }
// Add() read the schedstat of pid, and add stat to the fields // in self parameters. This function is useful if one wants to read stats of // a group of processes. func (self *ProcessSchedStat) Add(pid int) error { if self == nil { return fmt.Errorf("nil stat") } path := fmt.Sprintf("/proc/%d/schedstat", pid) f, err := fs.Open(path) if err != nil { return err } defer f.Close() v, err := readUint64List(f) if err != nil { return err } if len(v) < 3 { return fmt.Errorf("only %v fields read from %v: %v", len(v), path, v) } self.Running += v[0] self.RunWait += v[1] self.NumTimeSlices += v[2] self.NumProcesses++ return nil }