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

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

Issue 1151283007: Docserver overhaul: Gitiles away from me. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 6 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
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 import logging 5 import logging
6 import posixpath 6 import posixpath
7 import sys 7 import sys
8 import traceback
Ken Rockot(use gerrit already) 2015/05/26 00:26:23 unused - removed in ps#2
8 9
9 from file_system import FileSystem, StatInfo, FileNotFoundError 10 from file_system import FileSystem, StatInfo, FileNotFoundError
10 from future import All, Future 11 from future import All, Future
11 from path_util import AssertIsDirectory, IsDirectory, ToDirectory 12 from path_util import AssertIsDirectory, IsDirectory, ToDirectory
12 from third_party.json_schema_compiler.memoize import memoize 13 from third_party.json_schema_compiler.memoize import memoize
13 14
14 15
15 class CachingFileSystem(FileSystem): 16 class CachingFileSystem(FileSystem):
16 '''FileSystem which implements a caching layer on top of |file_system|. If 17 '''FileSystem which implements a caching layer on top of |file_system|. If
17 |fail_on_miss| is True then cache misses throw a FileNotFoundError rather than 18 |fail_on_miss| is True then cache misses throw a FileNotFoundError rather than
18 falling back onto the underlying FileSystem. 19 falling back onto the underlying FileSystem.
19 20
20 If the underlying FileSystem is versioned (i.e., it implements GetVersion to 21 If the underlying FileSystem is versioned (i.e., it implements GetVersion to
21 return something other than None), this will create a persistent stat cache 22 return something other than None), this will create a persistent stat cache
22 (keyed on the FileSystem instance's version) as an additional optimization. 23 (keyed on the FileSystem instance's version) as an additional optimization.
23 ''' 24 '''
24 def __init__(self, file_system, object_store_creator, fail_on_miss=False): 25 def __init__(self, file_system, object_store_creator, fail_on_miss=False):
25 self._file_system = file_system 26 self._file_system = file_system
26 self._fail_on_miss = fail_on_miss 27 self._fail_on_miss = fail_on_miss
27 def create_object_store(category, try_versioning=False, **optargs): 28 def create_object_store(category, start_empty=True):
28 version = file_system.GetVersion()
29 versioned = try_versioning and version is not None
30 if versioned:
31 identity = '%s/%s' % (file_system.GetIdentity(), version)
32 else:
33 identity = file_system.GetIdentity()
34 optargs['start_empty'] = optargs.get('start_empty', not versioned)
35 return object_store_creator.Create( 29 return object_store_creator.Create(
36 CachingFileSystem, 30 CachingFileSystem,
37 category='%s/%s' % (identity, category), 31 category='%s/%s' % (file_system.GetIdentity(), category),
38 **optargs) 32 start_empty=start_empty)
39 self._stat_cache = create_object_store('stat', try_versioning=True) 33 # We only start the stat cache empty if |fail_on_miss| is False, i.e. if
40 # The read caches can start populated (start_empty=False) because file 34 # we're NOT running on a live instance and we can afford to fall back onto
41 # updates are picked up by the stat, so it doesn't need the force-refresh 35 # the underlying FileSystem impl.
42 # which starting empty is designed for. Without this optimisation, cron 36 self._stat_cache = create_object_store('stat', start_empty=not fail_on_miss)
43 # runs are extra slow.
44 self._read_cache = create_object_store('read', start_empty=False) 37 self._read_cache = create_object_store('read', start_empty=False)
45 self._walk_cache = create_object_store('walk', start_empty=False) 38 self._walk_cache = create_object_store('walk', start_empty=False)
46 39
47 def Refresh(self): 40 def Refresh(self):
48 return self._file_system.Refresh() 41 return self._file_system.Refresh()
49 42
50 def StatAsync(self, path): 43 def StatAsync(self, path):
51 '''Stats the directory given, or if a file is given, stats the file's parent 44 '''Stats the directory given, or if a file is given, stats the file's parent
52 directory to get info about the file. 45 directory to get info about the file.
53 ''' 46 '''
(...skipping 16 matching lines...) Expand all
70 return StatInfo(file_version) 63 return StatInfo(file_version)
71 64
72 def raise_cache_miss(path): 65 def raise_cache_miss(path):
73 raise FileNotFoundError('Got cache miss when trying to stat %s' % path) 66 raise FileNotFoundError('Got cache miss when trying to stat %s' % path)
74 67
75 dir_stat = self._stat_cache.Get(dir_path).Get() 68 dir_stat = self._stat_cache.Get(dir_path).Get()
76 if dir_stat is not None: 69 if dir_stat is not None:
77 return Future(callback=lambda: make_stat_info(dir_stat)) 70 return Future(callback=lambda: make_stat_info(dir_stat))
78 71
79 if self._fail_on_miss: 72 if self._fail_on_miss:
80 logging.warning('Bailing on stat cache miss for %s' % dir_path) 73 logging.warning('Bailing on stat cache miss for %s on %s' %
74 (dir_path, self.GetIdentity()))
81 return Future(callback=lambda: raise_cache_miss(dir_path)) 75 return Future(callback=lambda: raise_cache_miss(dir_path))
82 76
83 def next(dir_stat): 77 def next(dir_stat):
84 assert dir_stat is not None # should have raised a FileNotFoundError 78 assert dir_stat is not None # should have raised a FileNotFoundError
85 # We only ever need to cache the dir stat. 79 # We only ever need to cache the dir stat.
86 self._stat_cache.Set(dir_path, dir_stat) 80 self._stat_cache.Set(dir_path, dir_stat)
87 return make_stat_info(dir_stat) 81 return make_stat_info(dir_stat)
88 return self._MemoizedStatAsyncFromFileSystem(dir_path).Then(next) 82 return self._MemoizedStatAsyncFromFileSystem(dir_path).Then(next)
89 83
90 @memoize 84 @memoize
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 (path, data) for path, (data, version) in cached_read_values.iteritems() 128 (path, data) for path, (data, version) in cached_read_values.iteritems()
135 if version is not None and stat_futures[path].Get().version == version) 129 if version is not None and stat_futures[path].Get().version == version)
136 130
137 if skip_not_found: 131 if skip_not_found:
138 # Filter out paths which we know do not exist, i.e. if |path| is in 132 # Filter out paths which we know do not exist, i.e. if |path| is in
139 # |cached_read_values| *and* has a None version, then it doesn't exist. 133 # |cached_read_values| *and* has a None version, then it doesn't exist.
140 # See the above declaration of |cached_read_values| for more information. 134 # See the above declaration of |cached_read_values| for more information.
141 paths = [path for path in paths 135 paths = [path for path in paths
142 if cached_read_values.get(path, (None, True))[1]] 136 if cached_read_values.get(path, (None, True))[1]]
143 137
144 if len(up_to_date_data) == len(paths): 138 remaining_paths = set(paths) - set(up_to_date_data.iterkeys())
139 if len(remaining_paths) == 0:
145 # Everything was cached and up-to-date. 140 # Everything was cached and up-to-date.
146 return Future(value=up_to_date_data) 141 return Future(value=up_to_date_data)
147 142
143 def raise_cache_miss(paths):
144 raise FileNotFoundError('Got cache miss when trying to stat %s' % paths)
145
146 if self._fail_on_miss:
147 # Ignore missing values and return anyway.
148 logging.warn('Read cache miss for %s on %s' %
Ken Rockot(use gerrit already) 2015/05/26 00:26:23 This was pretty useful in debugging, so I was goin
149 (remaining_paths, self.GetIdentity()))
150 return Future(callback=lambda: raise_cache_miss(remaining_paths))
151
148 def next(new_results): 152 def next(new_results):
149 # Update the cache. This is a path -> (data, version) mapping. 153 # Update the cache. This is a path -> (data, version) mapping.
150 self._read_cache.SetMulti( 154 self._read_cache.SetMulti(
151 dict((path, (new_result, stat_futures[path].Get().version)) 155 dict((path, (new_result, stat_futures[path].Get().version))
152 for path, new_result in new_results.iteritems())) 156 for path, new_result in new_results.iteritems()))
153 # Update the read cache to include files that weren't found, to prevent 157 # Update the read cache to include files that weren't found, to prevent
154 # constantly trying to read a file we now know doesn't exist. 158 # constantly trying to read a file we now know doesn't exist.
155 self._read_cache.SetMulti( 159 self._read_cache.SetMulti(
156 dict((path, (None, None)) for path in paths 160 dict((path, (None, None)) for path in paths
157 if stat_futures[path].Get() is None)) 161 if stat_futures[path].Get() is None))
158 new_results.update(up_to_date_data) 162 new_results.update(up_to_date_data)
159 return new_results 163 return new_results
164
160 # Read in the values that were uncached or old. 165 # Read in the values that were uncached or old.
161 return self._file_system.Read(set(paths) - set(up_to_date_data.iterkeys()), 166 return self._file_system.Read(remaining_paths,
162 skip_not_found=skip_not_found).Then(next) 167 skip_not_found=skip_not_found).Then(next)
163 168
164 def GetCommitID(self): 169 def GetCommitID(self):
165 return self._file_system.GetCommitID() 170 return self._file_system.GetCommitID()
166 171
167 def GetPreviousCommitID(self): 172 def GetPreviousCommitID(self):
168 return self._file_system.GetPreviousCommitID() 173 return self._file_system.GetPreviousCommitID()
169 174
170 def Walk(self, root, depth=-1): 175 def Walk(self, root, depth=-1):
171 '''Overrides FileSystem.Walk() to provide caching functionality. 176 '''Overrides FileSystem.Walk() to provide caching functionality.
(...skipping 18 matching lines...) Expand all
190 return self._file_system.Walk(root, depth=depth, file_lister=file_lister) 195 return self._file_system.Walk(root, depth=depth, file_lister=file_lister)
191 196
192 def GetIdentity(self): 197 def GetIdentity(self):
193 return self._file_system.GetIdentity() 198 return self._file_system.GetIdentity()
194 199
195 def GetVersion(self): 200 def GetVersion(self):
196 return self._file_system.GetVersion() 201 return self._file_system.GetVersion()
197 202
198 def __repr__(self): 203 def __repr__(self):
199 return '%s of <%s>' % (type(self).__name__, repr(self._file_system)) 204 return '%s of <%s>' % (type(self).__name__, repr(self._file_system))
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698