# SPDX-License-Identifier: GPL-2.0

"Record and report data access pattern in realtime"

import argparse
import os
import signal
import subprocess
import sys

import _damon
import _damon_args

def cleanup():
    if target_type == _damon_args.target_type_cmd and cmd_pipe.poll() == None:
        cmd_pipe.kill()

def sighandler(signum, frame):
    print('\nsignal %s received' % signum)
    cleanup()

def main(args):
    _damon.ensure_root_permission()

    global target_type
    global cmd_pipe

    signal.signal(signal.SIGINT, sighandler)
    signal.signal(signal.SIGTERM, sighandler)

    target = args.target
    target_fields = target.split()
    target_type = _damon_args.deduced_target_type(target)
    if target_type == None:
        print('invalid target \'%s\'' % target)
        exit(1)
    if target_type == _damon_args.target_type_explicit and target == 'paddr':
        pass
    elif target_type == _damon_args.target_type_cmd:
        cmd_pipe = subprocess.Popen(target, shell=True, executable='/bin/bash',
                stdout=subprocess.DEVNULL, stderr=subprocess.STDOUT)
        target = cmd_pipe.pid
    else:
        pid = int(target)

    bindir = os.path.dirname(sys.argv[0])
    damo = os.path.join(bindir, 'damo')

    record_cmd = 'timeout %s %s record \"%s\"' % (args.delay, damo, target)

    report_cmd = [damo]
    if args.report_type == 'heats':
        report_cmd += 'report heats --heatmap stdout --resol 10 80'.split()
    else:
        report_cmd += ['report', 'wss']

    nr_reports = 0
    while not args.count or nr_reports < args.count:
        if (target_type == _damon_args.target_type_cmd and
                cmd_pipe.poll() != None):
            break
        try:
            subprocess.check_output(record_cmd, shell=True,
                    stderr=subprocess.STDOUT, executable='/bin/bash')
        except subprocess.CalledProcessError as e:
            pass
        try:
            output = subprocess.check_output(report_cmd).decode()
            if args.report_type == 'heats':
                for line in output.strip().split('\n'):
                    if not line.startswith('#'):
                        print(line)
            else:
                print(output)
        except subprocess.CalledProcessError as e:
            pass
        nr_reports += 1

    cleanup()

def set_argparser(parser):
    parser.add_argument('target', type=str, metavar='<target>',
            help='monitoring target (command, pid or \'paddr\')')
    parser.add_argument('--report_type', type=str, choices=['heats', 'wss'],
            default='heats', help='report type')
    parser.add_argument('--delay', type=float, metavar='<seconds>', default=3,
            help='deplay between updates in seconds.')
    parser.add_argument('--count', type=int, metavar='<count>', default=0,
            help='number of updates.')
