1
0
Fork 0
mirror of https://github.com/borgbackup/borg.git synced 2024-12-26 09:47:58 +00:00

Repository: fix commit tags being seen in data

This commit is contained in:
Marian Beermann 2016-05-19 01:11:51 +02:00
parent eaf0f62022
commit 714e93bf64
No known key found for this signature in database
GPG key ID: 9B8450B91D1362C1
2 changed files with 32 additions and 6 deletions

View file

@ -536,7 +536,7 @@ def get_segments_transaction_id(self):
"""Verify that the transaction id is consistent with the index transaction id """Verify that the transaction id is consistent with the index transaction id
""" """
for segment, filename in self.segment_iterator(reverse=True): for segment, filename in self.segment_iterator(reverse=True):
if self.is_committed_segment(filename): if self.is_committed_segment(segment):
return segment return segment
return None return None
@ -550,10 +550,14 @@ def cleanup(self, transaction_id):
else: else:
break break
def is_committed_segment(self, filename): def is_committed_segment(self, segment):
"""Check if segment ends with a COMMIT_TAG tag """Check if segment ends with a COMMIT_TAG tag
""" """
with open(filename, 'rb') as fd: try:
iterator = self.iter_objects(segment)
except IntegrityError:
return False
with open(self.segment_filename(segment), 'rb') as fd:
try: try:
fd.seek(-self.header_fmt.size, os.SEEK_END) fd.seek(-self.header_fmt.size, os.SEEK_END)
except OSError as e: except OSError as e:
@ -561,7 +565,22 @@ def is_committed_segment(self, filename):
if e.errno == errno.EINVAL: if e.errno == errno.EINVAL:
return False return False
raise e raise e
return fd.read(self.header_fmt.size) == self.COMMIT if fd.read(self.header_fmt.size) != self.COMMIT:
return False
seen_commit = False
while True:
try:
tag, key, offset = next(iterator)
except IntegrityError:
return False
except StopIteration:
break
if tag == TAG_COMMIT:
seen_commit = True
continue
if seen_commit:
return False
return seen_commit
def segment_filename(self, segment): def segment_filename(self, segment):
return os.path.join(self.path, 'data', str(segment // self.segments_per_dir), str(segment)) return os.path.join(self.path, 'data', str(segment // self.segments_per_dir), str(segment))

View file

@ -8,7 +8,7 @@
from ..helpers import Location, IntegrityError from ..helpers import Location, IntegrityError
from ..locking import UpgradableLock, LockFailed from ..locking import UpgradableLock, LockFailed
from ..remote import RemoteRepository, InvalidRPCMethod from ..remote import RemoteRepository, InvalidRPCMethod
from ..repository import Repository from ..repository import Repository, LoggedIO, TAG_COMMIT
from . import BaseTestCase from . import BaseTestCase
@ -192,6 +192,13 @@ def test_crash_before_deleting_compacted_segments(self):
self.assert_equal(self.repository.check(), True) self.assert_equal(self.repository.check(), True)
self.assert_equal(len(self.repository), 3) self.assert_equal(len(self.repository), 3)
def test_ignores_commit_tag_in_data(self):
self.repository.put(b'0' * 32, LoggedIO.COMMIT)
self.reopen()
with self.repository:
io = self.repository.io
assert not io.is_committed_segment(io.get_latest_segment())
class RepositoryAppendOnlyTestCase(RepositoryTestCaseBase): class RepositoryAppendOnlyTestCase(RepositoryTestCaseBase):
def test_destroy_append_only(self): def test_destroy_append_only(self):
@ -268,7 +275,7 @@ def list_objects(self):
return set(int(key) for key in self.repository.list()) return set(int(key) for key in self.repository.list())
def test_repair_corrupted_segment(self): def test_repair_corrupted_segment(self):
self.add_objects([[1, 2, 3], [4, 5, 6]]) self.add_objects([[1, 2, 3], [4, 5], [6]])
self.assert_equal(set([1, 2, 3, 4, 5, 6]), self.list_objects()) self.assert_equal(set([1, 2, 3, 4, 5, 6]), self.list_objects())
self.check(status=True) self.check(status=True)
self.corrupt_object(5) self.corrupt_object(5)