From d618654b0c001294f122462adb73de8c13419882 Mon Sep 17 00:00:00 2001 From: bescoto Date: Sun, 5 Oct 2003 08:36:13 +0000 Subject: Added --list-increment-sizes code from 0.13.x git-svn-id: http://svn.savannah.nongnu.org/svn/rdiff-backup/branches/r0-12@466 2b77aa54-bcbc-44c9-a7ec-4f6cf2b41109 --- rdiff-backup/rdiff-backup.1 | 7 ++++ rdiff-backup/rdiff_backup/Main.py | 29 +++++++++----- rdiff-backup/rdiff_backup/Security.py | 5 ++- rdiff-backup/rdiff_backup/manage.py | 74 ++++++++++++++++++++++++++++++++++- rdiff-backup/testing/finaltest.py | 12 ++++++ 5 files changed, 115 insertions(+), 12 deletions(-) diff --git a/rdiff-backup/rdiff-backup.1 b/rdiff-backup/rdiff-backup.1 index b22dad7..9552f59 100644 --- a/rdiff-backup/rdiff-backup.1 +++ b/rdiff-backup/rdiff-backup.1 @@ -201,6 +201,13 @@ List the number and date of partial incremental backups contained in the specified destination directory. No backup or restore will take place if this option is given. .TP +.B --list-increment-sizes +List the total size of all the increment and mirror files by time. +This may be helpful in deciding how many increments to keep, and when +to --remove-older-than. Specifying a subdirectory is allowable; then +only the sizes of the mirror and increments pertaining to that +subdirectory will be listed. +.TP .B --no-change-dir-inc-perms Do not change the permissions of the directory increments to match the directories they represent. This option may be required on file diff --git a/rdiff-backup/rdiff_backup/Main.py b/rdiff-backup/rdiff_backup/Main.py index 1ccdbed..5eae9bf 100644 --- a/rdiff-backup/rdiff_backup/Main.py +++ b/rdiff-backup/rdiff_backup/Main.py @@ -52,15 +52,16 @@ def parse_cmdlineoptions(arglist): "include=", "include-filelist=", "include-filelist-stdin", "include-globbing-filelist=", "include-regexp=", "list-at-time=", "list-changed-since=", "list-increments", - "no-change-dir-inc-perms", "no-compare-inode", - "no-compression", "no-compression-regexp=", - "no-file-statistics", "no-hard-links", "null-separator", - "parsable-output", "print-statistics", "quoting-char=", - "remote-cmd=", "remote-schema=", "remove-older-than=", - "restore-as-of=", "restrict=", "restrict-read-only=", - "restrict-update-only=", "server", "ssh-no-compression", - "terminal-verbosity=", "test-server", "verbosity=", - "version", "windows-mode", "windows-restore"]) + "list-increment-sizes", "no-change-dir-inc-perms", + "no-compare-inode", "no-compression", + "no-compression-regexp=", "no-file-statistics", + "no-hard-links", "null-separator", "parsable-output", + "print-statistics", "quoting-char=", "remote-cmd=", + "remote-schema=", "remove-older-than=", "restore-as-of=", + "restrict=", "restrict-read-only=", "restrict-update-only=", + "server", "ssh-no-compression", "terminal-verbosity=", + "test-server", "verbosity=", "version", "windows-mode", + "windows-restore"]) except getopt.error, e: commandline_error("Bad commandline options: %s" % str(e)) @@ -105,6 +106,7 @@ def parse_cmdlineoptions(arglist): restore_timestr, action = arg, "list-changed-since" elif opt == "-l" or opt == "--list-increments": action = "list-increments" + elif opt == '--list-increment-sizes': action = 'list-increment-sizes' elif opt == "--no-change-dir-inc-perms": Globals.set("change_dir_inc_perms", 0) elif opt == "--no-compare-inode": Globals.set("compare_inode", 0) @@ -185,6 +187,7 @@ def set_action(): if l < 2 and (action == "backup" or action == "restore-as-of"): commandline_error("Two arguments are required (source, destination).") if l == 2 and (action == "list-increments" or + action == "list-increment-sizes" or action == "remove-older-than" or action == "list-at-time" or action == "list-changed-since" or @@ -223,6 +226,7 @@ def take_action(rps): elif action == "list-at-time": ListAtTime(rps[0]) elif action == "list-changed-since": ListChangedSince(rps[0]) elif action == "list-increments": ListIncrements(rps[0]) + elif action == "list-increment-sizes": ListIncrementSizes(rps[0]) elif action == "remove-older-than": RemoveOlderThan(rps[0]) elif action == "calculate-average": CalculateAverage(rps) elif action == "check-destination-dir": CheckDest(rps[0]) @@ -520,6 +524,13 @@ def ListIncrements(rp): else: print manage.describe_incs_human(incs, mirror_time, mirror_rp) +def ListIncrementSizes(rp): + """Print out a summary of the increments """ + mirror_root, index = restore_get_root(rp) + restore_check_backup_dir(mirror_root) + print manage.ListIncrementSizes(mirror_root, index) + + def CalculateAverage(rps): """Print out the average of the given statistics files""" statobjs = map(lambda rp: statistics.StatsObj().read_stats_from_rp(rp), diff --git a/rdiff-backup/rdiff_backup/Security.py b/rdiff-backup/rdiff_backup/Security.py index 25962ed..a8746e8 100644 --- a/rdiff-backup/rdiff_backup/Security.py +++ b/rdiff-backup/rdiff_backup/Security.py @@ -94,8 +94,9 @@ def set_security_level(action, cmdpairs): sec_level = "all" rdir = getpath(cp2) elif (action == "test-server" or action == "list-increments" or - action == "list-at-time" or action == "list-changed-since" - or action == "calculate-average" or action == "remove-older-than"): + action == "list-increment-sizes" or action == "list-at-time" + or action == "list-changed-since" or action == "calculate-average" + or action == "remove-older-than"): sec_level = "minimal" rdir = tempfile.gettempdir() else: assert 0, "Unknown action %s" % action diff --git a/rdiff-backup/rdiff_backup/manage.py b/rdiff-backup/rdiff_backup/manage.py index bb4259c..57f6535 100644 --- a/rdiff-backup/rdiff_backup/manage.py +++ b/rdiff-backup/rdiff_backup/manage.py @@ -21,7 +21,7 @@ from __future__ import generators from log import Log -import Globals, Time, static, manage +import Globals, Time, static, statistics, restore, selection class ManageException(Exception): pass @@ -128,3 +128,75 @@ class IncObj: s = ["Increment file %s" % self.incrp.path, "Date: %s" % self.pretty_time()] return "\n".join(s) + + +def ListIncrementSizes(mirror_root, index): + """Return string summarizing the size of all the increments""" + stat_obj = statistics.StatsObj() # used for byte summary string + def get_total(rp_iter): + """Return the total size of everything in rp_iter""" + total = 0 + for rp in rp_iter: total += rp.getsize() + return total + + def get_time_dict(inc_iter): + """Return dictionary pairing times to total size of incs""" + time_dict = {} + for inc in inc_iter: + if not inc.isincfile(): continue + t = inc.getinctime() + if not time_dict.has_key(t): time_dict[t] = 0 + time_dict[t] += inc.getsize() + return time_dict + + def get_mirror_select(): + """Return iterator of mirror rpaths""" + mirror_base = mirror_root.new_index(index) + mirror_select = selection.Select(mirror_base) + if not index: # must exclude rdiff-backup-directory + mirror_select.parse_rbdir_exclude() + return mirror_select.set_iter() + + def get_inc_select(): + """Return iterator of increment rpaths""" + inc_base = Globals.rbdir.append_path('increments', index) + for base_inc in restore.get_inclist(inc_base): yield base_inc + if inc_base.isdir(): + inc_select = selection.Select(inc_base).set_iter() + for inc in inc_select: yield inc + + def get_summary_triples(mirror_total, time_dict): + """Return list of triples (time, size, cumulative size)""" + triples = [] + + cur_mir_base = Globals.rbdir.append('current_mirror') + mirror_time = restore.get_inclist(cur_mir_base)[0].getinctime() + triples.append((mirror_time, mirror_total, mirror_total)) + + inc_times = time_dict.keys() + inc_times.sort() + inc_times.reverse() + cumulative_size = mirror_total + for inc_time in inc_times: + size = time_dict[inc_time] + cumulative_size += size + triples.append((inc_time, size, cumulative_size)) + return triples + + def triple_to_line(triple): + """Convert triple to display string""" + time, size, cum_size = triple + return "%24s %13s %15s" % \ + (Time.timetopretty(time), + stat_obj.get_byte_summary_string(size), + stat_obj.get_byte_summary_string(cum_size)) + + mirror_total = get_total(get_mirror_select()) + time_dict = get_time_dict(get_inc_select()) + triples = get_summary_triples(mirror_total, time_dict) + + l = ['%12s %9s %15s %20s' % ('Time', '', 'Size', 'Cumulative size'), + '-' * 77, + triple_to_line(triples[0]) + ' (current mirror)'] + for triple in triples[1:]: l.append(triple_to_line(triple)) + return '\n'.join(l) diff --git a/rdiff-backup/testing/finaltest.py b/rdiff-backup/testing/finaltest.py index 2c6c13a..8285b36 100644 --- a/rdiff-backup/testing/finaltest.py +++ b/rdiff-backup/testing/finaltest.py @@ -503,6 +503,18 @@ class FinalMisc(PathSetter): self.exec_rb_extra_args(None, '--list-at-time 20000', 'testfiles/restoretest3') + def testListIncrementSizesLocal(self): + """Test --list-increment-sizes switch. Uses restoretest3""" + self.set_connections(None, None, None, None) + self.exec_rb_extra_args(None, "--list-increment-sizes", + "testfiles/restoretest3") + + def testListIncrementsRemote(self): + """Test --list-increment-sizes mode remotely. Uses restoretest3""" + self.set_connections('test1', '../', None, None) + self.exec_rb_extra_args(None, "--list-increment-sizes", + "testfiles/restoretest3") + def get_all_increments(self, rp): """Iterate all increments at or below given directory""" assert rp.isdir() -- cgit v1.2.1