| OLD | NEW |
| 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 from object_store_creator import ObjectStoreCreator |
| 7 | 8 |
| 8 class _AsyncUncachedFuture(object): | 9 class _AsyncUncachedFuture(object): |
| 9 def __init__(self, | 10 def __init__(self, |
| 10 uncached_read_futures, | 11 uncached_read_futures, |
| 11 stats_for_uncached, | 12 stats_for_uncached, |
| 12 current_results, | 13 current_results, |
| 13 file_system, | 14 file_system, |
| 14 object_store): | 15 object_store): |
| 15 self._uncached_read_futures = uncached_read_futures | 16 self._uncached_read_futures = uncached_read_futures |
| 16 self._stats_for_uncached = stats_for_uncached | 17 self._stats_for_uncached = stats_for_uncached |
| 17 self._current_results = current_results | 18 self._current_results = current_results |
| 18 self._file_system = file_system | 19 self._file_system = file_system |
| 19 self._object_store = object_store | 20 self._object_store = object_store |
| 20 | 21 |
| 21 def Get(self): | 22 def Get(self): |
| 22 new_results = self._uncached_read_futures.Get() | 23 new_results = self._uncached_read_futures.Get() |
| 23 # Update the cached data in the object store. This is a path -> (read, | 24 # Update the cached data in the object store. This is a path -> (read, |
| 24 # version) mapping. | 25 # version) mapping. |
| 25 self._object_store.SetMulti(dict( | 26 self._object_store.SetMulti(dict( |
| 26 (path, (new_result, self._stats_for_uncached[path].version)) | 27 (path, (new_result, self._stats_for_uncached[path].version)) |
| 27 for path, new_result in new_results.iteritems())) | 28 for path, new_result in new_results.iteritems())) |
| 28 new_results.update(self._current_results) | 29 new_results.update(self._current_results) |
| 29 return new_results | 30 return new_results |
| 30 | 31 |
| 31 class CachingFileSystem(FileSystem): | 32 class CachingFileSystem(FileSystem): |
| 32 '''FileSystem which implements a caching layer on top of |file_system|. It's | 33 '''FileSystem which implements a caching layer on top of |file_system|. It's |
| 33 smart, using Stat() to decided whether to skip Read()ing from |file_system|, | 34 smart, using Stat() to decided whether to skip Read()ing from |file_system|, |
| 34 and only Stat()ing directories never files. | 35 and only Stat()ing directories never files. |
| 35 | |
| 36 Specify |use_existing_values| to continue using whatever has been cached in | |
| 37 the object stores. By default, the data in the stores is assumed to be stale | |
| 38 (althought consistent). Using existing values is useful for live instances | |
| 39 that don't want to touch the file system; not using them is good for the | |
| 40 cron jobs, where we want to refresh the data. | |
| 41 ''' | 36 ''' |
| 42 def __init__(self, | 37 def __init__(self, file_system, object_store_creator): |
| 43 file_system, | |
| 44 object_store_creator_factory, | |
| 45 use_existing_values=False): | |
| 46 self._file_system = file_system | 38 self._file_system = file_system |
| 47 def create_object_store(category): | 39 def create_object_store(category, **optargs): |
| 48 return (object_store_creator_factory.Create(CachingFileSystem) | 40 return object_store_creator.Create( |
| 49 .Create(category='%s/%s' % (file_system.GetName(), category), | 41 CachingFileSystem, |
| 50 # By Stat()ing from scratch we'll end up not using the | 42 category='%s/%s' % (file_system.GetIdentity(), category), |
| 51 # existing values, but also not doing unnecessary Read()s if | 43 **optargs) |
| 52 # the files haven't changed from last time. | |
| 53 start_empty=(not use_existing_values and category == 'stat'))) | |
| 54 self._stat_object_store = create_object_store('stat') | 44 self._stat_object_store = create_object_store('stat') |
| 55 self._read_object_store = create_object_store('read') | 45 # Force the read stores to start populated, even if |object_store_creator| |
| 56 self._read_binary_object_store = create_object_store('read-binary') | 46 # is configured to start empty, because the result from Stat entirely |
| 47 # determines how we end up (re)Read-ing data. This is a core optimisation. |
| 48 self._read_object_store = create_object_store( |
| 49 'read', start_empty=False) |
| 50 self._read_binary_object_store = create_object_store( |
| 51 'read-binary', start_empty=False) |
| 57 | 52 |
| 58 def Stat(self, path): | 53 def Stat(self, path): |
| 59 '''Stats the directory given, or if a file is given, stats the file's parent | 54 '''Stats the directory given, or if a file is given, stats the file's parent |
| 60 directory to get info about the file. | 55 directory to get info about the file. |
| 61 ''' | 56 ''' |
| 62 # Always stat the parent directory, since it will have the stat of the child | 57 # Always stat the parent directory, since it will have the stat of the child |
| 63 # anyway, and this gives us an entire directory's stat info at once. | 58 # anyway, and this gives us an entire directory's stat info at once. |
| 64 if path.endswith('/'): | 59 if path.endswith('/'): |
| 65 dir_path = path | 60 dir_path = path |
| 66 else: | 61 else: |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 111 | 106 |
| 112 if not uncached: | 107 if not uncached: |
| 113 return Future(value=results) | 108 return Future(value=results) |
| 114 | 109 |
| 115 return Future(delegate=_AsyncUncachedFuture( | 110 return Future(delegate=_AsyncUncachedFuture( |
| 116 self._file_system.Read(uncached.keys(), binary=binary), | 111 self._file_system.Read(uncached.keys(), binary=binary), |
| 117 uncached, | 112 uncached, |
| 118 results, | 113 results, |
| 119 self, | 114 self, |
| 120 read_object_store)) | 115 read_object_store)) |
| OLD | NEW |