#!/usr/bin/python

#
# Copyright (c) 2016 Intel Corporation.
#
# 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.
#

# 2 possible algos: at each new timestamp, update run/queue/sleep time for all threads vs update
# only the right process. 2nd algo is still easy
# because we have duration of this state.
# this presents run, queued, sleep time of processes sorted by run time. REL time starts when
# process was created while ABS time if from beginning. Therefore elapsed time between start and
# process creation is added as sleep time

import os, sys, re
from collections import defaultdict
from operator import itemgetter
from optparse import OptionParser

class FilterTrace:
    def __init__(self):
        self.compiled_regexp = []
        self.pid_names = {}
        self.run_time = defaultdict(int) # total run-time per tid
        self.queued_time = defaultdict(int)
        self.sleep_time = defaultdict(int)
        self.ctxswitch_run_times0 = defaultdict(int)
        self.ctxswitch_run_times1 = defaultdict(int)
        self.timestamp_current = 0
        self.convert = 1.0 / 1000

        self.timestamp_start = 0 # must be >=
        self.timestamp_end = 0 # must be <=, but if > to last context switch, will go until
			       # Last timestamp only
        self.runqueue_threads_only = False # see options help

        REGEXP_GLOSSARY = [
            # backup rule
            ['^.*psel.*$', None],
            ['^(?P<timestamp>\d+)\s+(?P<cpu_id>\d+)\s+(?P<task_name>[\w \.#-_/]+):(?P<tid>-?\d+)' \
	     '\s+(?P<state>\w+)\s+(?P<duration>\d+).*$', self.callback_context_switch],
            ['^Last timestamp:\s*(?P<last_timestamp>\d+).*$', self.callback_end],
            ['^.*$', self.callback_no_rule]
        ]

        # Compile all regexp
        for regexp_string, regexp_rules in REGEXP_GLOSSARY:
            self.compiled_regexp.append([re.compile(regexp_string), regexp_rules])

    def filter_line(self, line):
        # Parse all regexps
        for regexp, regexp_rules in self.compiled_regexp:
            # Test if regexp matches
            res = regexp.search(line)
            # if regexp match
            if res:
               # Execute regexp_rules
               if regexp_rules:
                  regexp_rules(res, line)
               # Only one regexp per line
               break

    def callback_context_switch(self, res, line):
        timestamp_current = int(res.group('timestamp'))

        # end boundary
        if (timestamp_current >= self.timestamp_end):
            return

        duration = int(res.group('duration'))
	# wait to reach timestamp_start before processing
        if (timestamp_current < self.timestamp_start):
	    # thread will keep this state until start boundary so count this time
            if ((timestamp_current + duration) > self.timestamp_start):
		# remove time before start boundary
                duration = timestamp_current + duration - self.timestamp_start
                timestamp_current = self.timestamp_start
            else:
                return

        # if process goes beyond end, remove time after end
        if (duration > (self.timestamp_end - timestamp_current)):
            duration = self.timestamp_end - timestamp_current

        tid = int(res.group('tid'))
        if (res.group('state') == 'R'):
            self.run_time[tid] += duration
            if (int(res.group('cpu_id')) == 0):
                self.ctxswitch_run_times0[tid] += 1
            else:
                self.ctxswitch_run_times1[tid] += 1
        elif (res.group('state') == 'Q'):
            self.queued_time[tid] += duration
        elif ((res.group('state') == 'S') or (res.group('state') == 'X')):
            self.sleep_time[tid] += duration

        self.pid_names[tid] = res.group('task_name').rstrip(' ')


    def callback_no_rule(self, res, line):
        return

    def callback_end(self, res, line):
        max_sum = 0

        # we capture the process that started the first in order to get the sum for the % and set
	# START time at 0
        for tid in self.pid_names:
            sum = self.run_time[tid] + self.sleep_time[tid] + self.queued_time[tid]
            if sum > max_sum:
                max_sum = sum

        print("%-16s:%-10s %-10s %-10s %-10s %-10s %-10s %-7s" \
	      " %-7s %-7s %-7s %-7s %-7s %7s %7s %8s") % (
			"PID_NAME", "TID", "RUNNING", "SLEEPING", "QUEUED", "SUM", "START",
			"%R_ABS", "%S_ABS", "%Q_ABS", "%R_REL", "%S_REL", "%Q_REL", "N_RUN_0",
			"N_RUN_1", "N_RUN")

        items = self.run_time.items()
        items.sort(key = itemgetter(1), reverse=True) # inverse key and value to sort by value
        for tid, v in items:
             if ((not self.runqueue_threads_only) or
		 ((self.run_time[tid] != 0) or (self.queued_time[tid] != 0))):
                rel_sum = self.run_time[tid] + self.sleep_time[tid] + self.queued_time[tid]
                print("%-16s:%-10d %-10d %-10d %-10d %-10d %-10d %7.3f %7.3f %7.3f %7.3f" \
		      " %7.3f %7.3f %7d %7d %8d") % ( \
                         self.pid_names[tid],
                         tid,
                         self.run_time[tid],
                         self.sleep_time[tid],
                         self.queued_time[tid],
                         rel_sum, # script execution time - start time of process
                         max_sum - rel_sum, # start time of process
                         self.run_time[tid] * 100.0 / max_sum, # ABS R time
			 # ABS sleep time, start time is counted as sleep time
                         (self.sleep_time[tid] + max_sum - rel_sum) * 100.0 / max_sum,
                         self.queued_time[tid] * 100.0 / max_sum, # ABS Q time
                         self.run_time[tid] * 100.0 / rel_sum, # REL R time
                         self.sleep_time[tid] * 100.0 / rel_sum, # REL S time
                         self.queued_time[tid] * 100.0 / rel_sum, # REL Q time
                         self.ctxswitch_run_times0[tid],
                         self.ctxswitch_run_times1[tid],
                         self.ctxswitch_run_times0[tid] + self.ctxswitch_run_times1[tid]
                       )

global filterMaster
filterMaster = FilterTrace()

def Main(argv):
    usage = "Usage: %prog FILENAME [options]"
    parser = OptionParser(usage = usage)
    parser.add_option("-s", "--start", action="store", type="int", dest="start", default=0,
		      help="Start time of analysis in relative ms")
    parser.add_option("-e", "--end", action="store", type="int", dest="end", default=1000000000,
		      help="End time of analysis in relative ms")
    parser.add_option("-r", "--runqueue_threads_only", action="store_true",
		      dest="runqueue_threads_only", default=False,
		      help="Display only threads with some running time")
    (options, args) = parser.parse_args()
    filterMaster.timestamp_start = int(options.start / filterMaster.convert)
    filterMaster.timestamp_end = int(options.end / filterMaster.convert)
    filterMaster.runqueue_threads_only = options.runqueue_threads_only

    if len(args) != 1:
        print "Usage: type python <program>.py -h"
        return

    file = open(args[0], 'r')
    string = file.readline()

    # search for regexp
    while (string ):
        filterMaster.filter_line(string)
        string = file.readline()

if __name__=="__main__":
    Main(sys.argv[1:])
