Include the shipped setuptools
[pysize.git] / pysize / core / deletion.py
blob860ad819b257ae932f49826ecc41332bb2a4e66e
1 # This program is free software; you can redistribute it and/or modify
2 # it under the terms of the GNU General Public License as published by
3 # the Free Software Foundation; either version 2 of the License, or
4 # (at your option) any later version.
6 # This program is distributed in the hope that it will be useful,
7 # but WITHOUT ANY WARRANTY; without even the implied warranty of
8 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 # GNU Library General Public License for more details.
11 # You should have received a copy of the GNU General Public License
12 # along with this program; if not, write to the Free Software
13 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 # See the COPYING file for license information.
17 # Copyright (c) 2006, 2007 Guillaume Chazarain <guichaz@yahoo.fr>
19 import os
21 from pysize.core.pysize_global_fs_cache import get_dev_ino
23 # ['/path/to/file1', '/path/to/file2']
24 TO_DELETE = []
26 # {device: {inode: (size_to_subtract|DELETED)}}
27 DEV_INO_TO_SUBTRACT = {}
29 DELETED = 'deleted'
31 def _get_subtracted(path):
32 dev, ino = get_dev_ino(path)
33 return DEV_INO_TO_SUBTRACT.setdefault(dev, {}).get(ino, None)
35 def _iter_to_the_root(path):
36 while path not in ('/', ''):
37 yield get_dev_ino(path), path
38 path = os.path.dirname(path)
40 def get_subtracted(path):
41 if DEV_INO_TO_SUBTRACT:
42 for dev_ino, tmp_path in _iter_to_the_root(path):
43 if _get_subtracted(tmp_path) is DELETED:
44 return DELETED
45 subtracted = _get_subtracted(path)
46 if subtracted is not None:
47 return subtracted
48 return 0
50 def _add_hash(path):
51 from pysize.core import compute_size
52 size = compute_size.slow(path)
53 dev, ino = get_dev_ino(path)
54 DEV_INO_TO_SUBTRACT.setdefault(dev, {})[ino] = DELETED
55 for (dev, ino), path in _iter_to_the_root(os.path.dirname(path)):
56 inodes = DEV_INO_TO_SUBTRACT.setdefault(dev, {})
57 subtract = inodes.get(ino, 0)
58 subtract += size
59 inodes[ino] = subtract
61 # TODO: Deletion of hard links
62 def schedule(nodes):
63 for node in nodes:
64 for path in node.get_fullpaths():
65 subtract = get_subtracted(path)
66 if subtract is not DELETED:
67 TO_DELETE.append(path)
68 _add_hash(path)
69 _prune_list()
70 _rebuild_hash()
72 def _prune_list():
73 """Remove children if we have the parent"""
74 while True:
75 for i in xrange(len(TO_DELETE)):
76 parent = os.path.dirname(TO_DELETE[i])
77 if get_subtracted(parent) is DELETED:
78 del TO_DELETE[i]
79 break
80 else:
81 break
83 def _rebuild_hash():
84 DEV_INO_TO_SUBTRACT.clear()
85 for path in TO_DELETE:
86 _add_hash(path)
88 def filter_deleted(paths):
89 if DEV_INO_TO_SUBTRACT:
90 def is_not_deleted(path):
91 return get_subtracted(path) is not DELETED
92 return filter(is_not_deleted, paths)
93 return paths
95 def get_deleted():
96 return TO_DELETE[:]
98 def restore(path):
99 from pysize.core import compute_size
100 TO_DELETE.remove(path)
101 dev, ino = get_dev_ino(path)
102 del DEV_INO_TO_SUBTRACT[dev][ino]
103 size = compute_size.slow(path, account_deletion=False)
104 for (dev, ino), path in _iter_to_the_root(os.path.dirname(path)):
105 inodes = DEV_INO_TO_SUBTRACT[dev]
106 if inodes[ino] == size:
107 del inodes[ino]
108 else:
109 inodes[ino] -= size