Преглед на файлове

Add function to clear empty directories at end of compact process.

Compact moves data to new segments, and then removes the old segments.
When enough segments are moved, directories holding the now cleared segments
may thus become empty.

With this commit any empty directories are cleared after segments compacting.
Fixes #6823
nain преди 2 години
родител
ревизия
aac55b1ad2
променени са 1 файла, в които са добавени 17 реда и са изтрити 0 реда
  1. 17 0
      src/borg/repository.py

+ 17 - 0
src/borg/repository.py

@@ -879,6 +879,7 @@ class Repository:
             pi.show()
             pi.show()
         pi.finish()
         pi.finish()
         complete_xfer(intermediate=False)
         complete_xfer(intermediate=False)
+        self.io.clear_empty_dirs()
         quota_use_after = self.storage_quota_use
         quota_use_after = self.storage_quota_use
         logger.info('compaction freed about %s repository space.', format_file_size(quota_use_before - quota_use_after))
         logger.info('compaction freed about %s repository space.', format_file_size(quota_use_before - quota_use_after))
         logger.debug('compaction completed.')
         logger.debug('compaction completed.')
@@ -1495,6 +1496,22 @@ class LoggedIO:
         except FileNotFoundError:
         except FileNotFoundError:
             pass
             pass
 
 
+    def clear_empty_dirs(self):
+        """Delete empty segment dirs, i.e those with no segment files.
+        """
+        data_dir = os.path.join(self.path, 'data')
+        segment_dirs = self.get_segment_dirs(data_dir)
+        for segment_dir in segment_dirs:
+            try:
+                # os.rmdir will only delete the directory if it is empty
+                # so we don't need to explicitly check for emptiness first.
+                os.rmdir(segment_dir)
+            except OSError:
+                # OSError is raised by os.rmdir if directory is not empty. This is expected.
+                # It's subclass FileNotFoundError may be raised if the directory already does not exist. Ignorable.
+                pass
+        sync_dir(data_dir)
+
     def segment_exists(self, segment):
     def segment_exists(self, segment):
         filename = self.segment_filename(segment)
         filename = self.segment_filename(segment)
         # When deleting segments, they are first truncated. If truncate(2) and unlink(2) are split
         # When deleting segments, they are first truncated. If truncate(2) and unlink(2) are split