Return a copy to allow suppressing elements while iterating
[pysize.git] / pysize / core / deletion.py
blob3cddb4b54bc6a671a2602f2de84de91d77b49978
1 import os
3 from pysize.core.pysize_global_fs_cache import get_dev_ino
5 # ['/path/to/file1', '/path/to/file2']
6 TO_DELETE = []
8 # {device: {inode: (size_to_subtract|DELETED)}}
9 DEV_INO_TO_SUBTRACT = {}
11 DELETED = 'deleted'
13 def _get_subtracted(path):
14 dev, ino = get_dev_ino(path)
15 return DEV_INO_TO_SUBTRACT.setdefault(dev, {}).get(ino, None)
17 def _iter_to_the_root(path):
18 while path not in ('/', ''):
19 yield get_dev_ino(path), path
20 path = os.path.dirname(path)
22 def get_subtracted(path):
23 if DEV_INO_TO_SUBTRACT:
24 for dev_ino, tmp_path in _iter_to_the_root(path):
25 if _get_subtracted(tmp_path) is DELETED:
26 return DELETED
27 subtracted = _get_subtracted(path)
28 if subtracted is not None:
29 return subtracted
30 return 0
32 def _add_hash(path):
33 from pysize.core import compute_size
34 size = compute_size.slow(path)
35 dev, ino = get_dev_ino(path)
36 DEV_INO_TO_SUBTRACT.setdefault(dev, {})[ino] = DELETED
37 for (dev, ino), path in _iter_to_the_root(os.path.dirname(path)):
38 inodes = DEV_INO_TO_SUBTRACT.setdefault(dev, {})
39 subtract = inodes.get(ino, 0)
40 subtract += size
41 inodes[ino] = subtract
43 # TODO: Deletion of hard links
44 def schedule(nodes):
45 for node in nodes:
46 for path in node.get_fullpaths():
47 subtract = get_subtracted(path)
48 if subtract is not DELETED:
49 TO_DELETE.append(path)
50 _add_hash(path)
51 _prune_list()
52 _rebuild_hash()
54 def _prune_list():
55 """Remove children if we have the parent"""
56 while True:
57 for i in xrange(len(TO_DELETE)):
58 parent = os.path.dirname(TO_DELETE[i])
59 if get_subtracted(parent) is DELETED:
60 del TO_DELETE[i]
61 break
62 else:
63 break
65 def _rebuild_hash():
66 DEV_INO_TO_SUBTRACT.clear()
67 for path in TO_DELETE:
68 _add_hash(path)
70 def filter_deleted(paths):
71 if DEV_INO_TO_SUBTRACT:
72 def is_not_deleted(path):
73 return get_subtracted(path) is not DELETED
74 return filter(is_not_deleted, paths)
75 return paths
77 def get_deleted():
78 return TO_DELETE[:]
80 def restore(path):
81 from pysize.core import compute_size
82 TO_DELETE.remove(path)
83 dev, ino = get_dev_ino(path)
84 del DEV_INO_TO_SUBTRACT[dev][ino]
85 size = compute_size.slow(path, account_deletion=False)
86 for (dev, ino), path in _iter_to_the_root(os.path.dirname(path)):
87 inodes = DEV_INO_TO_SUBTRACT[dev]
88 if inodes[ino] == size:
89 del inodes[ino]
90 else:
91 inodes[ino] -= size