| 
														
															@@ -2,6 +2,7 @@ import errno 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 import io 
														 | 
														
														 | 
														
															 import io 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 import os 
														 | 
														
														 | 
														
															 import os 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 import stat 
														 | 
														
														 | 
														
															 import stat 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+import sys 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 import tempfile 
														 | 
														
														 | 
														
															 import tempfile 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 import time 
														 | 
														
														 | 
														
															 import time 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 from collections import defaultdict 
														 | 
														
														 | 
														
															 from collections import defaultdict 
														 | 
													
												
											
										
											
												
													
														 | 
														
															@@ -16,7 +17,7 @@ from .logger import create_logger 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 logger = create_logger() 
														 | 
														
														 | 
														
															 logger = create_logger() 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															 from .archive import Archive 
														 | 
														
														 | 
														
															 from .archive import Archive 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-from .helpers import daemonize, hardlinkable 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+from .helpers import daemonize, hardlinkable, signal_handler, format_file_size 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 from .item import Item 
														 | 
														
														 | 
														
															 from .item import Item 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 from .lrucache import LRUCache 
														 | 
														
														 | 
														
															 from .lrucache import LRUCache 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
										
											
												
													
														 | 
														
															@@ -82,22 +83,32 @@ class FuseOperations(llfuse.Operations): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															     def _create_filesystem(self): 
														 | 
														
														 | 
														
															     def _create_filesystem(self): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         self._create_dir(parent=1)  # first call, create root dir (inode == 1) 
														 | 
														
														 | 
														
															         self._create_dir(parent=1)  # first call, create root dir (inode == 1) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         if self.args.location.archive: 
														 | 
														
														 | 
														
															         if self.args.location.archive: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-            archive = Archive(self.repository_uncached, self.key, self.manifest, self.args.location.archive, 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-                              consider_part_files=self.args.consider_part_files) 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-            self.process_archive(archive) 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            self.process_archive(self.args.location.archive) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         else: 
														 | 
														
														 | 
														
															         else: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															             archive_names = (x.name for x in self.manifest.archives.list_considering(self.args)) 
														 | 
														
														 | 
														
															             archive_names = (x.name for x in self.manifest.archives.list_considering(self.args)) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-            for name in archive_names: 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-                archive = Archive(self.repository_uncached, self.key, self.manifest, name, 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-                                  consider_part_files=self.args.consider_part_files) 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            for archive_name in archive_names: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															                 if self.versions: 
														 | 
														
														 | 
														
															                 if self.versions: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															                     # process archives immediately 
														 | 
														
														 | 
														
															                     # process archives immediately 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-                    self.process_archive(archive) 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                    self.process_archive(archive_name) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															                 else: 
														 | 
														
														 | 
														
															                 else: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															                     # lazy load archives, create archive placeholder inode 
														 | 
														
														 | 
														
															                     # lazy load archives, create archive placeholder inode 
														 | 
													
												
											
												
													
														| 
														 | 
														
															                     archive_inode = self._create_dir(parent=1) 
														 | 
														
														 | 
														
															                     archive_inode = self._create_dir(parent=1) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-                    self.contents[1][os.fsencode(name)] = archive_inode 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-                    self.pending_archives[archive_inode] = archive 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                    self.contents[1][os.fsencode(archive_name)] = archive_inode 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                    self.pending_archives[archive_inode] = archive_name 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    def sig_info_handler(self, sig_no, stack): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        logger.debug('fuse: %d inodes, %d synth inodes, %d edges (%s)', 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                     self._inode_count, len(self.items), len(self.parent), 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                     # getsizeof is the size of the dict itself; key and value are two small-ish integers, 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                     # which are shared due to code structure (this has been verified). 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                     format_file_size(sys.getsizeof(self.parent) + len(self.parent) * sys.getsizeof(self._inode_count))) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        logger.debug('fuse: %d pending archives', len(self.pending_archives)) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        logger.debug('fuse: ItemCache %d entries, %s', 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                     self._inode_count - len(self.items), 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                     format_file_size(os.stat(self.cache.fd.fileno()).st_size)) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        logger.debug('fuse: data cache: %d/%d entries, %s', len(self.data_cache.items()), self.data_cache._capacity, 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                     format_file_size(sum(len(chunk) for key, chunk in self.data_cache.items()))) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        self.repository.log_instrumentation() 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															     def mount(self, mountpoint, mount_options, foreground=False): 
														 | 
														
														 | 
														
															     def mount(self, mountpoint, mount_options, foreground=False): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         """Mount filesystem on *mountpoint* with *mount_options*.""" 
														 | 
														
														 | 
														
															         """Mount filesystem on *mountpoint* with *mount_options*.""" 
														 | 
													
												
											
										
											
												
													
														 | 
														
															@@ -126,7 +137,9 @@ class FuseOperations(llfuse.Operations): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         # mirror. 
														 | 
														
														 | 
														
															         # mirror. 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         umount = False 
														 | 
														
														 | 
														
															         umount = False 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         try: 
														 | 
														
														 | 
														
															         try: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-            signal = fuse_main() 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            with signal_handler('SIGUSR1', self.sig_info_handler), \ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                 signal_handler('SIGINFO', self.sig_info_handler): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                signal = fuse_main() 
														 | 
													
												
											
												
													
														| 
														 | 
														
															             # no crash and no signal (or it's ^C and we're in the foreground) -> umount request 
														 | 
														
														 | 
														
															             # no crash and no signal (or it's ^C and we're in the foreground) -> umount request 
														 | 
													
												
											
												
													
														| 
														 | 
														
															             umount = (signal is None or (signal == SIGINT and foreground)) 
														 | 
														
														 | 
														
															             umount = (signal is None or (signal == SIGINT and foreground)) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         finally: 
														 | 
														
														 | 
														
															         finally: 
														 | 
													
												
											
										
											
												
													
														 | 
														
															@@ -140,11 +153,14 @@ class FuseOperations(llfuse.Operations): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         self.parent[ino] = parent 
														 | 
														
														 | 
														
															         self.parent[ino] = parent 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         return ino 
														 | 
														
														 | 
														
															         return ino 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															-    def process_archive(self, archive, prefix=[]): 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+    def process_archive(self, archive_name, prefix=[]): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         """Build fuse inode hierarchy from archive metadata 
														 | 
														
														 | 
														
															         """Build fuse inode hierarchy from archive metadata 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         """ 
														 | 
														
														 | 
														
															         """ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         self.file_versions = {}  # for versions mode: original path -> version 
														 | 
														
														 | 
														
															         self.file_versions = {}  # for versions mode: original path -> version 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        t0 = time.perf_counter() 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         unpacker = msgpack.Unpacker() 
														 | 
														
														 | 
														
															         unpacker = msgpack.Unpacker() 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        archive = Archive(self.repository_uncached, self.key, self.manifest, archive_name, 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                          consider_part_files=self.args.consider_part_files) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         for key, chunk in zip(archive.metadata.items, self.repository.get_many(archive.metadata.items)): 
														 | 
														
														 | 
														
															         for key, chunk in zip(archive.metadata.items, self.repository.get_many(archive.metadata.items)): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															             data = self.key.decrypt(key, chunk) 
														 | 
														
														 | 
														
															             data = self.key.decrypt(key, chunk) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															             unpacker.feed(data) 
														 | 
														
														 | 
														
															             unpacker.feed(data) 
														 | 
													
												
											
										
											
												
													
														 | 
														
															@@ -168,6 +184,8 @@ class FuseOperations(llfuse.Operations): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															                 for segment in segments[:-1]: 
														 | 
														
														 | 
														
															                 for segment in segments[:-1]: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															                     parent = self.process_inner(segment, parent) 
														 | 
														
														 | 
														
															                     parent = self.process_inner(segment, parent) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															                 self.process_leaf(segments[-1], item, parent, prefix, is_dir) 
														 | 
														
														 | 
														
															                 self.process_leaf(segments[-1], item, parent, prefix, is_dir) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        duration = time.perf_counter() - t0 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        logger.debug('fuse: process_archive completed in %.1f s for archive %s', duration, archive.name) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															     def process_leaf(self, name, item, parent, prefix, is_dir): 
														 | 
														
														 | 
														
															     def process_leaf(self, name, item, parent, prefix, is_dir): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         def file_version(item): 
														 | 
														
														 | 
														
															         def file_version(item): 
														 | 
													
												
											
										
											
												
													
														 | 
														
															@@ -296,9 +314,9 @@ class FuseOperations(llfuse.Operations): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															     def _load_pending_archive(self, inode): 
														 | 
														
														 | 
														
															     def _load_pending_archive(self, inode): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         # Check if this is an archive we need to load 
														 | 
														
														 | 
														
															         # Check if this is an archive we need to load 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        archive = self.pending_archives.pop(inode, None) 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        if archive: 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-            self.process_archive(archive, [os.fsencode(archive.name)]) 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        archive_name = self.pending_archives.pop(inode, None) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        if archive_name: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            self.process_archive(archive_name, [os.fsencode(archive_name)]) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															     def lookup(self, parent_inode, name, ctx=None): 
														 | 
														
														 | 
														
															     def lookup(self, parent_inode, name, ctx=None): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         self._load_pending_archive(parent_inode) 
														 | 
														
														 | 
														
															         self._load_pending_archive(parent_inode) 
														 |