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