Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(597)

Side by Side Diff: chrome/common/extensions/docs/server2/caching_file_system.py

Issue 13470005: Refactor the devserver to make it easier to control caching (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: cduvall, rebase Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be 2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file. 3 # found in the LICENSE file.
4 4
5 from file_system import FileSystem, StatInfo, FileNotFoundError 5 from file_system import FileSystem, StatInfo, FileNotFoundError
6 from future import Future 6 from future import Future
7 import object_store 7 from object_store_creator import ObjectStoreCreator
8 8
9 class _AsyncUncachedFuture(object): 9 class _AsyncUncachedFuture(object):
10 def __init__(self, 10 def __init__(self,
11 uncached, 11 uncached,
12 current_result, 12 current_result,
13 file_system, 13 file_system,
14 object_store, 14 object_store):
15 namespace):
16 self._uncached = uncached 15 self._uncached = uncached
17 self._current_result = current_result 16 self._current_result = current_result
18 self._file_system = file_system 17 self._file_system = file_system
19 self._object_store = object_store 18 self._object_store = object_store
20 self._namespace = namespace
21 19
22 def Get(self): 20 def Get(self):
23 mapping = {} 21 mapping = {}
24 new_items = self._uncached.Get() 22 new_items = self._uncached.Get()
25 for item in new_items: 23 for item in new_items:
26 version = self._file_system.Stat(item).version 24 version = self._file_system.Stat(item).version
27 mapping[item] = (new_items[item], version) 25 mapping[item] = (new_items[item], version)
28 self._current_result[item] = new_items[item] 26 self._current_result[item] = new_items[item]
29 self._object_store.SetMulti(mapping, self._namespace, time=0) 27 self._object_store.SetMulti(mapping, time=0)
30 return self._current_result 28 return self._current_result
31 29
32 class MemcacheFileSystem(FileSystem): 30 class CachingFileSystem(FileSystem):
33 """FileSystem implementation which memcaches the results of Read. 31 """FileSystem implementation which caches its results in an object store.
34 """ 32 """
35 def __init__(self, file_system, object_store): 33 def __init__(self, file_system):
36 self._file_system = file_system 34 self._file_system = file_system
37 self._object_store = object_store 35 object_store_creator = ObjectStoreCreator(CachingFileSystem)
36 self._stat_object_store = object_store_creator.Create(
37 category='stat')
38 self._read_object_store = object_store_creator.Create(
39 category='read')
40 self._read_binary_object_store = object_store_creator.Create(
41 category='read-binary')
38 42
39 def Stat(self, path, stats=None): 43 def Stat(self, path, stats=None):
40 """Stats the directory given, or if a file is given, stats the files parent 44 """Stats the directory given, or if a file is given, stats the files parent
41 directory to get info about the file. 45 directory to get info about the file.
42 """ 46 """
43 # TODO(kalman): store the whole stat info, not just the version. 47 # TODO(kalman): store the whole stat info, not just the version.
44 version = self._object_store.Get(path, object_store.FILE_SYSTEM_STAT).Get() 48 version = self._stat_object_store.Get(path).Get()
45 if version is not None: 49 if version is not None:
46 return StatInfo(version) 50 return StatInfo(version)
47 51
48 # Always stat the parent directory, since it will have the stat of the child 52 # Always stat the parent directory, since it will have the stat of the child
49 # anyway, and this gives us an entire directory's stat info at once. 53 # anyway, and this gives us an entire directory's stat info at once.
50 if path.endswith('/'): 54 if path.endswith('/'):
51 dir_path = path 55 dir_path = path
52 else: 56 else:
53 dir_path = path.rsplit('/', 1)[0] + '/' 57 dir_path = path.rsplit('/', 1)[0] + '/'
54 58
55 dir_stat = self._file_system.Stat(dir_path) 59 dir_stat = self._file_system.Stat(dir_path)
56 if path == dir_path: 60 if path == dir_path:
57 version = dir_stat.version 61 version = dir_stat.version
58 else: 62 else:
59 version = dir_stat.child_versions.get(path.split('/')[-1], None) 63 version = dir_stat.child_versions.get(path.split('/')[-1], None)
60 if version is None: 64 if version is None:
61 raise FileNotFoundError(path) 65 raise FileNotFoundError(path)
62 mapping = { path: version } 66 mapping = { path: version }
63 67
64 for child_path, child_version in dir_stat.child_versions.iteritems(): 68 for child_path, child_version in dir_stat.child_versions.iteritems():
65 child_path = dir_path + child_path 69 child_path = dir_path + child_path
66 mapping[child_path] = child_version 70 mapping[child_path] = child_version
67 self._object_store.SetMulti(mapping, object_store.FILE_SYSTEM_STAT) 71 self._stat_object_store.SetMulti(mapping)
68 return StatInfo(version) 72 return StatInfo(version)
69 73
70 def Read(self, paths, binary=False): 74 def Read(self, paths, binary=False):
71 """Reads a list of files. If a file is in memcache and it is not out of 75 """Reads a list of files. If a file is in memcache and it is not out of
72 date, it is returned. Otherwise, the file is retrieved from the file system. 76 date, it is returned. Otherwise, the file is retrieved from the file system.
73 """ 77 """
74 result = {} 78 result = {}
75 uncached = [] 79 uncached = []
76 namespace = object_store.FILE_SYSTEM_READ 80 read_object_store = (self._read_binary_object_store if binary else
77 if binary: 81 self._read_object_store)
78 namespace = '%s.binary' % namespace 82 results = read_object_store.GetMulti(paths).Get()
79 results = self._object_store.GetMulti(paths, namespace, time=0).Get()
80 result_values = [x[1] for x in sorted(results.iteritems())] 83 result_values = [x[1] for x in sorted(results.iteritems())]
81 stats = self._object_store.GetMulti(paths, 84 stats = self._stat_object_store.GetMulti(paths).Get()
82 object_store.FILE_SYSTEM_STAT).Get()
83 stat_values = [x[1] for x in sorted(stats.iteritems())] 85 stat_values = [x[1] for x in sorted(stats.iteritems())]
84 for path, cached_result, stat in zip(sorted(paths), 86 for path, cached_result, stat in zip(sorted(paths),
85 result_values, 87 result_values,
86 stat_values): 88 stat_values):
87 if cached_result is None: 89 if cached_result is None:
88 uncached.append(path) 90 uncached.append(path)
89 continue 91 continue
90 data, version = cached_result 92 data, version = cached_result
91 # TODO(cduvall): Make this use a multi stat. 93 # TODO(cduvall): Make this use a multi stat.
92 if stat is None: 94 if stat is None:
93 stat = self.Stat(path).version 95 stat = self.Stat(path).version
94 if stat != version: 96 if stat != version:
95 uncached.append(path) 97 uncached.append(path)
96 continue 98 continue
97 result[path] = data 99 result[path] = data
98 100
99 if not uncached: 101 if not uncached:
100 return Future(value=result) 102 return Future(value=result)
101 return Future(delegate=_AsyncUncachedFuture( 103 return Future(delegate=_AsyncUncachedFuture(
102 self._file_system.Read(uncached, binary=binary), 104 self._file_system.Read(uncached, binary=binary),
103 result, 105 result,
104 self, 106 self,
105 self._object_store, 107 read_object_store))
106 namespace))
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698