3 # The cache for directories sizes
4 # {device: {directory_inode: 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
18 def get_dev_ino(path
):
19 """Return (device_number, inode) for path."""
21 return (st
.st_dev
, st
.st_ino
)
23 def _get_inodes(table
, dev
):
24 inodes
= table
.get(dev
, None)
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
)
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)
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)
51 return inodes
.get(ino
, None)