help="specify path to backup data store")
parser.add_option("--localdb", dest="localdb",
help="specify path to local database")
+parser.add_option("--intent", dest="intent", default=1.0,
+ help="give expected next snapshot type when cleaning")
(options, args) = parser.parse_args(sys.argv[1:])
# Read a passphrase from the user and store it in the LBS_GPG_PASSPHRASE
db = lbs.LocalDatabase(options.localdb)
# Delete old snapshots from the local database.
- db.garbage_collect()
- db.commit()
+ #db.garbage_collect()
+ #db.commit()
# Run the segment cleaner.
# Syntax: $0 --localdb=LOCALDB clean
db = lbs.LocalDatabase(options.localdb)
# Delete old snapshots from the local database.
- db.garbage_collect()
+ intent = float(options.intent)
+ for s in db.list_schemes():
+ db.garbage_collect(s, intent)
# Expire segments which are poorly-utilized.
for s in db.get_segment_cleaning_list():
lowlevel = lbs.LowlevelDataStore(options.store)
store = lbs.ObjectStore(lowlevel)
for s in snapshots:
+ lbs.accessed_segments.clear()
print "#### Snapshot", s
d = lbs.parse_full(store.load_snapshot(s))
check_version(d['Format'])
raise ValueError("File size does not match!")
if not verifier.valid():
raise ValueError("Bad checksum found")
+
+ # Verify that the list of segments included with the snapshot was
+ # actually accurate: covered all segments that were really read, and
+ # doesn't contain duplicates.
+ listed_segments = set(d['Segments'].split())
+ if lbs.accessed_segments - listed_segments:
+ print "Error: Some segments not listed in descriptor!"
+ print sorted(list(lbs.accessed_segments - listed_segments))
+ if listed_segments - lbs.accessed_segments :
+ print "Warning: Extra unused segments listed in descriptor!"
+ print sorted(list(listed_segments - lbs.accessed_segments))
store.cleanup()
# Restore a snapshot, or some subset of files from it
destdir = args[1]
paths = args[2:]
+ def matchpath(path):
+ "Return true if the specified path should be included in the restore."
+
+ # No specification of what to restore => restore everything
+ if len(paths) == 0: return True
+
+ for p in paths:
+ if path == p: return True
+ if path.startswith(p + "/"): return True
+ return False
+
def warn(m, msg):
print "Warning: %s: %s" % (m.items.name, msg)
pathname = os.path.normpath(m.items.name)
while os.path.isabs(pathname):
pathname = pathname[1:]
+ if not matchpath(pathname): continue
print pathname
destpath = os.path.join(destdir, pathname)
(path, filename) = os.path.split(destpath)