1
0
Fork 0
mirror of https://github.com/borgbackup/borg.git synced 2024-12-26 01:37:20 +00:00

Merge pull request #3002 from ThomasWaldmann/fd-cache-invalidation

FD cache invalidation
This commit is contained in:
enkore 2017-09-07 10:36:09 +02:00 committed by GitHub
commit 0607474586
2 changed files with 25 additions and 0 deletions

View file

@ -1176,6 +1176,8 @@ def cleanup(self, transaction_id):
count = 0 count = 0
for segment, filename in self.segment_iterator(reverse=True): for segment, filename in self.segment_iterator(reverse=True):
if segment > transaction_id: if segment > transaction_id:
if segment in self.fds:
del self.fds[segment]
truncate_and_unlink(filename) truncate_and_unlink(filename)
count += 1 count += 1
else: else:
@ -1232,6 +1234,12 @@ def get_write_fd(self, no_new=False, raise_full=False):
self._write_fd = SyncFile(self.segment_filename(self.segment), binary=True) self._write_fd = SyncFile(self.segment_filename(self.segment), binary=True)
self._write_fd.write(MAGIC) self._write_fd.write(MAGIC)
self.offset = MAGIC_LEN self.offset = MAGIC_LEN
if self.segment in self.fds:
# we may have a cached fd for a segment file we already deleted and
# we are writing now a new segment file to same file name. get rid of
# of the cached fd that still refers to the old file, so it will later
# get repopulated (on demand) with a fd that refers to the new file.
del self.fds[self.segment]
return self._write_fd return self._write_fd
def get_fd(self, segment): def get_fd(self, segment):

View file

@ -210,6 +210,23 @@ def test_sparse_delete(self):
self.repository.commit() self.repository.commit()
assert 0 not in [segment for segment, _ in self.repository.io.segment_iterator()] assert 0 not in [segment for segment, _ in self.repository.io.segment_iterator()]
def test_uncommitted_garbage(self):
# uncommitted garbage should be no problem, it is cleaned up automatically.
# we just have to be careful with invalidation of cached FDs in LoggedIO.
self.repository.put(H(0), b'foo')
self.repository.commit()
# write some crap to a uncommitted segment file
last_segment = self.repository.io.get_latest_segment()
with open(self.repository.io.segment_filename(last_segment + 1), 'wb') as f:
f.write(MAGIC + b'crapcrapcrap')
self.repository.close()
# usually, opening the repo and starting a transaction should trigger a cleanup.
self.repository = self.open()
with self.repository:
self.repository.put(H(0), b'bar') # this may trigger compact_segments()
self.repository.commit()
# the point here is that nothing blows up with an exception.
class RepositoryCommitTestCase(RepositoryTestCaseBase): class RepositoryCommitTestCase(RepositoryTestCaseBase):