| OLD | NEW |
| (Empty) | |
| 1 # Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. |
| 4 |
| 5 from compiled_file_system import CompiledFileSystem |
| 6 from file_system import FileNotFoundError |
| 7 |
| 8 class ChainedCompiledFileSystem(object): |
| 9 ''' A CompiledFileSystem implementation that fetches data from a chain of |
| 10 CompiledFileSystems that have different file systems and separate cache |
| 11 namespaces. |
| 12 |
| 13 The rules for the compiled file system chain are: |
| 14 - Versions are fetched from the first compiled file system's underlying |
| 15 file system. |
| 16 - Each compiled file system is read in the reverse order (the last one is |
| 17 read first). If the version matches, return the data. Otherwise, read |
| 18 from the previous compiled file system until the first one is read. |
| 19 |
| 20 It is used to chain compiled file systems whose underlying file systems are |
| 21 slightly different. This makes it possible to reuse cached compiled data in |
| 22 one of them without recompiling everything that is shared by them. |
| 23 ''' |
| 24 class Factory(CompiledFileSystem.Factory): |
| 25 def __init__(self, |
| 26 factory_and_fs_chain): |
| 27 self._factory_and_fs_chain = factory_and_fs_chain |
| 28 |
| 29 def Create(self, populate_function, cls, category=None): |
| 30 return ChainedCompiledFileSystem( |
| 31 [(factory.Create(populate_function, cls, category), fs) |
| 32 for factory, fs in self._factory_and_fs_chain]) |
| 33 |
| 34 def __init__(self, compiled_fs_chain): |
| 35 assert len(compiled_fs_chain) > 0 |
| 36 self._compiled_fs_chain = compiled_fs_chain |
| 37 |
| 38 def GetFromFile(self, path, binary=False): |
| 39 # It's possible that a new file is added in the first compiled file system |
| 40 # and it doesn't exist in other compiled file systems. |
| 41 try: |
| 42 first_compiled_fs, first_file_system = self._compiled_fs_chain[0] |
| 43 # The first file system contains both files of a newer version and files |
| 44 # shared with other compiled file systems. We are going to try each |
| 45 # compiled file system in the reverse order and return the data when |
| 46 # version matches. Data cached in other compiled file system will be |
| 47 # reused whenever possible so that we don't need to recompile things that |
| 48 # are not changed across these file systems. |
| 49 version = first_file_system.Stat(path).version |
| 50 for compiled_fs, _ in reversed(self._compiled_fs_chain): |
| 51 if compiled_fs.StatFile(path) == version: |
| 52 return compiled_fs.GetFromFile(path, binary) |
| 53 except FileNotFoundError: |
| 54 pass |
| 55 # Try first operation again to generate the correct stack trace |
| 56 return first_compiled_fs.GetFromFile(path, binary) |
| 57 |
| 58 def GetFromFileListing(self, path): |
| 59 if not path.endswith('/'): |
| 60 path += '/' |
| 61 try: |
| 62 first_compiled_fs, first_file_system = self._compiled_fs_chain[0] |
| 63 version = first_file_system.Stat(path).version |
| 64 for compiled_fs, _ in reversed(self._compiled_fs_chain): |
| 65 if compiled_fs.StatFileListing(path) == version: |
| 66 return compiled_fs.GetFromFileListing(path) |
| 67 except FileNotFoundError: |
| 68 pass |
| 69 # Try first operation again to generate the correct stack trace |
| 70 return first_compiled_fs.GetFromFileListing(path) |
| OLD | NEW |