Index: chrome/common/extensions/docs/server2/compiled_file_system.py |
diff --git a/chrome/common/extensions/docs/server2/compiled_file_system.py b/chrome/common/extensions/docs/server2/compiled_file_system.py |
index 265391dc4ff3d271401a81b7f00c4b82abf634be..4729ccf7feb7ea8eb567254b4e1b6d80c5188578 100644 |
--- a/chrome/common/extensions/docs/server2/compiled_file_system.py |
+++ b/chrome/common/extensions/docs/server2/compiled_file_system.py |
@@ -4,7 +4,6 @@ |
import sys |
-import schema_util |
from docs_server_utils import ToUnicode |
from file_system import FileNotFoundError |
from future import Future |
@@ -14,9 +13,30 @@ from third_party.json_schema_compiler.memoize import memoize |
from third_party.motemplate import Motemplate |
+_CACHEABLE_FUNCTIONS = set() |
_SINGLE_FILE_FUNCTIONS = set() |
+def _GetUnboundFunction(fn): |
+ '''Functions bound to an object are separate from the unbound |
+ defintion. This causes issues when checking for cache membership, |
+ so always get the unbound function, if possible. |
+ ''' |
+ return getattr(fn, 'im_func', fn) |
+ |
+ |
+def Cache(fn): |
+ '''A decorator which can be applied to the compilation function |
+ passed to CompiledFileSystem.Create, indicating that file/list data |
+ should be cached. |
+ |
+ This decorator should be listed first in any list of decorators, along |
+ with the SingleFile decorator below. |
+ ''' |
+ _CACHEABLE_FUNCTIONS.add(_GetUnboundFunction(fn)) |
+ return fn |
+ |
+ |
def SingleFile(fn): |
'''A decorator which can be optionally applied to the compilation function |
passed to CompiledFileSystem.Create, indicating that the function only |
@@ -26,7 +46,7 @@ def SingleFile(fn): |
Note that this decorator must be listed first in any list of decorators to |
have any effect. |
''' |
- _SINGLE_FILE_FUNCTIONS.add(fn) |
+ _SINGLE_FILE_FUNCTIONS.add(_GetUnboundFunction(fn)) |
return fn |
@@ -50,7 +70,7 @@ def Unicode(fn): |
class _CacheEntry(object): |
def __init__(self, cache_data, version): |
- self._cache_data = cache_data |
+ self.cache_data = cache_data |
self.version = version |
@@ -100,8 +120,8 @@ class CompiledFileSystem(object): |
These are memoized over file systems tied to different branches. |
''' |
return self.Create(file_system, |
- SingleFile(lambda _, data: |
- json_parse.Parse(ToUnicode(data))), |
+ Cache(SingleFile(lambda _, data: |
+ json_parse.Parse(ToUnicode(data)))), |
CompiledFileSystem, |
category='json') |
@@ -134,6 +154,15 @@ class CompiledFileSystem(object): |
self._file_object_store = file_object_store |
self._list_object_store = list_object_store |
+ def _Get(self, store, key): |
+ if _GetUnboundFunction(self._compilation_function) in _CACHEABLE_FUNCTIONS: |
+ return store.Get(key) |
+ return Future(value=None) |
+ |
+ def _Set(self, store, key, value): |
+ if _GetUnboundFunction(self._compilation_function) in _CACHEABLE_FUNCTIONS: |
+ store.Set(key, value) |
+ |
def _RecursiveList(self, path): |
'''Returns a Future containing the recursive directory listing of |path| as |
a flat list of paths. |
@@ -179,7 +208,7 @@ class CompiledFileSystem(object): |
files += add_prefix(dir_name[len(path):], new_files) |
if dirs: |
files += self._file_system.Read(dirs).Then( |
- lambda results: get_from_future_listing(results)).Get() |
+ get_from_future_listing).Get() |
return files |
return self._file_system.Read(add_prefix(path, first_layer_dirs)).Then( |
@@ -199,13 +228,13 @@ class CompiledFileSystem(object): |
else: |
return Future(exc_info=sys.exc_info()) |
- cache_entry = self._file_object_store.Get(path).Get() |
+ cache_entry = self._Get(self._file_object_store, path).Get() |
if (cache_entry is not None) and (version == cache_entry.version): |
- return Future(value=cache_entry._cache_data) |
+ return Future(value=cache_entry.cache_data) |
def compile_(files): |
cache_data = self._compilation_function(path, files) |
- self._file_object_store.Set(path, _CacheEntry(cache_data, version)) |
+ self._Set(self._file_object_store, path, _CacheEntry(cache_data, version)) |
return cache_data |
return self._file_system.ReadSingle( |
@@ -222,15 +251,15 @@ class CompiledFileSystem(object): |
except FileNotFoundError: |
return Future(exc_info=sys.exc_info()) |
- cache_entry = self._list_object_store.Get(path).Get() |
+ cache_entry = self._Get(self._list_object_store, path).Get() |
if (cache_entry is not None) and (version == cache_entry.version): |
- return Future(value=cache_entry._cache_data) |
+ return Future(value=cache_entry.cache_data) |
- def next(files): |
+ def compile_(files): |
cache_data = self._compilation_function(path, files) |
- self._list_object_store.Set(path, _CacheEntry(cache_data, version)) |
+ self._Set(self._list_object_store, path, _CacheEntry(cache_data, version)) |
return cache_data |
- return self._RecursiveList(path).Then(next) |
+ return self._RecursiveList(path).Then(compile_) |
# _GetFileVersionFromCache and _GetFileListingVersionFromCache are exposed |
# *only* so that ChainedCompiledFileSystem can optimise its caches. *Do not* |
@@ -238,7 +267,7 @@ class CompiledFileSystem(object): |
# FileSystem.Stat on the FileSystem that this CompiledFileSystem uses. |
def _GetFileVersionFromCache(self, path): |
- cache_entry = self._file_object_store.Get(path).Get() |
+ cache_entry = self._Get(self._file_object_store, path).Get() |
if cache_entry is not None: |
return Future(value=cache_entry.version) |
stat_future = self._file_system.StatAsync(path) |
@@ -246,7 +275,7 @@ class CompiledFileSystem(object): |
def _GetFileListingVersionFromCache(self, path): |
path = ToDirectory(path) |
- cache_entry = self._list_object_store.Get(path).Get() |
+ cache_entry = self._Get(self._list_object_store, path).Get() |
if cache_entry is not None: |
return Future(value=cache_entry.version) |
stat_future = self._file_system.StatAsync(path) |