| Index: chrome/common/extensions/docs/server2/chained_compiled_file_system.py
|
| diff --git a/chrome/common/extensions/docs/server2/chained_compiled_file_system.py b/chrome/common/extensions/docs/server2/chained_compiled_file_system.py
|
| index 3ae700aa0676819c1709d441845d516fb75ede93..92069340c8866c8272cd4729a4ef4a0aebea42b2 100644
|
| --- a/chrome/common/extensions/docs/server2/chained_compiled_file_system.py
|
| +++ b/chrome/common/extensions/docs/server2/chained_compiled_file_system.py
|
| @@ -8,30 +8,31 @@ from future import Gettable, Future
|
|
|
|
|
| class ChainedCompiledFileSystem(object):
|
| - ''' A CompiledFileSystem implementation that fetches data from a chain of
|
| - CompiledFileSystems that have different file systems and separate cache
|
| - namespaces.
|
| + '''A CompiledFileSystem implementation that fetches data from a chain of
|
| + possible FileSystems. The chain consists of some number of FileSystems which
|
| + may have cached data for their CompiledFileSystem instances (injected on
|
| + Factory construction) + the main FileSystem (injected at Creation time).
|
|
|
| - The rules for the compiled file system chain are:
|
| - - Versions are fetched from the first compiled file system's underlying
|
| - file system.
|
| - - Each compiled file system is read in the reverse order (the last one is
|
| - read first). If the version matches, return the data. Otherwise, read
|
| - from the previous compiled file system until the first one is read.
|
| + The expected configuration is that the main FileSystem is a PatchedFileSystem
|
| + and the chain the FileSystem which it patches, but with file systems
|
| + constructed via the HostFileSystemIterator the main FileSystems could be
|
| + anything.
|
|
|
| - It is used to chain compiled file systems whose underlying file systems are
|
| - slightly different. This makes it possible to reuse cached compiled data in
|
| - one of them without recompiling everything that is shared by them.
|
| + This slightly unusual configuration is primarily needed to avoid re-compiling
|
| + data for PatchedFileSystems, which are very similar to the FileSystem which
|
| + they patch. Re-compiling data is expensive and a waste of memory resources.
|
| + ChainedCompiledFileSystem shares the data.
|
| '''
|
| class Factory(CompiledFileSystem.Factory):
|
| - def __init__(self,
|
| - factory_and_fs_chain):
|
| - self._factory_and_fs_chain = factory_and_fs_chain
|
| + def __init__(self, file_system_chain, object_store):
|
| + self._file_system_chain = file_system_chain
|
| + self._object_store = object_store
|
|
|
| - def Create(self, populate_function, cls, category=None):
|
| - return ChainedCompiledFileSystem(
|
| - [(factory.Create(populate_function, cls, category), fs)
|
| - for factory, fs in self._factory_and_fs_chain])
|
| + def Create(self, file_system, populate_function, cls, category=None):
|
| + return ChainedCompiledFileSystem(tuple(
|
| + CompiledFileSystem.Factory(self._object_store).Create(
|
| + fs, populate_function, cls, category=category)
|
| + for fs in [file_system] + self._file_system_chain))
|
|
|
| def __init__(self, compiled_fs_chain):
|
| '''|compiled_fs_chain| is a list of tuples (compiled_fs, file_system).
|
| @@ -43,7 +44,7 @@ class ChainedCompiledFileSystem(object):
|
| return self._GetImpl(
|
| path,
|
| lambda compiled_fs: compiled_fs.GetFromFile(path, binary=binary),
|
| - lambda compiled_fs: compiled_fs.StatFile(path))
|
| + lambda compiled_fs: compiled_fs.GetFileVersion(path))
|
|
|
| def GetFromFileListing(self, path):
|
| if not path.endswith('/'):
|
| @@ -51,26 +52,30 @@ class ChainedCompiledFileSystem(object):
|
| return self._GetImpl(
|
| path,
|
| lambda compiled_fs: compiled_fs.GetFromFileListing(path),
|
| - lambda compiled_fs: compiled_fs.StatFileListing(path))
|
| + lambda compiled_fs: compiled_fs.GetFileListingVersion(path))
|
|
|
| - def _GetImpl(self, path, reader, statter):
|
| - # It's possible that a new file is added in the first compiled file system
|
| - # and it doesn't exist in other compiled file systems.
|
| + def _GetImpl(self, path, reader, version_getter):
|
| + # Strategy: Get the current version of |path| in main FileSystem, then run
|
| + # through |_compiled_fs_chain| in *reverse* to find the "oldest" FileSystem
|
| + # with an up-to-date version of that file.
|
| + #
|
| + # Obviously, if files have been added in the main FileSystem then none of
|
| + # the older FileSystems will be able to find it.
|
| read_futures = [(reader(compiled_fs), compiled_fs)
|
| - for compiled_fs, _ in self._compiled_fs_chain]
|
| + for compiled_fs in self._compiled_fs_chain]
|
|
|
| def resolve():
|
| try:
|
| - first_compiled_fs, first_file_system = self._compiled_fs_chain[0]
|
| + first_compiled_fs = self._compiled_fs_chain[0]
|
| # The first file system contains both files of a newer version and
|
| # files shared with other compiled file systems. We are going to try
|
| # each compiled file system in the reverse order and return the data
|
| # when version matches. Data cached in other compiled file system will
|
| # be reused whenever possible so that we don't need to recompile things
|
| # that are not changed across these file systems.
|
| - version = first_file_system.Stat(path).version
|
| + first_version = version_getter(first_compiled_fs)
|
| for read_future, compiled_fs in reversed(read_futures):
|
| - if statter(compiled_fs) == version:
|
| + if version_getter(compiled_fs) == first_version:
|
| return read_future.Get()
|
| except FileNotFoundError:
|
| pass
|
|
|