diff options
Diffstat (limited to 'cvs2svn_lib/pass_manager.py')
-rw-r--r-- | cvs2svn_lib/pass_manager.py | 215 |
1 files changed, 0 insertions, 215 deletions
diff --git a/cvs2svn_lib/pass_manager.py b/cvs2svn_lib/pass_manager.py deleted file mode 100644 index 90fa2dc..0000000 --- a/cvs2svn_lib/pass_manager.py +++ /dev/null @@ -1,215 +0,0 @@ -# (Be in -*- python -*- mode.) -# -# ==================================================================== -# Copyright (c) 2000-2009 CollabNet. All rights reserved. -# -# This software is licensed as described in the file COPYING, which -# you should have received as part of this distribution. The terms -# are also available at http://subversion.tigris.org/license-1.html. -# If newer versions of this license are posted there, you may use a -# newer version instead, at your option. -# -# This software consists of voluntary contributions made by many -# individuals. For exact contribution history, see the revision -# history and logs, available at http://cvs2svn.tigris.org/. -# ==================================================================== - -"""This module contains tools to manage the passes of a conversion.""" - - -import time -import gc - -from cvs2svn_lib import config -from cvs2svn_lib.common import FatalError -from cvs2svn_lib.context import Ctx -from cvs2svn_lib.log import Log -from cvs2svn_lib.stats_keeper import StatsKeeper -from cvs2svn_lib.stats_keeper import read_stats_keeper -from cvs2svn_lib.artifact_manager import artifact_manager - - -class InvalidPassError(FatalError): - def __init__(self, msg): - FatalError.__init__( - self, msg + '\nUse --help-passes for more information.') - - -def check_for_garbage(): - # We've turned off the garbage collector because we shouldn't - # need it (we don't create circular dependencies) and because it - # is therefore a waste of time. So here we check for any - # unreachable objects and generate a debug-level warning if any - # occur: - gc.set_debug(gc.DEBUG_SAVEALL) - gc_count = gc.collect() - if gc_count: - if Log().is_on(Log.DEBUG): - Log().debug( - 'INTERNAL: %d unreachable object(s) were garbage collected:' - % (gc_count,) - ) - for g in gc.garbage: - Log().debug(' %s' % (g,)) - del gc.garbage[:] - - -class Pass(object): - """Base class for one step of the conversion.""" - - def __init__(self): - # By default, use the pass object's class name as the pass name: - self.name = self.__class__.__name__ - - def register_artifacts(self): - """Register artifacts (created and needed) in artifact_manager.""" - - raise NotImplementedError - - def _register_temp_file(self, basename): - """Helper method; for brevity only.""" - - artifact_manager.register_temp_file(basename, self) - - def _register_temp_file_needed(self, basename): - """Helper method; for brevity only.""" - - artifact_manager.register_temp_file_needed(basename, self) - - def run(self, run_options, stats_keeper): - """Carry out this step of the conversion. - - RUN_OPTIONS is an instance of RunOptions. STATS_KEEPER is an - instance of StatsKeeper.""" - - raise NotImplementedError - - -class PassManager: - """Manage a list of passes that can be executed separately or all at once. - - Passes are numbered starting with 1.""" - - def __init__(self, passes): - """Construct a PassManager with the specified PASSES. - - Internally, passes are numbered starting with 1. So PASSES[0] is - considered to be pass number 1.""" - - self.passes = passes - self.num_passes = len(self.passes) - - def get_pass_number(self, pass_name, default=None): - """Return the number of the pass indicated by PASS_NAME. - - PASS_NAME should be a string containing the name or number of a - pass. If a number, it should be in the range 1 <= value <= - self.num_passes. Return an integer in the same range. If - PASS_NAME is the empty string and DEFAULT is specified, return - DEFAULT. Raise InvalidPassError if PASS_NAME cannot be converted - into a valid pass number.""" - - if not pass_name and default is not None: - assert 1 <= default <= self.num_passes - return default - - try: - # Does pass_name look like an integer? - pass_number = int(pass_name) - if not 1 <= pass_number <= self.num_passes: - raise InvalidPassError( - 'illegal value (%d) for pass number. Must be 1 through %d or\n' - 'the name of a known pass.' - % (pass_number,self.num_passes,)) - return pass_number - except ValueError: - # Is pass_name the name of one of the passes? - for (i, the_pass) in enumerate(self.passes): - if the_pass.name == pass_name: - return i + 1 - raise InvalidPassError('Unknown pass name (%r).' % (pass_name,)) - - def run(self, run_options): - """Run the specified passes, one after another. - - RUN_OPTIONS will be passed to the Passes' run() methods. - RUN_OPTIONS.start_pass is the number of the first pass that should - be run. RUN_OPTIONS.end_pass is the number of the last pass that - should be run. It must be that 1 <= RUN_OPTIONS.start_pass <= - RUN_OPTIONS.end_pass <= self.num_passes.""" - - # Convert start_pass and end_pass into the indices of the passes - # to execute, using the Python index range convention (i.e., first - # pass executed and first pass *after* the ones that should be - # executed). - index_start = run_options.start_pass - 1 - index_end = run_options.end_pass - - # Inform the artifact manager when artifacts are created and used: - for (i, the_pass) in enumerate(self.passes): - the_pass.register_artifacts() - # Each pass creates a new version of the statistics file: - artifact_manager.register_temp_file( - config.STATISTICS_FILE % (i + 1,), the_pass - ) - if i != 0: - # Each pass subsequent to the first reads the statistics file - # from the preceding pass: - artifact_manager.register_temp_file_needed( - config.STATISTICS_FILE % (i + 1 - 1,), the_pass - ) - - # Tell the artifact manager about passes that are being skipped this run: - for the_pass in self.passes[0:index_start]: - artifact_manager.pass_skipped(the_pass) - - start_time = time.time() - for i in range(index_start, index_end): - the_pass = self.passes[i] - Log().quiet('----- pass %d (%s) -----' % (i + 1, the_pass.name,)) - artifact_manager.pass_started(the_pass) - - if i == 0: - stats_keeper = StatsKeeper() - else: - stats_keeper = read_stats_keeper( - artifact_manager.get_temp_file( - config.STATISTICS_FILE % (i + 1 - 1,) - ) - ) - - the_pass.run(run_options, stats_keeper) - end_time = time.time() - stats_keeper.log_duration_for_pass( - end_time - start_time, i + 1, the_pass.name - ) - Log().normal(stats_keeper.single_pass_timing(i + 1)) - stats_keeper.archive( - artifact_manager.get_temp_file(config.STATISTICS_FILE % (i + 1,)) - ) - start_time = end_time - Ctx().clean() - # Allow the artifact manager to clean up artifacts that are no - # longer needed: - artifact_manager.pass_done(the_pass, Ctx().skip_cleanup) - - check_for_garbage() - - # Tell the artifact manager about passes that are being deferred: - for the_pass in self.passes[index_end:]: - artifact_manager.pass_deferred(the_pass) - - Log().quiet(stats_keeper) - Log().normal(stats_keeper.timings()) - - # Consistency check: - artifact_manager.check_clean() - - def help_passes(self): - """Output (to sys.stdout) the indices and names of available passes.""" - - print 'PASSES:' - for (i, the_pass) in enumerate(self.passes): - print '%5d : %s' % (i + 1, the_pass.name,) - - |