summaryrefslogtreecommitdiff
path: root/rdiff-backup/rdiff_backup/lazy.py
diff options
context:
space:
mode:
authorben <ben@2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109>2002-06-15 20:03:46 +0000
committerben <ben@2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109>2002-06-15 20:03:46 +0000
commit127e5a48e7b64b5aa7c01b4ccfcc6852f31c2b20 (patch)
tree94a60eb3e0b5fdbe490b2d67e81a35b2fa04c0ed /rdiff-backup/rdiff_backup/lazy.py
parentd2943df4a4eb71162dfd3939e0c668a83d85ee4e (diff)
downloadrdiff-backup-127e5a48e7b64b5aa7c01b4ccfcc6852f31c2b20.tar.gz
Various CPU optimizations
git-svn-id: http://svn.savannah.nongnu.org/svn/rdiff-backup/trunk@126 2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109
Diffstat (limited to 'rdiff-backup/rdiff_backup/lazy.py')
-rw-r--r--rdiff-backup/rdiff_backup/lazy.py113
1 files changed, 60 insertions, 53 deletions
diff --git a/rdiff-backup/rdiff_backup/lazy.py b/rdiff-backup/rdiff_backup/lazy.py
index c7d1a52..425a9c4 100644
--- a/rdiff-backup/rdiff_backup/lazy.py
+++ b/rdiff-backup/rdiff_backup/lazy.py
@@ -196,9 +196,9 @@ class IterTreeReducer:
iterator nature of the connection between hosts and the temporal
order in which the files are processed.
- There are four stub functions below: start_process, end_process,
- branch_process, and check_for_errors. A class that subclasses
- this one will probably fill in these functions to do more.
+ There are three stub functions below: start_process, end_process,
+ and branch_process. A class that subclasses this one will
+ probably fill in these functions to do more.
It is important that this class be pickable, so keep that in mind
when subclassing (this is used to resume failed sessions).
@@ -207,26 +207,49 @@ class IterTreeReducer:
def __init__(self, *args):
"""ITR initializer"""
self.init_args = args
- self.index = None
- self.subinstance = None
+ self.base_index = self.index = None
+ self.subinstances = [self]
self.finished = None
- self.caught_exception, self.start_successful = None, None
+ self.caught_exception = None
- def intree(self, index):
- """Return true if index is still in current tree"""
- return self.base_index == index[:len(self.base_index)]
+ def finish_subinstances(self, index):
+ """Run Finish() on all subinstances index has passed
- def set_subinstance(self):
- """Return subinstance of same type as self"""
- self.subinstance = self.__class__(*self.init_args)
+ When we pass out of a subinstance's tree, delete it and
+ process it with the parent. The innermost subinstances will
+ be the last in the list. Return None if we are out of the
+ entire tree, and 1 otherwise.
- def process_w_subinstance(self, args):
- """Give object to subinstance, if necessary update branch_val"""
- if not self.subinstance: self.set_subinstance()
- if not self.subinstance(*args):
- self.branch_process(self.subinstance)
- self.set_subinstance()
- assert self.subinstance(*args)
+ """
+ subinstances = self.subinstances
+ while 1:
+ to_be_finished = subinstances[-1]
+ base_index = to_be_finished.base_index
+ if base_index != index[:len(base_index)]:
+ # out of the tree, finish with to_be_finished
+ to_be_finished.call_end_proc()
+ del subinstances[-1]
+ if not subinstances: return None
+ subinstances[-1].branch_process(to_be_finished)
+ else: return 1
+
+ def call_end_proc(self):
+ """Runs the end_process on self, checking for errors"""
+ if self.finished: self.caught_exception = 1
+ if self.caught_exception: self.log_pref_error(self.base_index)
+ Robust.check_common_error(self.on_error, self.end_process)
+ self.finished = 1
+
+ def add_subinstance(self):
+ """Return subinstance of same type as self, add to subinstances"""
+ subinst = self.__class__(*self.init_args)
+ self.subinstances.append(subinst)
+ return subinst
+
+ def process_w_subinstance(self, index, subinst, args):
+ """Run start_process on latest subinstance"""
+ Robust.check_common_error(self.on_error, subinst.start_process, args)
+ subinst.base_index = index
def start_process(self, *args):
"""Do some initial processing (stub)"""
@@ -238,31 +261,20 @@ class IterTreeReducer:
def branch_process(self, subinstance):
"""Process a branch right after it is finished (stub)"""
+ assert subinstance.finished
pass
- def check_for_errors(self, function, *args):
- """start/end_process is called by this function
-
- Usually it will distinguish between two types of errors. Some
- are serious and will be reraised, others are caught and simply
- invalidate the current instance by setting
- self.caught_exception.
-
- """
- try: return apply(function, args)
- except: raise
+ def on_error(self, exc, *args):
+ """This will be run on any exception in start/end-process"""
+ pass
def Finish(self):
"""Call at end of sequence to tie everything up"""
- if not self.start_successful or self.finished:
- self.caught_exception = 1
- if self.caught_exception: self.log_prev_error(self.index)
- else:
- if self.subinstance:
- self.subinstance.Finish()
- self.branch_process(self.subinstance)
- self.check_for_errors(self.end_process)
- self.finished = 1
+ while 1:
+ to_be_finished = self.subinstances.pop()
+ to_be_finished.call_end_proc()
+ if not self.subinstances: break
+ self.subinstances[-1].branch_process(to_be_finished)
def log_prev_error(self, index):
"""Call function if no pending exception"""
@@ -280,24 +292,22 @@ class IterTreeReducer:
"""
index = args[0]
- assert type(index) is types.TupleType, type(index)
-
- if self.index is None:
- self.check_for_errors(self.start_process, *args)
- self.start_successful = 1
- self.index = self.base_index = index
+ if self.base_index is None:
+ self.process_w_subinstance(index, self, args)
+ self.index = index
return 1
if index <= self.index:
Log("Warning: oldindex %s >= newindex %s" % (self.index, index), 2)
return 1
- if not self.intree(index):
- self.Finish()
- return None
-
+ if self.finish_subinstances(index) is None:
+ return None # We are no longer in the main tree
if self.caught_exception: self.log_prev_error(index)
- else: self.process_w_subinstance(args)
+ else:
+ subinst = self.add_subinstance()
+ self.process_w_subinstance(index, subinst, args)
+
self.index = index
return 1
@@ -313,7 +323,4 @@ class ErrorITR(IterTreeReducer):
else: filename = "."
Log("Error '%s' processing %s" % (exc, filename), 2)
- def check_for_errors(self, function, *args):
- """Catch some non-fatal errors"""
- return Robust.check_common_error(self.on_error, function, *args)