OLD | NEW |
1 # Copyright 1998-2010 Gentoo Foundation | 1 # Copyright 1998-2010 Gentoo Foundation |
2 # Distributed under the terms of the GNU General Public License v2 | 2 # Distributed under the terms of the GNU General Public License v2 |
3 | 3 |
4 import errno | 4 import errno |
5 import logging | 5 import logging |
6 | 6 |
7 try: | 7 try: |
8 import cPickle as pickle | 8 import cPickle as pickle |
9 except ImportError: | 9 except ImportError: |
10 import pickle | 10 import pickle |
11 | 11 |
12 from portage import os | 12 from portage import os |
13 from portage import _encodings | 13 from portage import _encodings |
14 from portage import _os_merge | 14 from portage import _os_merge |
15 from portage import _unicode_encode | 15 from portage import _unicode_encode |
16 from portage.exception import PermissionDenied | 16 from portage.exception import PermissionDenied |
17 from portage.localization import _ | 17 from portage.localization import _ |
18 from portage.util import atomic_ofstream | 18 from portage.util import atomic_ofstream |
19 from portage.util import writemsg_level | 19 from portage.util import writemsg_level |
20 from portage.versions import cpv_getkey | 20 from portage.versions import cpv_getkey |
| 21 from portage.locks import lockfile, unlockfile |
21 | 22 |
22 class PreservedLibsRegistry(object): | 23 class PreservedLibsRegistry(object): |
23 """ This class handles the tracking of preserved library objects """ | 24 """ This class handles the tracking of preserved library objects """ |
24 » def __init__(self, root, filename, autocommit=True): | 25 » def __init__(self, root, filename): |
25 """ | 26 """ |
26 @param root: root used to check existence of paths in pr
uneNonExisting | 27 @param root: root used to check existence of paths in pr
uneNonExisting |
27 @type root: String | 28 @type root: String |
28 @param filename: absolute path for saving the preserved
libs records | 29 @param filename: absolute path for saving the preserved
libs records |
29 @type filename: String | 30 @type filename: String |
30 @param autocommit: determines if the file is written aft
er every update | |
31 @type autocommit: Boolean | |
32 """ | 31 """ |
33 self._root = root | 32 self._root = root |
34 self._filename = filename | 33 self._filename = filename |
35 » » self._autocommit = autocommit | 34 » » self._data = None |
36 » » self.load() | 35 » » self._lock = None |
37 » » self.pruneNonExisting() | 36 |
| 37 » def lock(self): |
| 38 » » """Grab an exclusive lock on the preserved libs registry.""" |
| 39 » » self._lock = lockfile(self._filename) |
| 40 |
| 41 » def unlock(self): |
| 42 » » """Release our exclusive lock on the preserved libs registry.""" |
| 43 » » unlockfile(self._lock) |
38 | 44 |
39 def load(self): | 45 def load(self): |
40 """ Reload the registry data from file """ | 46 """ Reload the registry data from file """ |
41 self._data = None | 47 self._data = None |
42 try: | 48 try: |
43 self._data = pickle.load( | 49 self._data = pickle.load( |
44 open(_unicode_encode(self._filename, | 50 open(_unicode_encode(self._filename, |
45 encoding=_encodings['fs'], errors='stric
t'), 'rb')) | 51 encoding=_encodings['fs'], errors='stric
t'), 'rb')) |
46 except (ValueError, pickle.UnpicklingError) as e: | 52 except (ValueError, pickle.UnpicklingError) as e: |
47 writemsg_level(_("!!! Error loading '%s': %s\n") % \ | 53 writemsg_level(_("!!! Error loading '%s': %s\n") % \ |
48 (self._filename, e), level=logging.ERROR, noisel
evel=-1) | 54 (self._filename, e), level=logging.ERROR, noisel
evel=-1) |
49 except (EOFError, IOError) as e: | 55 except (EOFError, IOError) as e: |
50 if isinstance(e, EOFError) or e.errno == errno.ENOENT: | 56 if isinstance(e, EOFError) or e.errno == errno.ENOENT: |
51 pass | 57 pass |
52 elif e.errno == PermissionDenied.errno: | 58 elif e.errno == PermissionDenied.errno: |
53 » » » » raise PermissionDenied(self._filename) | 59 » » » » pass |
54 else: | 60 else: |
55 raise | 61 raise |
56 if self._data is None: | 62 if self._data is None: |
57 self._data = {} | 63 self._data = {} |
58 self._data_orig = self._data.copy() | 64 self._data_orig = self._data.copy() |
| 65 self.pruneNonExisting() |
| 66 |
59 def store(self): | 67 def store(self): |
60 » » """ Store the registry data to file. No need to call this if aut
ocommit | 68 » » """ Store the registry data to file """ |
61 » » was enabled. | |
62 » » """ | |
63 if os.environ.get("SANDBOX_ON") == "1" or \ | 69 if os.environ.get("SANDBOX_ON") == "1" or \ |
64 self._data == self._data_orig: | 70 self._data == self._data_orig: |
65 return | 71 return |
66 try: | 72 try: |
67 f = atomic_ofstream(self._filename, 'wb') | 73 f = atomic_ofstream(self._filename, 'wb') |
68 pickle.dump(self._data, f, protocol=2) | 74 pickle.dump(self._data, f, protocol=2) |
69 f.close() | 75 f.close() |
70 except EnvironmentError as e: | 76 except EnvironmentError as e: |
71 if e.errno != PermissionDenied.errno: | 77 if e.errno != PermissionDenied.errno: |
72 writemsg_level("!!! %s %s\n" % (e, self._filenam
e), | 78 writemsg_level("!!! %s %s\n" % (e, self._filenam
e), |
(...skipping 14 matching lines...) Expand all Loading... |
87 @param paths: absolute paths of objects that got preserv
ed during an update | 93 @param paths: absolute paths of objects that got preserv
ed during an update |
88 @type paths: List | 94 @type paths: List |
89 """ | 95 """ |
90 cp = cpv_getkey(cpv) | 96 cp = cpv_getkey(cpv) |
91 cps = cp+":"+slot | 97 cps = cp+":"+slot |
92 if len(paths) == 0 and cps in self._data \ | 98 if len(paths) == 0 and cps in self._data \ |
93 and self._data[cps][0] == cpv and int(self._data
[cps][1]) == int(counter): | 99 and self._data[cps][0] == cpv and int(self._data
[cps][1]) == int(counter): |
94 del self._data[cps] | 100 del self._data[cps] |
95 elif len(paths) > 0: | 101 elif len(paths) > 0: |
96 self._data[cps] = (cpv, counter, paths) | 102 self._data[cps] = (cpv, counter, paths) |
97 if self._autocommit: | |
98 self.store() | |
99 | 103 |
100 def unregister(self, cpv, slot, counter): | 104 def unregister(self, cpv, slot, counter): |
101 """ Remove a previous registration of preserved objects for the
given package. | 105 """ Remove a previous registration of preserved objects for the
given package. |
102 @param cpv: package instance whose records should be rem
oved | 106 @param cpv: package instance whose records should be rem
oved |
103 @type cpv: CPV (as String) | 107 @type cpv: CPV (as String) |
104 @param slot: the value of SLOT of the given package inst
ance | 108 @param slot: the value of SLOT of the given package inst
ance |
105 @type slot: String | 109 @type slot: String |
106 """ | 110 """ |
107 self.register(cpv, slot, counter, []) | 111 self.register(cpv, slot, counter, []) |
108 | 112 |
109 def pruneNonExisting(self): | 113 def pruneNonExisting(self): |
110 """ Remove all records for objects that no longer exist on the f
ilesystem. """ | 114 """ Remove all records for objects that no longer exist on the f
ilesystem. """ |
111 | 115 |
112 os = _os_merge | 116 os = _os_merge |
113 | 117 |
114 for cps in list(self._data): | 118 for cps in list(self._data): |
115 cpv, counter, paths = self._data[cps] | 119 cpv, counter, paths = self._data[cps] |
116 paths = [f for f in paths \ | 120 paths = [f for f in paths \ |
117 if os.path.exists(os.path.join(self._root, f.lst
rip(os.sep)))] | 121 if os.path.exists(os.path.join(self._root, f.lst
rip(os.sep)))] |
118 if len(paths) > 0: | 122 if len(paths) > 0: |
119 self._data[cps] = (cpv, counter, paths) | 123 self._data[cps] = (cpv, counter, paths) |
120 else: | 124 else: |
121 del self._data[cps] | 125 del self._data[cps] |
122 if self._autocommit: | |
123 self.store() | |
124 | 126 |
125 def hasEntries(self): | 127 def hasEntries(self): |
126 """ Check if this registry contains any records. """ | 128 """ Check if this registry contains any records. """ |
| 129 if self._data is None: |
| 130 self.load() |
127 return len(self._data) > 0 | 131 return len(self._data) > 0 |
128 | 132 |
129 def getPreservedLibs(self): | 133 def getPreservedLibs(self): |
130 """ Return a mapping of packages->preserved objects. | 134 """ Return a mapping of packages->preserved objects. |
131 @returns mapping of package instances to preserved objec
ts | 135 @returns mapping of package instances to preserved objec
ts |
132 @rtype Dict cpv->list-of-paths | 136 @rtype Dict cpv->list-of-paths |
133 """ | 137 """ |
| 138 if self._data is None: |
| 139 self.load() |
134 rValue = {} | 140 rValue = {} |
135 for cps in self._data: | 141 for cps in self._data: |
136 rValue[self._data[cps][0]] = self._data[cps][2] | 142 rValue[self._data[cps][0]] = self._data[cps][2] |
137 return rValue | 143 return rValue |
OLD | NEW |