/*
 *
 * Copyright 2018 gRPC 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 syscall provides functionalities that grpc uses to get low-level operating system
// stats/info.
package syscall

import (
	"fmt"
	"net"
	"syscall"
	"time"

	"golang.org/x/sys/unix"
	"google.golang.org/grpc/grpclog"
)

var logger = grpclog.Component("core")

// GetCPUTime returns the how much CPU time has passed since the start of this process.
func GetCPUTime() int64 {
	var ts unix.Timespec
	if err := unix.ClockGettime(unix.CLOCK_PROCESS_CPUTIME_ID, &ts); err != nil {
		logger.Fatal(err)
	}
	return ts.Nano()
}

// Rusage is an alias for syscall.Rusage under linux environment.
type Rusage = syscall.Rusage

// GetRusage returns the resource usage of current process.
func GetRusage() *Rusage {
	rusage := new(Rusage)
	syscall.Getrusage(syscall.RUSAGE_SELF, rusage)
	return rusage
}

// CPUTimeDiff returns the differences of user CPU time and system CPU time used
// between two Rusage structs.
func CPUTimeDiff(first *Rusage, latest *Rusage) (float64, float64) {
	var (
		utimeDiffs  = latest.Utime.Sec - first.Utime.Sec
		utimeDiffus = latest.Utime.Usec - first.Utime.Usec
		stimeDiffs  = latest.Stime.Sec - first.Stime.Sec
		stimeDiffus = latest.Stime.Usec - first.Stime.Usec
	)

	uTimeElapsed := float64(utimeDiffs) + float64(utimeDiffus)*1.0e-6
	sTimeElapsed := float64(stimeDiffs) + float64(stimeDiffus)*1.0e-6

	return uTimeElapsed, sTimeElapsed
}

// SetTCPUserTimeout sets the TCP user timeout on a connection's socket
func SetTCPUserTimeout(conn net.Conn, timeout time.Duration) error {
	tcpconn, ok := conn.(*net.TCPConn)
	if !ok {
		// not a TCP connection. exit early
		return nil
	}
	rawConn, err := tcpconn.SyscallConn()
	if err != nil {
		return fmt.Errorf("error getting raw connection: %v", err)
	}
	err = rawConn.Control(func(fd uintptr) {
		err = syscall.SetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_USER_TIMEOUT, int(timeout/time.Millisecond))
	})
	if err != nil {
		return fmt.Errorf("error setting option on socket: %v", err)
	}

	return nil
}

// GetTCPUserTimeout gets the TCP user timeout on a connection's socket
func GetTCPUserTimeout(conn net.Conn) (opt int, err error) {
	tcpconn, ok := conn.(*net.TCPConn)
	if !ok {
		err = fmt.Errorf("conn is not *net.TCPConn. got %T", conn)
		return
	}
	rawConn, err := tcpconn.SyscallConn()
	if err != nil {
		err = fmt.Errorf("error getting raw connection: %v", err)
		return
	}
	err = rawConn.Control(func(fd uintptr) {
		opt, err = syscall.GetsockoptInt(int(fd), syscall.IPPROTO_TCP, unix.TCP_USER_TIMEOUT)
	})
	if err != nil {
		err = fmt.Errorf("error getting option on socket: %v", err)
		return
	}

	return
}
