Implement a file cache which lives inside the main emscripten cache directory. The defference here is that we use a per-file lock rather than a cache-wide lock. The cache is pruned (by removing the oldest files) if it grows above a certain number of files.
(filetype, filename, generator, cache_limit)
| 298 | |
| 299 | |
| 300 | def get_cached_file(filetype, filename, generator, cache_limit): |
| 301 | """Implement a file cache which lives inside the main emscripten cache directory. |
| 302 | |
| 303 | The defference here is that we use a per-file lock rather than a cache-wide lock. |
| 304 | |
| 305 | The cache is pruned (by removing the oldest files) if it grows above |
| 306 | a certain number of files. |
| 307 | """ |
| 308 | root = cache.get_path(filetype) |
| 309 | utils.safe_ensure_dirs(root) |
| 310 | |
| 311 | cache_file = os.path.join(root, filename) |
| 312 | |
| 313 | with filelock.FileLock(cache_file + '.lock'): |
| 314 | if os.path.exists(cache_file): |
| 315 | # Cache hit, read the file |
| 316 | file_content = utils.read_file(cache_file) |
| 317 | else: |
| 318 | # Cache miss, generate the symbol list and write the file |
| 319 | file_content = generator() |
| 320 | utils.write_file(cache_file, file_content) |
| 321 | |
| 322 | if len([f for f in os.listdir(root) if not f.endswith('.lock')]) > cache_limit: |
| 323 | with filelock.FileLock(cache.get_path(f'{filetype}.lock')): |
| 324 | files = [] |
| 325 | for f in os.listdir(root): |
| 326 | if not f.endswith('.lock'): |
| 327 | f = os.path.join(root, f) |
| 328 | files.append((f, os.path.getmtime(f))) |
| 329 | files.sort(key=lambda x: x[1]) |
| 330 | # Delete all but the newest N files |
| 331 | for f, _ in files[:-cache_limit]: |
| 332 | with filelock.FileLock(f + '.lock'): |
| 333 | utils.delete_file(f) |
| 334 | |
| 335 | return file_content |
| 336 | |
| 337 | |
| 338 | @ToolchainProfiler.profile() |
no test coverage detected