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 2d329c0a2efa94ad47607ea1da48c144c351075f..2ba1329a5b7ba446fd3794de8fe5b1b4718815fa 100644 |
--- a/chrome/common/extensions/docs/server2/compiled_file_system.py |
+++ b/chrome/common/extensions/docs/server2/compiled_file_system.py |
@@ -14,9 +14,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 |
ahernandez
2014/08/29 01:49:42
I don't know how to explain this concisely, but th
not at google - send to devlin
2014/08/29 05:00:14
Neat, nice catch. This nested decorator stuff in P
|
+ defintion. This causes issues when checking for 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 +47,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 |
@@ -100,8 +121,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: |
not at google - send to devlin
2014/08/29 05:00:14
JSON should be ... fairly cheap? Very commonly use
|
+ json_parse.Parse(ToUnicode(data)))), |
CompiledFileSystem, |
category='json') |
@@ -134,6 +155,27 @@ class CompiledFileSystem(object): |
self._file_object_store = file_object_store |
self._list_object_store = list_object_store |
+ def _GetFromStore(self, key, store): |
+ if _GetUnboundFunction(self._compilation_function) in _CACHEABLE_FUNCTIONS: |
+ return store.Get(key) |
+ return Future(value=None) |
+ |
+ def _SetToStore(self, key, value, store): |
+ if _GetUnboundFunction(self._compilation_function) in _CACHEABLE_FUNCTIONS: |
+ store.Set(key, value) |
+ |
+ def _GetFromFileStore(self, key): |
+ return self._GetFromStore(key, self._file_object_store) |
+ |
+ def _GetFromListStore(self, key): |
+ return self._GetFromStore(key, self._list_object_store) |
+ |
+ def _SetToFileStore(self, key, value): |
+ self._SetToStore(key, value, self._file_object_store) |
+ |
+ def _SetToListStore(self, key, value): |
+ self._SetToStore(key, value, self._list_object_store) |
+ |
def _RecursiveList(self, path): |
'''Returns a Future containing the recursive directory listing of |path| as |
a flat list of paths. |
@@ -199,13 +241,13 @@ class CompiledFileSystem(object): |
else: |
return Future(exc_info=sys.exc_info()) |
- cache_entry = self._file_object_store.Get(path).Get() |
+ cache_entry = self._GetFromFileStore(path).Get() |
not at google - send to devlin
2014/08/29 05:00:14
These wrapper functions are nice, but if you had s
|
if (cache_entry is not None) and (version == cache_entry.version): |
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._SetToFileStore(path, _CacheEntry(cache_data, version)) |
not at google - send to devlin
2014/08/29 05:00:14
(FWIW I think that "set in" reads slightly better
|
return cache_data |
return self._file_system.ReadSingle( |
@@ -222,25 +264,25 @@ class CompiledFileSystem(object): |
except FileNotFoundError: |
return Future(exc_info=sys.exc_info()) |
- cache_entry = self._list_object_store.Get(path).Get() |
+ cache_entry = self._GetFromListStore(path).Get() |
if (cache_entry is not None) and (version == cache_entry.version): |
return Future(value=cache_entry._cache_data) |
def next(files): |
cache_data = self._compilation_function(path, files) |
- self._list_object_store.Set(path, _CacheEntry(cache_data, version)) |
+ self._SetToListStore(path, _CacheEntry(cache_data, version)) |
return cache_data |
return self._RecursiveList(path).Then(next) |
def GetFileVersion(self, path): |
- cache_entry = self._file_object_store.Get(path).Get() |
+ cache_entry = self._GetFromFileStore(path).Get() |
if cache_entry is not None: |
return cache_entry.version |
return self._file_system.Stat(path).version |
def GetFileListingVersion(self, path): |
path = ToDirectory(path) |
- cache_entry = self._list_object_store.Get(path).Get() |
+ cache_entry = self._GetFromListStore(path).Get() |
if cache_entry is not None: |
return cache_entry.version |
return self._file_system.Stat(path).version |