56    """The routine that kicks off processing a ref file 
   59    filename The full path to the file to process 
   63        - A list of objects whose lifetimes were completed 
   64            (i.e., finished objects) 
   65        - A list of objects referenced after destruction 
   66            (i.e., invalid objects) 
   67        - A list of objects whose lifetimes were not completed 
   68            (i.e., leaked objects) 
   69        - A list of objects whose lifetimes are skewed 
   70            (i.e., Object history starting with an unusual ref count) 
   78    filename = options.filepath
 
   80    with open(filename, 
'r') 
as ref_file:
 
   87            obj = parsed_line[
'addr']
 
   89            if obj 
not in current_objects:
 
   90                current_objects[obj] = {
'log': [], 
'curcount': 1}
 
   91                if 'constructor' in parsed_line[
'state']:
 
   94                elif 'invalid' in parsed_line[
'state']:
 
   96                    current_objects[obj][
'curcount'] = 0
 
   98                        invalid_objects.append((obj, current_objects[obj]))
 
   99                elif 'destructor' in parsed_line[
'state']:
 
  100                    current_objects[obj][
'curcount'] = 0
 
  102                        skewed_objects.append((obj, current_objects[obj]))
 
  104                    current_objects[obj][
'curcount'] = int(
 
  105                        parsed_line[
'state'])
 
  107                        skewed_objects.append((obj, current_objects[obj]))
 
  109                current_objects[obj][
'curcount'] += int(parsed_line[
'delta'])
 
  112            if 'constructor' in parsed_line[
'state']:
 
  113                parsed_line[
'state'] = 
'**constructor**' 
  114            elif 'destructor' in parsed_line[
'state']:
 
  115                parsed_line[
'state'] = 
'**destructor**' 
  117            current_objects[obj][
'log'].append(
 
  118                "[%s] %s:%s %s: %s %s - [%s]" % (
 
  119                    parsed_line[
'thread_id'],
 
  122                    parsed_line[
'function'],
 
  123                    parsed_line[
'delta'],
 
  125                    parsed_line[
'state']))
 
  131            if current_objects[obj][
'curcount'] <= 0:
 
  132                if current_objects[obj][
'curcount'] < 0:
 
  133                    current_objects[obj][
'log'].append(
 
  134                        "[%s] %s:%s %s: %s %s - [%s]" % (
 
  135                            parsed_line[
'thread_id'],
 
  138                            parsed_line[
'function'],
 
  140                            "Object abnormally finalized",
 
  141                            "**implied destructor**"))
 
  146                        invalid_objects.append((obj, current_objects[obj]))
 
  147                if not invalid 
and options.normal:
 
  148                    finished_objects.append((obj, current_objects[obj]))
 
  149                del current_objects[obj]
 
  152        for (key, lines) 
in current_objects.items():
 
  153            leaked_objects.append((key, lines))
 
  154    return (finished_objects, invalid_objects, leaked_objects, skewed_objects)
 
 
  176    """Main entry point for the script""" 
  183    parser = OptionParser()
 
  185    parser.add_option(
"-f", 
"--file", action=
"store", type=
"string",
 
  186                      dest=
"filepath", default=
"/var/log/asterisk/refs",
 
  187                      help=
"The full path to the refs file to process")
 
  188    parser.add_option(
"-i", 
"--suppress-invalid", action=
"store_false",
 
  189                      dest=
"invalid", default=
True,
 
  190                      help=
"If specified, don't output invalid object " 
  192    parser.add_option(
"-l", 
"--suppress-leaks", action=
"store_false",
 
  193                      dest=
"leaks", default=
True,
 
  194                      help=
"If specified, don't output leaked objects")
 
  195    parser.add_option(
"-n", 
"--suppress-normal", action=
"store_false",
 
  196                      dest=
"normal", default=
True,
 
  197                      help=
"If specified, don't output objects with a " 
  199    parser.add_option(
"-s", 
"--suppress-skewed", action=
"store_false",
 
  200                      dest=
"skewed", default=
True,
 
  201                      help=
"If specified, don't output objects with a " 
  204    (options, args) = parser.parse_args(argv)
 
  206    if not options.invalid 
and not options.leaks 
and not options.normal \
 
  207            and not options.skewed:
 
  208        print(
"All options disabled", file=sys.stderr)
 
  211    if not os.path.isfile(options.filepath):
 
  212        print(
"File not found: %s" % options.filepath, file=sys.stderr)
 
  221        if options.invalid 
and len(invalid_objects):
 
  225        if options.leaks 
and len(leaked_objects):
 
  229        if options.skewed 
and len(skewed_objects):
 
  236    except (KeyboardInterrupt, SystemExit, IOError):
 
  237        print(
"File processing cancelled", file=sys.stderr)