#!/usr/bin/env python3
#################################################
# Copyright (C), 2020-2025, KylinSoft Co., Ltd.
# File name: vmsize_tracer_main.py
# Author: liuyang01@kylinos.cn
# Version: 3.0
# Description: Main user-space entry point for the virtual memory size tracing and leakage detection tool.
#              This program monitors resident set size (RSS) and virtual memory size (VmSize) of specified
#              processes or system services over a configurable time window. It detects abnormal memory growth
#              that may indicate memory leaks by comparing initial and final memory snapshots.
#
#              The tool supports three operational modes:
#              - Service status monitoring (-c): Tracks predefined or user-specified services.
#              - Lightning detection (-C): Identifies top memory-growing processes in real time.
#              - Single process tracking (-p): Monitors a specific PID for detailed analysis.
#
#              Output can be formatted as human-readable text or structured JSON, and directed to stdout
#              or a specified file.
# Date: 2026-01-14
# Others: none
# Function List:
#   - main: Entry function that parses command-line arguments, dispatches to detection routines,
#           and manages output stream lifecycle.
#################################################
import sys, os, getopt
from vmsize_tracer_utils import vmsize_tracer_usage, status_detect, lightning_detect, specified_process_detect

add_service = ""
skip_service = ""
detect_time = 5*60
task_count = 5

def main():
    global detect_time, task_count, skip_service, add_service
    try:
        opts, args = getopt.getopt (sys.argv[1:], "hca:Ct:n:k:p:jo:", ["help"])
    except getopt.GetoptError as err:
        print (err)
        vmsize_tracer_usage ()
        sys.exit(1)

    lightning_detection = 0
    status_detection = 0
    target_pid = None
    json_mode = False
    output_file = None

    for optname, optvalue in opts:
        if optname in ('-h', '--help'):
            vmsize_tracer_usage ()
            sys.exit (0)
        if optname in ('-c'):
            status_detection = 1
        if optname in ('-C'):
            lightning_detection = 1
        if optname in ('-t'):
            if optvalue:
                detect_time = int (optvalue)
            else:
                vmsize_tracer_usage ()
                sys.exit ()
        if optname in ('-n'):
            if optvalue:
                task_count = int (optvalue)
            else:
                vmsize_tracer_usage ()
                sys.exit ()
        if optname in ('-k'):
            if optvalue:
                skip_service = optvalue
            else:
                vmsize_tracer_usage ()
                sys.exit ()
        if optname in ('-a'):
            if optvalue:
                add_service = optvalue
            else:
                vmsize_tracer_usage ()
                sys.exit ()
        if optname in ('-p'):
            if optvalue and optvalue.isdigit():
                target_pid = int (optvalue)
            else:
                vmsize_tracer_usage ()
                sys.exit ()
        if optname in ('-j'):
            json_mode = True
        if optname in ('-o'):
            output_file = optvalue

    if output_file:
        os.makedirs (os.path.dirname(output_file), exist_ok=True)
        output_stream = open (output_file, 'w')
    else:
        output_stream = sys.stdout

    try:
        if target_pid is not None:
            specified_process_detect (
                pid = target_pid,
                check_duration = detect_time,
                output_stream = output_stream,
                json_output = json_mode
            )
        elif status_detection:
            status_detect (
                check_duration = detect_time,
                extra_services = add_service,
                output_stream = output_stream,
                json_output = json_mode
            )
        elif lightning_detection:
            lightning_detect (
                skip_services = skip_service,
                check_interval = detect_time,
                top_count = task_count,
                output_stream = output_stream,
                json_output = json_mode
            )
        else:
            vmsize_tracer_usage ()
            sys.exit(1)

    finally:
        if output_file:
            output_stream.close ()

if __name__ == '__main__':
    main()
