#!/usr/bin/env python

# Search a GC log created with, e.g. -Xlog:gc*,gc+refine=debug
#
# Find Concurrent Refinement deactivation messages with an off
# threshold less than the current number of buffers.  If it is the
# first such after a GC pause, and there are Concurrent Refinement
# activation messages between that deactivation message and the next
# GC pause, then print the deactivation message.
#
# We're looking for sequences of the form:
#
# (1) unusual deactivation(s)
# (2) activation(s)
# (3) GC pause
#
# Note that sequences of the form:
#
# (1) unusual deactivation(s)
# (2) GC pause
#
# with no activations between (1) and (2) are allowed; that situation
# arises when a pending GC requests running concurrent refinement
# threads to yield to allow the GC to proceed.

import sys
import re

gc_boundary = '.*\[gc(,start)?\s*\]'
find_gc_boundary = re.compile(gc_boundary)

activate_pattern = '.*\[gc,refine\s*\] Activated'
find_activate = re.compile(activate_pattern)

deactivate_pattern = '.*\[gc,refine\s*\] Deactivated'
find_deactivate = re.compile(deactivate_pattern)

def extract_threshold(s):
    match = "threshold: "
    start = s.find(match) + len(match)
    end = s.find(",", start)
    return int(s[start : end])

def extract_current_value(s):
    match = "current: "
    start = s.find(match) + len(match)
    return int(s[start:])

def is_unusual(s):
    return extract_threshold(s) < extract_current_value(s)

if __name__ == "__main__":

    filename = sys.argv[1]

    pending_deactivation = None
    looking_for_activation = False

    with open(filename) as file:
        for line in file:
            if find_gc_boundary.match(line):
                pending_deactivation = None
                looking_for_activation = False
            elif looking_for_activation and find_activate.match(line):
                print pending_deactivation[:-1]
                looking_for_activation = False
            elif not pending_deactivation:
                if find_deactivate.match(line) and is_unusual(line):
                    pending_deactivation = line
                    looking_for_activation = True


            
