| OLD | NEW |
| 1 # Copyright 2016 The LUCI Authors. All rights reserved. | 1 # Copyright 2016 The LUCI Authors. All rights reserved. |
| 2 # Use of this source code is governed under the Apache License, Version 2.0 | 2 # Use of this source code is governed under the Apache License, Version 2.0 |
| 3 # that can be found in the LICENSE file. | 3 # that can be found in the LICENSE file. |
| 4 | 4 |
| 5 """This file implements Named Caches.""" | 5 """This file implements Named Caches.""" |
| 6 | 6 |
| 7 import contextlib | 7 import contextlib |
| 8 import logging | 8 import logging |
| 9 import optparse | 9 import optparse |
| 10 import os | 10 import os |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 189 | 189 |
| 190 def trim(self, min_free_space): | 190 def trim(self, min_free_space): |
| 191 """Purges cache. | 191 """Purges cache. |
| 192 | 192 |
| 193 Removes cache directories that were not accessed for a long time | 193 Removes cache directories that were not accessed for a long time |
| 194 until there is enough free space and the number of caches is sane. | 194 until there is enough free space and the number of caches is sane. |
| 195 | 195 |
| 196 If min_free_space is None, disk free space is not checked. | 196 If min_free_space is None, disk free space is not checked. |
| 197 | 197 |
| 198 Requires NamedCache to be open. | 198 Requires NamedCache to be open. |
| 199 |
| 200 Returns: |
| 201 Number of caches deleted. |
| 199 """ | 202 """ |
| 200 self._lock.assert_locked() | 203 self._lock.assert_locked() |
| 201 if not os.path.isdir(self.root_dir): | 204 if not os.path.isdir(self.root_dir): |
| 202 return | 205 return 0 |
| 203 | 206 |
| 207 total = 0 |
| 204 free_space = 0 | 208 free_space = 0 |
| 205 if min_free_space: | 209 if min_free_space: |
| 206 free_space = file_path.get_free_space(self.root_dir) | 210 free_space = file_path.get_free_space(self.root_dir) |
| 207 while ((min_free_space and free_space < min_free_space) | 211 while ((min_free_space and free_space < min_free_space) |
| 208 or len(self._lru) > MAX_CACHE_SIZE): | 212 or len(self._lru) > MAX_CACHE_SIZE): |
| 209 logging.info( | 213 logging.info( |
| 210 'Making space for named cache %s > %s or %s > %s', | 214 'Making space for named cache %s > %s or %s > %s', |
| 211 free_space, min_free_space, len(self._lru), MAX_CACHE_SIZE) | 215 free_space, min_free_space, len(self._lru), MAX_CACHE_SIZE) |
| 212 try: | 216 try: |
| 213 name, (path, _) = self._lru.get_oldest() | 217 name, (path, _) = self._lru.get_oldest() |
| 214 except KeyError: | 218 except KeyError: |
| 215 return | 219 return total |
| 216 named_dir = self._get_named_path(name) | 220 named_dir = self._get_named_path(name) |
| 217 if fs.islink(named_dir): | 221 if fs.islink(named_dir): |
| 218 fs.unlink(named_dir) | 222 fs.unlink(named_dir) |
| 219 path_abs = os.path.join(self.root_dir, path) | 223 path_abs = os.path.join(self.root_dir, path) |
| 220 if os.path.isdir(path_abs): | 224 if os.path.isdir(path_abs): |
| 221 logging.info('Removing named cache %s', path_abs) | 225 logging.info('Removing named cache %s', path_abs) |
| 222 file_path.rmtree(path_abs) | 226 file_path.rmtree(path_abs) |
| 223 if min_free_space: | 227 if min_free_space: |
| 224 free_space = file_path.get_free_space(self.root_dir) | 228 free_space = file_path.get_free_space(self.root_dir) |
| 225 self._lru.pop(name) | 229 self._lru.pop(name) |
| 230 total += 1 |
| 231 return total |
| 226 | 232 |
| 227 _DIR_ALPHABET = string.ascii_letters + string.digits | 233 _DIR_ALPHABET = string.ascii_letters + string.digits |
| 228 | 234 |
| 229 def _allocate_dir(self): | 235 def _allocate_dir(self): |
| 230 """Creates and returns relative path of a new cache directory.""" | 236 """Creates and returns relative path of a new cache directory.""" |
| 231 # We randomly generate directory names that have two lower/upper case | 237 # We randomly generate directory names that have two lower/upper case |
| 232 # letters or digits. Total number of possibilities is (26*2 + 10)^2 = 3844. | 238 # letters or digits. Total number of possibilities is (26*2 + 10)^2 = 3844. |
| 233 abc_len = len(self._DIR_ALPHABET) | 239 abc_len = len(self._DIR_ALPHABET) |
| 234 tried = set() | 240 tried = set() |
| 235 while len(tried) < 1000: | 241 while len(tried) < 1000: |
| (...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 281 if options.named_cache_root: | 287 if options.named_cache_root: |
| 282 return CacheManager(os.path.abspath(options.named_cache_root)) | 288 return CacheManager(os.path.abspath(options.named_cache_root)) |
| 283 return None | 289 return None |
| 284 | 290 |
| 285 | 291 |
| 286 def _validate_named_cache_path(path): | 292 def _validate_named_cache_path(path): |
| 287 if os.path.isabs(path): | 293 if os.path.isabs(path): |
| 288 raise Error('named cache path must not be absolute') | 294 raise Error('named cache path must not be absolute') |
| 289 if '..' in path.split(os.path.sep): | 295 if '..' in path.split(os.path.sep): |
| 290 raise Error('named cache path must not contain ".."') | 296 raise Error('named cache path must not contain ".."') |
| OLD | NEW |