+ print "%s [%s]: %.3f +%.3f -%.3f (+%d/-%d segments)" % (s, intent, size / 1024.0**2, added / 1024.0**2, removed / 1024.0**2, addcount, remcount)
+
+def cmd_garbage_collect(args):
+ """ Search for any files which are not needed by any current
+ snapshots and offer to delete them.
+ Syntax: $0 --store=DATADIR gc
+ """
+ lowlevel = cumulus.LowlevelDataStore(options.store)
+ lowlevel.scan()
+ store = cumulus.ObjectStore(lowlevel)
+ snapshots = set(lowlevel.list_snapshots())
+ segments = set()
+ for s in snapshots:
+ d = cumulus.parse_full(store.load_snapshot(s))
+ check_version(d['Format'])
+ segments.update(d['Segments'].split())
+
+ referenced = snapshots.union(segments)
+ reclaimed = 0
+ for (t, r) in cumulus.store.type_patterns.items():
+ for f in lowlevel.store.list(t):
+ m = r.match(f)
+ if m is None or m.group(1) not in referenced:
+ print "Garbage:", (t, f)
+ reclaimed += lowlevel.store.stat(t, f)['size']
+ if not options.dry_run:
+ lowlevel.store.delete(t, f)
+ print "Reclaimed space:", reclaimed
+
+cmd_gc = cmd_garbage_collect