summaryrefslogtreecommitdiff
path: root/rdiff-backup/rdiff_backup/backup.py
diff options
context:
space:
mode:
authorbescoto <bescoto@2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109>2002-12-25 21:15:31 +0000
committerbescoto <bescoto@2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109>2002-12-25 21:15:31 +0000
commit9725333f0f73e72af4834f623666376fc46894df (patch)
tree624a792c9f096caa7e5db8feb961b58e93a6dae1 /rdiff-backup/rdiff_backup/backup.py
parent77bf17a39b77dab86274ceb6e415c74ae6a2622f (diff)
downloadrdiff-backup-9725333f0f73e72af4834f623666376fc46894df.tar.gz
Renamed highlevel.py to backup.py
git-svn-id: http://svn.savannah.nongnu.org/svn/rdiff-backup/trunk@254 2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109
Diffstat (limited to 'rdiff-backup/rdiff_backup/backup.py')
-rw-r--r--rdiff-backup/rdiff_backup/backup.py198
1 files changed, 198 insertions, 0 deletions
diff --git a/rdiff-backup/rdiff_backup/backup.py b/rdiff-backup/rdiff_backup/backup.py
new file mode 100644
index 0000000..fc75099
--- /dev/null
+++ b/rdiff-backup/rdiff_backup/backup.py
@@ -0,0 +1,198 @@
+# Copyright 2002 Ben Escoto
+#
+# This file is part of rdiff-backup.
+#
+# rdiff-backup is free software; you can redistribute it and/or modify
+# under the terms of the GNU General Public License as published by the
+# Free Software Foundation; either version 2 of the License, or (at your
+# option) any later version.
+#
+# rdiff-backup is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with rdiff-backup; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+# USA
+
+"""High level functions for mirroring, mirror & inc, etc."""
+
+from __future__ import generators
+import Globals, MiscStats, metadata, rorpiter, TempFile, Hardlink, \
+ robust, increment, rpath, lazy, static, log, selection, Time, Rdiff
+
+
+def Mirror(src_rpath, dest_rpath):
+ """Turn dest_rpath into a copy of src_rpath"""
+ SourceS = src_rpath.conn.highlevel.HLSourceStruct
+ DestS = dest_rpath.conn.highlevel.HLDestinationStruct
+
+ source_rpiter = SourceS.get_source_select()
+ dest_sigiter = DestS.process_source_get_sigs(dest_rpath,
+ source_rpiter, 0)
+ source_diffiter = SourceS.get_diffs(src_rpath, dest_sigiter)
+ DestS.patch(dest_rpath, source_diffiter)
+
+def Mirror_and_increment(src_rpath, dest_rpath, inc_rpath):
+ """Mirror + put increments in tree based at inc_rpath"""
+ SourceS = src_rpath.conn.highlevel.HLSourceStruct
+ DestS = dest_rpath.conn.highlevel.HLDestinationStruct
+
+ source_rpiter = SourceS.get_source_select()
+ dest_sigiter = DestS.process_source_get_sigs(dest_rpath,
+ source_rpiter, 1)
+ source_diffiter = SourceS.get_diffs(src_rpath, dest_sigiter)
+ DestS.patch_and_increment(dest_rpath, source_diffiter, inc_rpath)
+
+
+class HLSourceStruct:
+ """Hold info used by HL on the source side"""
+ source_select = None # will be set to source Select iterator
+ def set_source_select(cls, rpath, tuplelist, *filelists):
+ """Initialize select object using tuplelist
+
+ Note that each list in filelists must each be passed as
+ separate arguments, so each is recognized as a file by the
+ connection. Otherwise we will get an error because a list
+ containing files can't be pickled.
+
+ """
+ sel = selection.Select(rpath)
+ sel.ParseArgs(tuplelist, filelists)
+ cls.source_select = sel.set_iter()
+
+ def get_source_select(cls):
+ """Return source select iterator, set by set_source_select"""
+ return cls.source_select
+
+ def get_diffs(cls, baserp, dest_sigiter):
+ """Return diffs of any files with signature in dest_sigiter"""
+ for dest_sig in dest_sigiter:
+ src_rp = baserp.new_index(dest_sig.index)
+ diff_rorp = src_rp.getRORPath()
+ if dest_sig.isflaglinked(): diff_rorp.flaglinked()
+ elif dest_sig.isreg() and src_rp.isreg():
+ diff_rorp.setfile(Rdiff.get_delta_sigrp(dest_sig, src_rp))
+ diff_rorp.set_attached_filetype('diff')
+ else:
+ diff_rorp.set_attached_filetype('snapshot')
+ if src_rp.isreg(): diff_rorp.setfile(src_rp.open("rb"))
+ yield diff_rorp
+
+static.MakeClass(HLSourceStruct)
+
+
+class HLDestinationStruct:
+ """Hold info used by HL on the destination side"""
+ def get_dest_select(cls, rpath, use_metadata = 1):
+ """Return destination select rorpath iterator
+
+ If metadata file doesn't exist, select all files on
+ destination except rdiff-backup-data directory.
+
+ """
+ if use_metadata:
+ metadata_iter = metadata.GetMetadata_at_time(Globals.rbdir,
+ Time.curtime)
+ if metadata_iter: return metadata_iter
+ log.Log("Warning: Metadata file not found.\n"
+ "Metadata will be read from filesystem.", 2)
+
+ sel = selection.Select(rpath)
+ sel.parse_rbdir_exclude()
+ return sel.set_iter()
+
+ def dest_iter_filter(cls, dest_iter):
+ """Destination rorps pass through this - record stats"""
+ for dest_rorp in dest_iter:
+ # XXX Statistics process
+ Hardlink.add_rorp(dest_rorp, source = 0)
+ yield dest_rorp
+
+ def src_iter_filter(cls, source_iter):
+ """Source rorps pass through this - record stats, write metadata"""
+ metadata.OpenMetadata()
+ for src_rorp in source_iter:
+ Hardlink.add_rorp(src_rorp, source = 1)
+ metadata.WriteMetadata(src_rorp)
+ #XXXX Statistics process
+ yield src_rorp
+ metadata.CloseMetadata()
+
+ def process_source_get_sigs(cls, baserp, source_iter, for_increment):
+ """Process the source rorpiter and return signatures of dest dir
+
+ Write all metadata to file, then return signatures of any
+ destination files that have changed. for_increment should be
+ true if we are mirror+incrementing, and false if we are just
+ mirroring.
+
+ """
+ source_iter = cls.src_iter_filter(source_iter)
+ dest_iter = cls.dest_iter_filter(cls.get_dest_select(baserp,
+ for_increment))
+ for index in rorpiter.get_dissimilar_indicies(source_iter, dest_iter):
+ dest_rp = baserp.new_index(index)
+ dest_sig = dest_rp.getRORPath()
+ if Globals.preserve_hardlinks and Hardlink.islinked(dest_rp):
+ dest_sig.flaglinked()
+ elif dest_rp.isreg():
+ dest_sig.setfile(Rdiff.get_signature(dest_rp))
+ yield dest_sig
+
+ def patch(cls, dest_rpath, source_diffiter):
+ """Patch dest_rpath with an rorpiter of diffs"""
+ ITR = rorpiter.IterTreeReducer(increment.PatchITRB, [dest_rpath])
+ for diff in rorpiter.FillInIter(source_diffiter, dest_rpath):
+ ITR(diff.index, diff)
+ ITR.Finish()
+ dest_rpath.setdata()
+
+ def patch_and_increment(cls, dest_rpath, source_diffiter, inc_rpath):
+ """Patch dest_rpath with rorpiter of diffs and write increments"""
+ ITR = rorpiter.IterTreeReducer(increment.IncrementITRB,
+ [dest_rpath, inc_rpath])
+ for diff in rorpiter.FillInIter(source_diffiter, dest_rpath):
+ ITR(diff.index, diff)
+ ITR.Finish()
+ dest_rpath.setdata()
+
+ def patch_increment_and_finalize(cls, dest_rpath, diffs, inc_rpath):
+ """Apply diffs, write increment if necessary, and finalize"""
+ collated = rorpiter.CollateIterators(diffs, cls.initial_dsiter2)
+ #finalizer, ITR = cls.get_finalizer(), cls.get_ITR(inc_rpath)
+ finalizer, ITR = None, cls.get_ITR(inc_rpath)
+ MiscStats.open_dir_stats_file()
+ dsrp, finished_dsrp = None, None
+
+ try:
+ for indexed_tuple in collated:
+ log.Log(lambda: "Processing %s" % str(indexed_tuple), 7)
+ diff_rorp, dsrp = indexed_tuple
+ index = indexed_tuple.index
+ if not dsrp: dsrp = cls.get_dsrp(dest_rpath, index)
+ if diff_rorp and diff_rorp.isplaceholder(): diff_rorp = None
+ ITR(index, diff_rorp, dsrp)
+ #finalizer(index, dsrp)
+ finished_dsrp = dsrp
+ ITR.Finish()
+ #finalizer.Finish()
+ except: cls.handle_last_error(finished_dsrp, finalizer, ITR)
+
+ if Globals.preserve_hardlinks: Hardlink.final_writedata()
+ MiscStats.close_dir_stats_file()
+ MiscStats.write_session_statistics(ITR.root_branch)
+
+ def handle_last_error(cls, dsrp, finalizer, ITR):
+ """If catch fatal error, try to checkpoint before exiting"""
+ log.Log.exception(1, 2)
+ robust.TracebackArchive.log()
+ #SaveState.checkpoint(ITR, finalizer, dsrp, 1)
+ #if Globals.preserve_hardlinks: Hardlink.final_checkpoint(Globals.rbdir)
+ #SaveState.touch_last_file_definitive()
+ raise
+
+static.MakeClass(HLDestinationStruct)
+