refcounter Namespace Reference


Functions

def main
def parse_line
def print_objects
def process_file


Function Documentation

def refcounter::main (   argv = None  ) 

Main entry point for the script

Definition at line 168 of file refcounter.py.

00168                    :
00169     """Main entry point for the script"""
00170 
00171     ret_code = 0
00172 
00173     if argv is None:
00174         argv = sys.argv
00175 
00176     parser = OptionParser()
00177 
00178     parser.add_option("-f", "--file", action="store", type="string",
00179                       dest="filepath", default="/var/log/asterisk/refs",
00180                       help="The full path to the refs file to process")
00181     parser.add_option("-i", "--suppress-invalid", action="store_false",
00182                       dest="invalid", default=True,
00183                       help="If specified, don't output invalid object "
00184                            "references")
00185     parser.add_option("-l", "--suppress-leaks", action="store_false",
00186                       dest="leaks", default=True,
00187                       help="If specified, don't output leaked objects")
00188     parser.add_option("-n", "--suppress-normal", action="store_false",
00189                       dest="normal", default=True,
00190                       help="If specified, don't output objects with a "
00191                            "complete lifetime")
00192     parser.add_option("-s", "--suppress-skewed", action="store_false",
00193                       dest="skewed", default=True,
00194                       help="If specified, don't output objects with a "
00195                            "skewed lifetime")
00196 
00197     (options, args) = parser.parse_args(argv)
00198 
00199     if not options.invalid and not options.leaks and not options.normal \
00200             and not options.skewed:
00201         print >>sys.stderr, "All options disabled"
00202         return -1
00203 
00204     if not os.path.isfile(options.filepath):
00205         print >>sys.stderr, "File not found: %s" % options.filepath
00206         return -1
00207 
00208     try:
00209         (finished_objects,
00210          invalid_objects,
00211          leaked_objects,
00212          skewed_objects) = process_file(options)
00213 
00214         if options.invalid and len(invalid_objects):
00215             print_objects(invalid_objects, "Invalid Referenced")
00216             ret_code |= 4
00217 
00218         if options.leaks and len(leaked_objects):
00219             print_objects(leaked_objects, "Leaked")
00220             ret_code |= 1
00221 
00222         if options.skewed and len(skewed_objects):
00223             print_objects(skewed_objects, "Skewed")
00224             ret_code |= 2
00225 
00226         if options.normal:
00227             print_objects(finished_objects, "Finalized")
00228 
00229     except (KeyboardInterrupt, SystemExit, IOError):
00230         print >>sys.stderr, "File processing cancelled"
00231         return -1
00232 
00233     return ret_code
00234 
00235 
if __name__ == "__main__":

def refcounter::parse_line (   line  ) 

Parse out a line into its constituent parts.

Keyword Arguments:
line The line from a ref debug log to parse out

Returns:
A dictionary containing the options, or None

Definition at line 27 of file refcounter.py.

00027                     :
00028     """Parse out a line into its constituent parts.
00029 
00030     Keyword Arguments:
00031     line The line from a ref debug log to parse out
00032 
00033     Returns:
00034     A dictionary containing the options, or None
00035     """
00036     tokens = line.strip().split(',', 7)
00037     if len(tokens) < 8:
00038         print "ERROR: ref debug line '%s' contains fewer tokens than " \
00039               "expected: %d" % (line.strip(), len(tokens))
00040         return None
00041 
00042     processed_line = {'addr': tokens[0],
00043                       'delta': tokens[1],
00044                       'thread_id': tokens[2],
00045                       'file': tokens[3],
00046                       'line': tokens[4],
00047                       'function': tokens[5],
00048                       'state': tokens[6],
00049                       'tag': tokens[7],
00050                       }
00051     return processed_line
00052 
00053 
def process_file(options):

def refcounter::print_objects (   objects,
  prefix = "" 
)

Prints out the objects that were processed

Keyword Arguments:
objects A list of objects to print
prefix  A prefix to print that specifies something about
        this object

Definition at line 150 of file refcounter.py.

00150                                      :
00151     """Prints out the objects that were processed
00152 
00153     Keyword Arguments:
00154     objects A list of objects to print
00155     prefix  A prefix to print that specifies something about
00156             this object
00157     """
00158 
00159     print "======== %s Objects ========" % prefix
00160     print "\n"
00161     for obj in objects:
00162         print "==== %s Object %s history ====" % (prefix, obj[0])
00163         for line in obj[1]['log']:
00164             print line
00165         print "\n"
00166 
00167 
def main(argv=None):

def refcounter::process_file (   options  ) 

The routine that kicks off processing a ref file

Keyword Arguments:
filename The full path to the file to process

Returns:
A tuple containing:
    - A list of objects whose lifetimes were completed
        (i.e., finished objects)
    - A list of objects referenced after destruction
        (i.e., invalid objects)
    - A list of objects whose lifetimes were not completed
        (i.e., leaked objects)
    - A list of objects whose lifetimes are skewed
        (i.e., Object history starting with an unusual ref count)

Definition at line 54 of file refcounter.py.

00054                          :
00055     """The routine that kicks off processing a ref file
00056 
00057     Keyword Arguments:
00058     filename The full path to the file to process
00059 
00060     Returns:
00061     A tuple containing:
00062         - A list of objects whose lifetimes were completed
00063             (i.e., finished objects)
00064         - A list of objects referenced after destruction
00065             (i.e., invalid objects)
00066         - A list of objects whose lifetimes were not completed
00067             (i.e., leaked objects)
00068         - A list of objects whose lifetimes are skewed
00069             (i.e., Object history starting with an unusual ref count)
00070     """
00071 
00072     finished_objects = []
00073     invalid_objects = []
00074     leaked_objects = []
00075     skewed_objects = []
00076     current_objects = {}
00077     filename = options.filepath
00078 
00079     with open(filename, 'r') as ref_file:
00080         for line in ref_file:
00081             parsed_line = parse_line(line)
00082             if not parsed_line:
00083                 continue
00084 
00085             invalid = False
00086             obj = parsed_line['addr']
00087 
00088             if obj not in current_objects:
00089                 current_objects[obj] = {'log': [], 'curcount': 1}
00090                 if 'constructor' in parsed_line['state']:
00091                     # This is the normal expected case
00092                     pass
00093                 elif 'invalid' in parsed_line['state']:
00094                     invalid = True
00095                     current_objects[obj]['curcount'] = 0
00096                     if options.invalid:
00097                         invalid_objects.append((obj, current_objects[obj]))
00098                 elif 'destructor' in parsed_line['state']:
00099                     current_objects[obj]['curcount'] = 0
00100                     if options.skewed:
00101                         skewed_objects.append((obj, current_objects[obj]))
00102                 else:
00103                     current_objects[obj]['curcount'] = int(
00104                         parsed_line['state'])
00105                     if options.skewed:
00106                         skewed_objects.append((obj, current_objects[obj]))
00107             else:
00108                 current_objects[obj]['curcount'] += int(parsed_line['delta'])
00109 
00110             current_objects[obj]['log'].append(
00111                 "[%s] %s:%s %s: %s %s - [%s]" % (
00112                     parsed_line['thread_id'],
00113                     parsed_line['file'],
00114                     parsed_line['line'],
00115                     parsed_line['function'],
00116                     parsed_line['delta'],
00117                     parsed_line['tag'],
00118                     parsed_line['state']))
00119 
00120             # It is possible for curcount to go below zero if someone
00121             # unrefs an object by two or more when there aren't that
00122             # many refs remaining.  This condition abnormally finishes
00123             # the object.
00124             if current_objects[obj]['curcount'] <= 0:
00125                 if current_objects[obj]['curcount'] < 0:
00126                     current_objects[obj]['log'].append(
00127                         "[%s] %s:%s %s: %s %s - [%s]" % (
00128                             parsed_line['thread_id'],
00129                             parsed_line['file'],
00130                             parsed_line['line'],
00131                             parsed_line['function'],
00132                             "+0",
00133                             "Object abnormally finalized",
00134                             "**implied destructor**"))
00135                     # Highlight the abnormally finished object in the
00136                     # invalid section as well as reporting it in the normal
00137                     # finished section.
00138                     if options.invalid:
00139                         invalid_objects.append((obj, current_objects[obj]))
00140                 if not invalid and options.normal:
00141                     finished_objects.append((obj, current_objects[obj]))
00142                 del current_objects[obj]
00143 
00144     if options.leaks:
00145         for key, lines in current_objects.iteritems():
00146             leaked_objects.append((key, lines))
00147     return (finished_objects, invalid_objects, leaked_objects, skewed_objects)
00148 
00149 
def print_objects(objects, prefix=""):


Generated on Thu Apr 16 06:41:38 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6