// Copyright 2019 The Prometheus Authors
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package procfs

import (
	"bufio"
	"errors"
	"os"
	"regexp"
	"strconv"
)

var (
	cpuLineRE  = regexp.MustCompile(`cpu(\d+) (\d+) (\d+) (\d+) (\d+) (\d+) (\d+) (\d+) (\d+) (\d+)`)
	procLineRE = regexp.MustCompile(`(\d+) (\d+) (\d+)`)
)

// Schedstat contains scheduler statistics from /proc/schedstat
//
// See
// https://www.kernel.org/doc/Documentation/scheduler/sched-stats.txt
// for a detailed description of what these numbers mean.
//
// Note the current kernel documentation claims some of the time units are in
// jiffies when they are actually in nanoseconds since 2.6.23 with the
// introduction of CFS. A fix to the documentation is pending. See
// https://lore.kernel.org/patchwork/project/lkml/list/?series=403473
type Schedstat struct {
	CPUs []*SchedstatCPU
}

// SchedstatCPU contains the values from one "cpu<N>" line.
type SchedstatCPU struct {
	CPUNum string

	RunningNanoseconds uint64
	WaitingNanoseconds uint64
	RunTimeslices      uint64
}

// ProcSchedstat contains the values from `/proc/<pid>/schedstat`.
type ProcSchedstat struct {
	RunningNanoseconds uint64
	WaitingNanoseconds uint64
	RunTimeslices      uint64
}

// Schedstat reads data from `/proc/schedstat`.
func (fs FS) Schedstat() (*Schedstat, error) {
	file, err := os.Open(fs.proc.Path("schedstat"))
	if err != nil {
		return nil, err
	}
	defer file.Close()

	stats := &Schedstat{}
	scanner := bufio.NewScanner(file)

	for scanner.Scan() {
		match := cpuLineRE.FindStringSubmatch(scanner.Text())
		if match != nil {
			cpu := &SchedstatCPU{}
			cpu.CPUNum = match[1]

			cpu.RunningNanoseconds, err = strconv.ParseUint(match[8], 10, 64)
			if err != nil {
				continue
			}

			cpu.WaitingNanoseconds, err = strconv.ParseUint(match[9], 10, 64)
			if err != nil {
				continue
			}

			cpu.RunTimeslices, err = strconv.ParseUint(match[10], 10, 64)
			if err != nil {
				continue
			}

			stats.CPUs = append(stats.CPUs, cpu)
		}
	}

	return stats, nil
}

func parseProcSchedstat(contents string) (ProcSchedstat, error) {
	var (
		stats ProcSchedstat
		err   error
	)
	match := procLineRE.FindStringSubmatch(contents)

	if match != nil {
		stats.RunningNanoseconds, err = strconv.ParseUint(match[1], 10, 64)
		if err != nil {
			return stats, err
		}

		stats.WaitingNanoseconds, err = strconv.ParseUint(match[2], 10, 64)
		if err != nil {
			return stats, err
		}

		stats.RunTimeslices, err = strconv.ParseUint(match[3], 10, 64)
		return stats, err
	}

	return stats, errors.New("could not parse schedstat")
}
