# Copyright 2024 The Chromium Authors # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. """ An AbstractContextManager to wait the modifications to finish during exit. """ import os import time from contextlib import AbstractContextManager class ModificationWaiter(AbstractContextManager): """ Exits if there is no modifications for a certain time period, or the timeout has been reached. """ def __init__(self, path: str) -> None: self._path = path # Waits at most 60 seconds. self._timeout = 60 # Exits early if no modification happened during last 5 seconds. self._quiet_time = 5 def __enter__(self) -> None: # Do nothing, the logic happens in __exit__ return def __exit__(self, exc_type, exc_value, traceback) -> bool: # The default log.dir is /tmp and it's not a good idea to monitor it. if not self._path: return False # Always consider the last modification happening now to avoid an # unexpected early return. last_mod_time = time.time() start_time = last_mod_time while True: cur_time = time.time() if cur_time - start_time >= self._timeout: break cur_mod_time = os.path.getmtime(self._path) if cur_mod_time > last_mod_time: last_mod_time = cur_mod_time elif cur_time - last_mod_time >= self._quiet_time: break time.sleep(1) # Do not suppress exceptions. return False