+
+ @staticmethod
+ def cleanup_cachedir(cachedir, maxsize):
+ blocks = []
+ totalsize = 0
+ for root, dirs, files in os.walk(cachedir):
+ for name in files:
+ blockpath = os.path.join(root, name)
+ res = os.stat(blockpath)
+ blocks.append((blockpath, res.st_size, res.st_atime))
+ totalsize += res.st_size
+
+ if totalsize <= maxsize:
+ return
+
+ # sort by atime, so the blocks accessed the longest time in
+ # the past get deleted first.
+ blocks.sort(key=lambda x: x[2])
+
+ # go through the list and try deleting blocks until we're
+ # below the target size and/or we run out of blocks
+ i = 0
+ while i < len(blocks) and totalsize > maxsize:
+ try:
+ with open(blocks[i][0], "rb") as f:
+ # If we can't get an exclusive lock, it'll
+ # throw an error, that's fine and desirable,
+ # it means another process has a lock and we
+ # shouldn't delete the block.
+ fcntl.flock(f, fcntl.LOCK_EX | fcntl.LOCK_NB)
+ os.remove(block)
+ totalsize -= blocks[i][1]
+ except OSError:
+ pass
+ i += 1