diff options
Diffstat (limited to 'third_party/python/dlmanager/dlmanager/persist_limit.py')
-rw-r--r-- | third_party/python/dlmanager/dlmanager/persist_limit.py | 65 |
1 files changed, 65 insertions, 0 deletions
diff --git a/third_party/python/dlmanager/dlmanager/persist_limit.py b/third_party/python/dlmanager/dlmanager/persist_limit.py new file mode 100644 index 0000000000..03a1829f70 --- /dev/null +++ b/third_party/python/dlmanager/dlmanager/persist_limit.py @@ -0,0 +1,65 @@ +import os +import stat + +from collections import namedtuple +from glob import glob + +from dlmanager import fs + + +File = namedtuple('File', ('path', 'stat')) + + +class PersistLimit(object): + """ + Keep a list of files, removing the oldest ones when the size_limit + is reached. + + The access time of a file is used to determine the oldests, e.g. the + last time a file was read. + + :param size_limit: the size limit in bytes. A value of 0 means no limit. + :param file_limit: even if the size limit is reached, this force + to keep at least *file_limit* files. + """ + def __init__(self, size_limit, file_limit=5): + self.size_limit = size_limit + self.file_limit = file_limit + self.files = [] + self._files_size = 0 + + def register_file(self, path): + """ + register a single file. + """ + try: + fstat = os.stat(path) + except OSError: + # file do not exists probably, just skip it + # note this happen when backgound files are canceled + return + if stat.S_ISREG(fstat.st_mode): + self.files.append(File(path=path, stat=fstat)) + self._files_size += fstat.st_size + + def register_dir_content(self, directory, pattern="*"): + """ + Register every files in a directory that match *pattern*. + """ + for path in glob(os.path.join(directory, pattern)): + self.register_file(path) + + def remove_old_files(self): + """ + remove oldest registered files. + """ + if self.size_limit <= 0 or self.file_limit <= 0: + return + # sort by creation time, oldest first + files = sorted(self.files, key=lambda f: f.stat.st_atime) + while len(files) > self.file_limit and \ + self._files_size >= self.size_limit: + f = files.pop(0) + fs.remove(f.path) + self._files_size -= f.stat.st_size + self.files = files |