set_sensitive() on Back and Forward when needed
[pysize.git] / pysize / core / pysize_global_fs_cache.py
blobce170a7ba4cf455f310f603271041b38a6d6a8a8
1 import os
3 # The cache for directories sizes
4 # {device: {directory_inode: size}}
5 DEV_DIR_SIZE = {}
7 # The cache for hardlinks locations
8 # {device: {hardlink_inode: (directory_inode, basename)}}
9 # For memory efficiency reasons, we suppose directory_inode lives
10 # in the same device as hardlink_inode, but this can be defeated with
11 # mount --bind on files. So if we have the same hardlink device/inode
12 # in two directories with the same inode on different devices, we may
13 # count both instances as canonical, and then counting many times the
14 # hardlink size. But this is very unlikely, unless on purpose, but then
15 # you get what you deserve :-p
16 DEV_HLINK_DNAME = {}
18 def get_dev_ino(path):
19 """Return (device_number, inode) for path."""
20 st = os.lstat(path)
21 return (st.st_dev, st.st_ino)
23 def _get_inodes(table, dev):
24 inodes = table.get(dev, None)
25 if not inodes:
26 inodes = {}
27 table[dev] = inodes
28 return inodes
30 def cache_add_dir((dev, ino), size):
31 """Add a directory and its size to the cache."""
32 inodes = _get_inodes(DEV_DIR_SIZE, dev)
33 inodes[ino] = size
35 def cache_add_hardlink(dev, ino, dir_ino, basename):
36 """Add a hardlink and its location to the cache, and returns True iff the
37 location should be considered as the canonical location. Unlike for the
38 canonical location, a hardlink size is 0."""
39 entry = (dir_ino, basename)
40 inodes = _get_inodes(DEV_HLINK_DNAME, dev)
41 cached_entry = inodes.get(ino, None)
42 if not cached_entry:
43 inodes[ino] = entry
44 return True
45 return cached_entry == entry
47 def cache_get_dir_size((dev, ino)):
48 """Retrieve a directory size from the cache."""
49 inodes = DEV_DIR_SIZE.get(dev, None)
50 if inodes:
51 return inodes.get(ino, None)
53 def drop_caches():
54 DEV_DIR_SIZE.clear()
55 DEV_HLINK_DNAME.clear()