#!/usr/bin/env python
#
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you 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.
#
#

## See the usage() function for operating instructions. ##

import re
try:
  # Python >=2.6
  from functools import reduce
except ImportError:
  # Python <2.6
  pass
import sys
import operator

_re_trail = re.compile('\((?P<txn_body>[a-z_]*), (?P<filename>[a-z_\-./]*), (?P<lineno>[0-9]*), (?P<txn>0|1)\): (?P<ops>.*)')
_re_table_op = re.compile('\(([a-z]*), ([a-z]*)\)')

_separator = '------------------------------------------------------------\n'

def parse_trails_log(infile):
  trails = []
  lineno = 0
  for line in infile.readlines():
    m = _re_trail.match(line)

    lineno = lineno + 1

    if not m:
      sys.stderr.write('Invalid input, line %u:\n%s\n' % (lineno, line))
      sys.exit(1)

    txn = int(m.group('txn'))
    if not txn:
      ### We're not interested in trails that don't use txns at this point.
      continue

    txn_body = (m.group('txn_body'), m.group('filename'),
                int(m.group('lineno')))
    trail = _re_table_op.findall(m.group('ops'))
    trail.reverse()

    if not trail:
      sys.stderr.write('Warning!  Empty trail at line %u:\n%s' % (lineno, line))

    trails.append((txn_body, trail))

  return trails


def output_summary(trails, outfile):
  ops = []
  for (txn_body, trail) in trails:
    ops.append(len(trail))
  ops.sort()

  total_trails = len(ops)
  total_ops = reduce(operator.add, ops)
  max_ops = ops[-1]
  median_ops = ops[total_trails / 2]
  average_ops = float(total_ops) / total_trails

  outfile.write(_separator)
  outfile.write('Summary\n')
  outfile.write(_separator)
  outfile.write('Total number of trails: %10i\n' % total_trails)
  outfile.write('Total number of ops:    %10i\n' % total_ops)
  outfile.write('max ops/trail:          %10i\n' % max_ops)
  outfile.write('median ops/trail:       %10i\n' % median_ops)
  outfile.write('average ops/trail:      %10.2f\n' % average_ops)
  outfile.write('\n')


# custom compare function
def _freqtable_cmp(a_b, c_d):
  (a, b) = a_b
  (c, d) = c_d
  c = cmp(d, b)
  if not c:
    c = cmp(a, c)
  return c

def list_frequencies(list):
  """
  Given a list, return a list composed of (item, frequency)
  in sorted order
  """

  counter = {}
  for item in list:
    counter[item] = counter.get(item, 0) + 1

  frequencies = list(counter.items())
  frequencies.sort(_freqtable_cmp)

  return frequencies


def output_trail_length_frequencies(trails, outfile):
  ops = []
  for (txn_body, trail) in trails:
    ops.append(len(trail))

  total_trails = len(ops)
  frequencies = list_frequencies(ops)

  outfile.write(_separator)
  outfile.write('Trail length frequencies\n')
  outfile.write(_separator)
  outfile.write('ops/trail   frequency   percentage\n')
  for (r, f) in frequencies:
    p = float(f) * 100 / total_trails
    outfile.write('%4i         %6i       %5.2f\n' % (r, f, p))
  outfile.write('\n')


def output_trail(outfile, trail, column = 0):
  ### Output the trail itself, in its own column

  if len(trail) == 0:
    outfile.write('<empty>\n')
    return

  line = str(trail[0])
  for op in trail[1:]:
    op_str = str(op)
    if len(line) + len(op_str) > 75 - column:
      outfile.write('%s,\n' % line)
      outfile.write(''.join(' ' * column))
      line = op_str
    else:
      line = line + ', ' + op_str
  outfile.write('%s\n' % line)

  outfile.write('\n')


def output_trail_frequencies(trails, outfile):

  total_trails = len(trails)

  ttrails = []
  for (txn_body, trail) in trails:
    ttrails.append((txn_body, tuple(trail)))

  frequencies = list_frequencies(ttrails)

  outfile.write(_separator)
  outfile.write('Trail frequencies\n')
  outfile.write(_separator)
  outfile.write('frequency   percentage   ops/trail   trail\n')
  for (((txn_body, file, line), trail), f) in frequencies:
    p = float(f) * 100 / total_trails
    outfile.write('-- %s - %s:%u --\n' % (txn_body, file, line))
    outfile.write('%6i        %5.2f       %4i       ' % (f, p, len(trail)))
    output_trail(outfile, trail, 37)


def output_txn_body_frequencies(trails, outfile):
  bodies = []
  for (txn_body, trail) in trails:
    bodies.append(txn_body)

  total_trails = len(trails)
  frequencies = list_frequencies(bodies)

  outfile.write(_separator)
  outfile.write('txn_body frequencies\n')
  outfile.write(_separator)
  outfile.write('frequency   percentage   txn_body\n')
  for ((txn_body, file, line), f) in frequencies:
    p = float(f) * 100 / total_trails
    outfile.write('%6i        %5.2f       %s - %s:%u\n'
                  % (f, p, txn_body, file, line))


def usage(pgm):
  w = sys.stderr.write
  w("%s: a program for analyzing Subversion trail usage statistics.\n" % pgm)
  w("\n")
  w("Usage:\n")
  w("\n")
  w("   Compile Subversion with -DSVN_FS__TRAIL_DEBUG, which will cause it\n")
  w("   it to print trail statistics to stderr.  Save the stats to a file,\n")
  w("   invoke %s on the file, and ponder the output.\n" % pgm)
  w("\n")


if __name__ == '__main__':
  if len(sys.argv) > 2:
    sys.stderr.write("Error: too many arguments\n\n")
    usage(sys.argv[0])
    sys.exit(1)

  if len(sys.argv) == 1:
    infile = sys.stdin
  else:
    try:
      infile = open(sys.argv[1])
    except (IOError):
      sys.stderr.write("Error: unable to open '%s'\n\n" % sys.argv[1])
      usage(sys.argv[0])
      sys.exit(1)

  trails = parse_trails_log(infile)

  output_summary(trails, sys.stdout)
  output_trail_length_frequencies(trails, sys.stdout)
  output_trail_frequencies(trails, sys.stdout)
  output_txn_body_frequencies(trails, sys.stdout)
