| 
														
															@@ -12,10 +12,13 @@ logger = create_logger() 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 from .helpers import Error, get_cache_dir, decode_dict, int_to_bigint, \ 
														 | 
														
														 | 
														
															 from .helpers import Error, get_cache_dir, decode_dict, int_to_bigint, \ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															     bigint_to_int, format_file_size, yes 
														 | 
														
														 | 
														
															     bigint_to_int, format_file_size, yes 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 from .locking import UpgradableLock 
														 | 
														
														 | 
														
															 from .locking import UpgradableLock 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-from .hashindex import ChunkIndex 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+from .hashindex import ChunkIndex, ChunkIndexEntry 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															 import msgpack 
														 | 
														
														 | 
														
															 import msgpack 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ChunkListEntry = namedtuple('ChunkListEntry', 'id size csize') 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+FileCacheEntry = namedtuple('FileCacheEntry', 'age inode size mtime chunk_ids') 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+ 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															 class Cache: 
														 | 
														
														 | 
														
															 class Cache: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															     """Client Side cache 
														 | 
														
														 | 
														
															     """Client Side cache 
														 | 
													
												
											
										
											
												
													
														 | 
														
															@@ -183,9 +186,9 @@ Chunk index:    {0.total_unique_chunks:20d} {0.total_chunks:20d}""" 
														 | 
													
												
											
												
													
														| 
														 | 
														
															                     break 
														 | 
														
														 | 
														
															                     break 
														 | 
													
												
											
												
													
														| 
														 | 
														
															                 u.feed(data) 
														 | 
														
														 | 
														
															                 u.feed(data) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															                 for path_hash, item in u: 
														 | 
														
														 | 
														
															                 for path_hash, item in u: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-                    item[0] += 1 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                    entry = FileCacheEntry(*item) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															                     # in the end, this takes about 240 Bytes per file 
														 | 
														
														 | 
														
															                     # in the end, this takes about 240 Bytes per file 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-                    self.files[path_hash] = msgpack.packb(item) 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                    self.files[path_hash] = msgpack.packb(entry._replace(age=entry.age + 1)) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															     def begin_txn(self): 
														 | 
														
														 | 
														
															     def begin_txn(self): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         # Initialize transaction snapshot 
														 | 
														
														 | 
														
															         # Initialize transaction snapshot 
														 | 
													
												
											
										
											
												
													
														 | 
														
															@@ -208,9 +211,9 @@ Chunk index:    {0.total_unique_chunks:20d} {0.total_chunks:20d}""" 
														 | 
													
												
											
												
													
														| 
														 | 
														
															                 for path_hash, item in self.files.items(): 
														 | 
														
														 | 
														
															                 for path_hash, item in self.files.items(): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															                     # Discard cached files with the newest mtime to avoid 
														 | 
														
														 | 
														
															                     # Discard cached files with the newest mtime to avoid 
														 | 
													
												
											
												
													
														| 
														 | 
														
															                     # issues with filesystem snapshots and mtime precision 
														 | 
														
														 | 
														
															                     # issues with filesystem snapshots and mtime precision 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-                    item = msgpack.unpackb(item) 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-                    if item[0] < 10 and bigint_to_int(item[3]) < self._newest_mtime: 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-                        msgpack.pack((path_hash, item), fd) 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                    entry = FileCacheEntry(*msgpack.unpackb(item)) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                    if entry.age < 10 and bigint_to_int(entry.mtime) < self._newest_mtime: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                        msgpack.pack((path_hash, entry), fd) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         self.config.set('cache', 'manifest', hexlify(self.manifest.id).decode('ascii')) 
														 | 
														
														 | 
														
															         self.config.set('cache', 'manifest', hexlify(self.manifest.id).decode('ascii')) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         self.config.set('cache', 'timestamp', self.manifest.timestamp) 
														 | 
														
														 | 
														
															         self.config.set('cache', 'timestamp', self.manifest.timestamp) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         self.config.set('cache', 'key_type', str(self.key.TYPE)) 
														 | 
														
														 | 
														
															         self.config.set('cache', 'key_type', str(self.key.TYPE)) 
														 | 
													
												
											
										
											
												
													
														 | 
														
															@@ -375,12 +378,12 @@ Chunk index:    {0.total_unique_chunks:20d} {0.total_chunks:20d}""" 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         data = self.key.encrypt(data) 
														 | 
														
														 | 
														
															         data = self.key.encrypt(data) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         csize = len(data) 
														 | 
														
														 | 
														
															         csize = len(data) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         self.repository.put(id, data, wait=False) 
														 | 
														
														 | 
														
															         self.repository.put(id, data, wait=False) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        self.chunks[id] = (refcount + 1, size, csize) 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        self.chunks[id] = ChunkIndexEntry(refcount + 1, size, csize) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         stats.update(size, csize, True) 
														 | 
														
														 | 
														
															         stats.update(size, csize, True) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        return id, size, csize 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        return ChunkListEntry(id, size, csize) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															     def seen_chunk(self, id, size=None): 
														 | 
														
														 | 
														
															     def seen_chunk(self, id, size=None): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        refcount, stored_size, _ = self.chunks.get(id, (0, None, None)) 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        refcount, stored_size, _ = self.chunks.get(id, ChunkIndexEntry(0, None, None)) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         if size is not None and stored_size is not None and size != stored_size: 
														 | 
														
														 | 
														
															         if size is not None and stored_size is not None and size != stored_size: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															             # we already have a chunk with that id, but different size. 
														 | 
														
														 | 
														
															             # we already have a chunk with that id, but different size. 
														 | 
													
												
											
												
													
														| 
														 | 
														
															             # this is either a hash collision (unlikely) or corruption or a bug. 
														 | 
														
														 | 
														
															             # this is either a hash collision (unlikely) or corruption or a bug. 
														 | 
													
												
											
										
											
												
													
														 | 
														
															@@ -393,7 +396,7 @@ Chunk index:    {0.total_unique_chunks:20d} {0.total_chunks:20d}""" 
														 | 
													
												
											
												
													
														| 
														 | 
														
															             self.begin_txn() 
														 | 
														
														 | 
														
															             self.begin_txn() 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         count, size, csize = self.chunks.incref(id) 
														 | 
														
														 | 
														
															         count, size, csize = self.chunks.incref(id) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         stats.update(size, csize, False) 
														 | 
														
														 | 
														
															         stats.update(size, csize, False) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        return id, size, csize 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        return ChunkListEntry(id, size, csize) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															     def chunk_decref(self, id, stats): 
														 | 
														
														 | 
														
															     def chunk_decref(self, id, stats): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         if not self.txn_active: 
														 | 
														
														 | 
														
															         if not self.txn_active: 
														 | 
													
												
											
										
											
												
													
														 | 
														
															@@ -414,20 +417,17 @@ Chunk index:    {0.total_unique_chunks:20d} {0.total_chunks:20d}""" 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         entry = self.files.get(path_hash) 
														 | 
														
														 | 
														
															         entry = self.files.get(path_hash) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         if not entry: 
														 | 
														
														 | 
														
															         if not entry: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															             return None 
														 | 
														
														 | 
														
															             return None 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        entry = msgpack.unpackb(entry) 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        if (entry[2] == st.st_size and bigint_to_int(entry[3]) == st.st_mtime_ns and 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-                (ignore_inode or entry[1] == st.st_ino)): 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-            # reset entry age 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-            entry[0] = 0 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-            self.files[path_hash] = msgpack.packb(entry) 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-            return entry[4] 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        entry = FileCacheEntry(*msgpack.unpackb(entry)) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        if (entry.size == st.st_size and bigint_to_int(entry.mtime) == st.st_mtime_ns and 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+                (ignore_inode or entry.inode == st.st_ino)): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            self.files[path_hash] = msgpack.packb(entry._replace(age=0)) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+            return entry.chunk_ids 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         else: 
														 | 
														
														 | 
														
															         else: 
														 | 
													
												
											
												
													
														| 
														 | 
														
															             return None 
														 | 
														
														 | 
														
															             return None 
														 | 
													
												
											
												
													
														| 
														 | 
														
															  
														 | 
														
														 | 
														
															  
														 | 
													
												
											
												
													
														| 
														 | 
														
															     def memorize_file(self, path_hash, st, ids): 
														 | 
														
														 | 
														
															     def memorize_file(self, path_hash, st, ids): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															         if not (self.do_files and stat.S_ISREG(st.st_mode)): 
														 | 
														
														 | 
														
															         if not (self.do_files and stat.S_ISREG(st.st_mode)): 
														 | 
													
												
											
												
													
														| 
														 | 
														
															             return 
														 | 
														
														 | 
														
															             return 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        # Entry: Age, inode, size, mtime, chunk ids 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        mtime_ns = st.st_mtime_ns 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        self.files[path_hash] = msgpack.packb((0, st.st_ino, st.st_size, int_to_bigint(mtime_ns), ids)) 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															-        self._newest_mtime = max(self._newest_mtime, mtime_ns) 
														 | 
														
														 | 
														
															 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        entry = FileCacheEntry(age=0, inode=st.st_ino, size=st.st_size, mtime=int_to_bigint(st.st_mtime_ns), chunk_ids=ids) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        self.files[path_hash] = msgpack.packb(entry) 
														 | 
													
												
											
												
													
														| 
														 | 
														
															 
														 | 
														
														 | 
														
															+        self._newest_mtime = max(self._newest_mtime, st.st_mtime_ns) 
														 |