Index: chrome/common/extensions/docs/server2/memcache_file_system.py |
diff --git a/chrome/common/extensions/docs/server2/memcache_file_system.py b/chrome/common/extensions/docs/server2/memcache_file_system.py |
index 53bd0c992c6deca49acd914a6675cffeaad8f9e3..843fb4b96425f3a868dec7897b4bafea0daf86fb 100644 |
--- a/chrome/common/extensions/docs/server2/memcache_file_system.py |
+++ b/chrome/common/extensions/docs/server2/memcache_file_system.py |
@@ -2,7 +2,10 @@ |
# Use of this source code is governed by a BSD-style license that can be |
# found in the LICENSE file. |
-from file_system import FileSystem |
+import logging |
+import time |
+ |
+from file_system import FileSystem, StatInfo |
from future import Future |
import appengine_memcache as memcache |
@@ -14,25 +17,58 @@ class MemcacheFileSystem(FileSystem): |
self._memcache = memcache |
def Stat(self, path): |
+ start_time = time.time() |
+ try: |
+ return self._DoStat(path) |
+ finally: |
+ logging.info("(cached) Stat of %s took %sms", |
+ path, |
+ (time.time() - start_time) * 1000) |
+ |
+ def _DoStat(self, path): |
"""Stats the directory given, or if a file is given, stats the files parent |
directory to get info about the file. |
""" |
+ # TODO(kalman): store the whole stat info, not just the version. |
version = self._memcache.Get(path, memcache.MEMCACHE_FILE_SYSTEM_STAT) |
- if version is None: |
- stat_info = self._file_system.Stat(path) |
- self._memcache.Set(path, |
- stat_info.version, |
- memcache.MEMCACHE_FILE_SYSTEM_STAT) |
- if stat_info.child_versions is not None: |
- for child_path, child_version in stat_info.child_versions.iteritems(): |
- self._memcache.Set(path.rsplit('/', 1)[0] + '/' + child_path, |
- child_version, |
- memcache.MEMCACHE_FILE_SYSTEM_STAT) |
+ if version is not None: |
+ return StatInfo(version) |
+ |
+ # Always stat the parent directory, since it will have the stat of the child |
+ # anyway, and this gives us an entire directory's stat info at once. |
+ if path.endswith('/'): |
+ dir_path = path |
else: |
- stat_info = self.StatInfo(version) |
- return stat_info |
+ dir_path = path.rsplit('/', 1)[0] + '/' |
+ |
+ # TODO: batch set? |
+ dir_stat = self._file_system.Stat(dir_path) |
+ if path == dir_path: |
+ version = dir_stat.version |
+ |
+ self._memcache.Set(path, |
+ dir_stat.version, |
+ memcache.MEMCACHE_FILE_SYSTEM_STAT) |
+ |
+ for child_path, child_version in dir_stat.child_versions.iteritems(): |
+ child_path = dir_path + child_path |
+ if path == child_path: |
+ version = child_version |
+ self._memcache.Set(child_path, |
+ child_version, |
+ memcache.MEMCACHE_FILE_SYSTEM_STAT) |
+ return StatInfo(version) |
def Read(self, paths, binary=False): |
+ start_time = time.time() |
+ try: |
+ return self._DoRead(paths, binary=binary) |
+ finally: |
+ logging.info("(cached) Read of %s took %sms", |
+ paths, |
+ (time.time() - start_time) * 1000) |
+ |
+ def _DoRead(self, paths, binary=False): |
"""Reads a list of files. If a file is in memcache and it is not out of |
date, it is returned. Otherwise, the file is retrieved from the file system. |
""" |
@@ -50,17 +86,20 @@ class MemcacheFileSystem(FileSystem): |
uncached.append(path) |
continue |
result[path] = data |
- if uncached: |
- # TODO(cduvall): if there are uncached items we should return an |
- # asynchronous future. http://crbug.com/142013 |
- new_items = self._file_system.Read(uncached, binary=binary).Get() |
- for item in new_items: |
- version = self.Stat(item).version |
- value = new_items[item] |
- # Cache this file forever. |
- self._memcache.Set(item, |
- (value, version), |
- memcache.MEMCACHE_FILE_SYSTEM_READ, |
- time=0) |
- result[item] = value |
+ |
+ if not uncached: |
+ return Future(value=result) |
+ |
+ # TODO(cduvall): if there are uncached items we should return an |
+ # asynchronous future. http://crbug.com/142013 |
+ new_items = self._file_system.Read(uncached, binary=binary).Get() |
+ for item in new_items: |
+ version = self.Stat(item).version |
+ value = new_items[item] |
+ self._memcache.Set(item, |
+ (value, version), |
+ memcache.MEMCACHE_FILE_SYSTEM_READ, |
+ # Forever. |
+ time=0) |
+ result[item] = value |
return Future(value=result) |