Gentoo Archives: gentoo-commits

From: Zac Medico <zmedico@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/portage:master commit in: pym/portage/dbapi/, pym/portage/util/_dyn_libs/, pym/_emerge/
Date: Sat, 07 May 2011 03:03:13
Message-Id: f36b9fa38b5268c2a5579db62acec026625f84a9.zmedico@gentoo
1 commit: f36b9fa38b5268c2a5579db62acec026625f84a9
2 Author: David James <davidjames <AT> chromium <DOT> org>
3 AuthorDate: Thu May 5 21:08:27 2011 +0000
4 Commit: Zac Medico <zmedico <AT> gentoo <DOT> org>
5 CommitDate: Sat May 7 01:52:39 2011 +0000
6 URL: http://git.overlays.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=f36b9fa3
7
8 Cleanup preserved lib locking in portage.
9
10 This change makes preserved lib modification atomic, and
11 prepares us for narrowing the scope of the merge lock.
12
13 BUG=chromium-os:14983
14 TEST=Ran test suite and some example emerges.
15
16 Change-Id: I39abb6a5ec72be3274e508ef807ac1d9e69db1a8
17
18 Review URL: http://gerrit.chromium.org/gerrit/417
19
20 ---
21 pym/_emerge/actions.py | 7 -
22 pym/portage/dbapi/vartree.py | 199 ++++++++++----------
23 .../util/_dyn_libs/PreservedLibsRegistry.py | 32 ++--
24 3 files changed, 114 insertions(+), 124 deletions(-)
25
26 diff --git a/pym/_emerge/actions.py b/pym/_emerge/actions.py
27 index 6379b36..29ecb38 100644
28 --- a/pym/_emerge/actions.py
29 +++ b/pym/_emerge/actions.py
30 @@ -448,13 +448,6 @@ def action_build(settings, trees, mtimedb,
31 portage.writemsg_stdout(colorize("WARN", "WARNING:")
32 + " AUTOCLEAN is disabled. This can cause serious"
33 + " problems due to overlapping packages.\n")
34 - plib_registry = \
35 - trees[settings["ROOT"]]["vartree"].dbapi._plib_registry
36 - if plib_registry is None:
37 - # preserve-libs is entirely disabled
38 - pass
39 - else:
40 - plib_registry.pruneNonExisting()
41
42 return retval
43
44
45 diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py
46 index 08263d6..4170d3d 100644
47 --- a/pym/portage/dbapi/vartree.py
48 +++ b/pym/portage/dbapi/vartree.py
49 @@ -148,13 +148,9 @@ class vardbapi(dbapi):
50
51 self._plib_registry = None
52 if _ENABLE_PRESERVE_LIBS:
53 - try:
54 - self._plib_registry = PreservedLibsRegistry(self.root,
55 - os.path.join(self._eroot, PRIVATE_PATH,
56 - "preserved_libs_registry"))
57 - except PermissionDenied:
58 - # apparently this user isn't allowed to access PRIVATE_PATH
59 - pass
60 + self._plib_registry = PreservedLibsRegistry(self.root,
61 + os.path.join(self._eroot, PRIVATE_PATH,
62 + "preserved_libs_registry"))
63
64 self._linkmap = None
65 if _ENABLE_DYN_LINK_MAP:
66 @@ -1437,8 +1433,50 @@ class dblink(object):
67 self.contentscache = pkgfiles
68 return pkgfiles
69
70 + def _prune_plib_registry(self, unmerge=False, others_in_slot=[],
71 + needed=None):
72 + # remove preserved libraries that don't have any consumers left
73 + plib_registry = self.vartree.dbapi._plib_registry
74 + if plib_registry:
75 + plib_registry.lock()
76 + try:
77 + plib_registry.load()
78 +
79 + if unmerge:
80 + # self.mycpv is about to be unmerged, so we shouldn't pay
81 + # attention to its needs in the linkmap.
82 + exclude_pkgs = (self.mycpv,)
83 + else:
84 + exclude_pkgs = None
85 +
86 + self._linkmap_rebuild(exclude_pkgs=exclude_pkgs,
87 + include_file=needed)
88 +
89 + cpv_lib_map = self._find_unused_preserved_libs()
90 + if cpv_lib_map:
91 + self._remove_preserved_libs(cpv_lib_map)
92 + for cpv, removed in cpv_lib_map.items():
93 + if not self.vartree.dbapi.cpv_exists(cpv):
94 + for dblnk in others_in_slot:
95 + if dblnk.mycpv == cpv:
96 + # This one just got merged so it doesn't
97 + # register with cpv_exists() yet.
98 + self.vartree.dbapi.removeFromContents(
99 + dblnk, removed)
100 + break
101 + continue
102 + self.vartree.dbapi.removeFromContents(cpv, removed)
103 +
104 + if unmerge:
105 + plib_registry.unregister(self.mycpv, self.settings["SLOT"],
106 + self.vartree.dbapi.cpv_counter(self.mycpv))
107 +
108 + plib_registry.store()
109 + finally:
110 + plib_registry.unlock()
111 +
112 def unmerge(self, pkgfiles=None, trimworld=None, cleanup=True,
113 - ldpath_mtimes=None, others_in_slot=None):
114 + ldpath_mtimes=None, others_in_slot=None, needed=None):
115 """
116 Calls prerm
117 Unmerges a given package (CPV)
118 @@ -1456,6 +1494,8 @@ class dblink(object):
119 @type ldpath_mtimes: Dictionary
120 @param others_in_slot: all dblink instances in this slot, excluding self
121 @type others_in_slot: list
122 + @param needed: Filename containing libraries needed after unmerge.
123 + @type needed: String
124 @rtype: Integer
125 @returns:
126 1. os.EX_OK if everything went well.
127 @@ -1574,15 +1614,6 @@ class dblink(object):
128 self._unmerge_pkgfiles(pkgfiles, others_in_slot)
129 self._clear_contents_cache()
130
131 - # Remove the registration of preserved libs for this pkg instance
132 - plib_registry = self.vartree.dbapi._plib_registry
133 - if plib_registry is None:
134 - # preserve-libs is entirely disabled
135 - pass
136 - else:
137 - plib_registry.unregister(self.mycpv, self.settings["SLOT"],
138 - self.vartree.dbapi.cpv_counter(self.mycpv))
139 -
140 if myebuildpath:
141 ebuild_phase = "postrm"
142 phase = EbuildPhase(background=background,
143 @@ -1597,37 +1628,8 @@ class dblink(object):
144 showMessage(_("!!! FAILED postrm: %s\n") % retval,
145 level=logging.ERROR, noiselevel=-1)
146
147 - # Skip this if another package in the same slot has just been
148 - # merged on top of this package, since the other package has
149 - # already called LinkageMap.rebuild() and passed it's NEEDED file
150 - # in as an argument.
151 - if not others_in_slot:
152 - self._linkmap_rebuild(exclude_pkgs=(self.mycpv,))
153 -
154 - # remove preserved libraries that don't have any consumers left
155 - cpv_lib_map = self._find_unused_preserved_libs()
156 - if cpv_lib_map:
157 - self._remove_preserved_libs(cpv_lib_map)
158 - for cpv, removed in cpv_lib_map.items():
159 - if not self.vartree.dbapi.cpv_exists(cpv):
160 - for dblnk in others_in_slot:
161 - if dblnk.mycpv == cpv:
162 - # This one just got merged so it doesn't
163 - # register with cpv_exists() yet.
164 - self.vartree.dbapi.removeFromContents(
165 - dblnk, removed)
166 - break
167 - continue
168 - self.vartree.dbapi.removeFromContents(cpv, removed)
169 - else:
170 - # Prune any preserved libs that may have
171 - # been unmerged with this package.
172 - if plib_registry is None:
173 - # preserve-libs is entirely disabled
174 - pass
175 - else:
176 - plib_registry.pruneNonExisting()
177 -
178 + self._prune_plib_registry(unmerge=True,
179 + others_in_slot=others_in_slot, needed=needed)
180 finally:
181 self.vartree.dbapi._bump_mtime(self.mycpv)
182 if builddir_lock:
183 @@ -3268,15 +3270,22 @@ class dblink(object):
184 self._clear_contents_cache()
185
186 linkmap = self.vartree.dbapi._linkmap
187 - if linkmap is None:
188 - # preserve-libs is entirely disabled
189 + plib_registry = self.vartree.dbapi._plib_registry
190 + include_file = None
191 + if linkmap is None or plib_registry is None:
192 preserve_paths = None
193 else:
194 - self._linkmap_rebuild(include_file=os.path.join(inforoot,
195 - linkmap._needed_aux_key))
196 + plib_registry.lock()
197 + try:
198 + plib_registry.load()
199 + needed = os.path.join(inforoot, linkmap._needed_aux_key)
200 + self._linkmap_rebuild(include_file=needed)
201 +
202 + # Preserve old libs if they are still in use
203 + preserve_paths = self._find_libs_to_preserve()
204 + finally:
205 + plib_registry.unlock()
206
207 - # Preserve old libs if they are still in use
208 - preserve_paths = self._find_libs_to_preserve()
209 if preserve_paths:
210 self._add_preserve_libs_to_contents(preserve_paths)
211
212 @@ -3312,7 +3321,7 @@ class dblink(object):
213 dblnk.settings["REPLACED_BY_VERSION"] = portage.versions.cpv_getversion(self.mycpv)
214 dblnk.settings.backup_changes("REPLACED_BY_VERSION")
215 unmerge_rval = dblnk.unmerge(ldpath_mtimes=prev_mtimes,
216 - others_in_slot=others_in_slot)
217 + others_in_slot=others_in_slot, needed=needed)
218 dblnk.settings.pop("REPLACED_BY_VERSION", None)
219
220 if unmerge_rval == os.EX_OK:
221 @@ -3335,12 +3344,6 @@ class dblink(object):
222 self.delete()
223 _movefile(self.dbtmpdir, self.dbpkgdir, mysettings=self.settings)
224
225 - # keep track of the libs we preserved
226 - if self.vartree.dbapi._plib_registry is not None and \
227 - preserve_paths:
228 - self.vartree.dbapi._plib_registry.register(self.mycpv,
229 - slot, counter, sorted(preserve_paths))
230 -
231 # Check for file collisions with blocking packages
232 # and remove any colliding files from their CONTENTS
233 # since they now belong to this package.
234 @@ -3351,27 +3354,37 @@ class dblink(object):
235 self.vartree.dbapi.removeFromContents(blocker, iter(contents),
236 relative_paths=False)
237
238 - # Unregister any preserved libs that this package has overwritten
239 - # and update the contents of the packages that owned them.
240 plib_registry = self.vartree.dbapi._plib_registry
241 - if plib_registry is None:
242 - # preserve-libs is entirely disabled
243 - pass
244 - else:
245 - plib_dict = plib_registry.getPreservedLibs()
246 - for cpv, paths in plib_collisions.items():
247 - if cpv not in plib_dict:
248 - continue
249 - if cpv == self.mycpv:
250 - continue
251 - try:
252 - slot, counter = self.vartree.dbapi.aux_get(
253 - cpv, ["SLOT", "COUNTER"])
254 - except KeyError:
255 - continue
256 - remaining = [f for f in plib_dict[cpv] if f not in paths]
257 - plib_registry.register(cpv, slot, counter, remaining)
258 - self.vartree.dbapi.removeFromContents(cpv, paths)
259 + if plib_registry:
260 + plib_registry.lock()
261 + try:
262 + plib_registry.load()
263 +
264 + if preserve_paths:
265 + # keep track of the libs we preserved
266 + plib_registry.register(self.mycpv, slot, counter,
267 + sorted(preserve_paths))
268 +
269 + # Unregister any preserved libs that this package has overwritten
270 + # and update the contents of the packages that owned them.
271 + plib_dict = plib_registry.getPreservedLibs()
272 + for cpv, paths in plib_collisions.items():
273 + if cpv not in plib_dict:
274 + continue
275 + if cpv == self.mycpv:
276 + continue
277 + try:
278 + slot, counter = self.vartree.dbapi.aux_get(
279 + cpv, ["SLOT", "COUNTER"])
280 + except KeyError:
281 + continue
282 + remaining = [f for f in plib_dict[cpv] if f not in paths]
283 + plib_registry.register(cpv, slot, counter, remaining)
284 + self.vartree.dbapi.removeFromContents(cpv, paths)
285 +
286 + plib_registry.store()
287 + finally:
288 + plib_registry.unlock()
289
290 self.vartree.dbapi._add(self)
291 contents = self.getcontents()
292 @@ -3410,14 +3423,7 @@ class dblink(object):
293
294 # For gcc upgrades, preserved libs have to be removed after the
295 # the library path has been updated.
296 - self._linkmap_rebuild()
297 - cpv_lib_map = self._find_unused_preserved_libs()
298 - if cpv_lib_map:
299 - self._remove_preserved_libs(cpv_lib_map)
300 - for cpv, removed in cpv_lib_map.items():
301 - if not self.vartree.dbapi.cpv_exists(cpv):
302 - continue
303 - self.vartree.dbapi.removeFromContents(cpv, removed)
304 + self._prune_plib_registry()
305
306 return os.EX_OK
307
308 @@ -3839,14 +3845,6 @@ class dblink(object):
309 self.lockdb()
310 self.vartree.dbapi._bump_mtime(self.mycpv)
311 try:
312 - plib_registry = self.vartree.dbapi._plib_registry
313 - if plib_registry is None:
314 - # preserve-libs is entirely disabled
315 - pass
316 - else:
317 - plib_registry.load()
318 - plib_registry.pruneNonExisting()
319 -
320 retval = self.treewalk(mergeroot, myroot, inforoot, myebuild,
321 cleanup=cleanup, mydbapi=mydbapi, prev_mtimes=prev_mtimes)
322
323 @@ -4001,13 +3999,6 @@ def unmerge(cat, pkg, myroot=None, settings=None,
324 try:
325 mylink.lockdb()
326 if mylink.exists():
327 - plib_registry = vartree.dbapi._plib_registry
328 - if plib_registry is None:
329 - # preserve-libs is entirely disabled
330 - pass
331 - else:
332 - plib_registry.load()
333 - plib_registry.pruneNonExisting()
334 retval = mylink.unmerge(ldpath_mtimes=ldpath_mtimes)
335 if retval == os.EX_OK:
336 mylink.delete()
337
338 diff --git a/pym/portage/util/_dyn_libs/PreservedLibsRegistry.py b/pym/portage/util/_dyn_libs/PreservedLibsRegistry.py
339 index 0d0b57d..f3cbb33 100644
340 --- a/pym/portage/util/_dyn_libs/PreservedLibsRegistry.py
341 +++ b/pym/portage/util/_dyn_libs/PreservedLibsRegistry.py
342 @@ -18,23 +18,29 @@ from portage.localization import _
343 from portage.util import atomic_ofstream
344 from portage.util import writemsg_level
345 from portage.versions import cpv_getkey
346 +from portage.locks import lockfile, unlockfile
347
348 class PreservedLibsRegistry(object):
349 """ This class handles the tracking of preserved library objects """
350 - def __init__(self, root, filename, autocommit=True):
351 + def __init__(self, root, filename):
352 """
353 @param root: root used to check existence of paths in pruneNonExisting
354 @type root: String
355 @param filename: absolute path for saving the preserved libs records
356 @type filename: String
357 - @param autocommit: determines if the file is written after every update
358 - @type autocommit: Boolean
359 """
360 self._root = root
361 self._filename = filename
362 - self._autocommit = autocommit
363 - self.load()
364 - self.pruneNonExisting()
365 + self._data = None
366 + self._lock = None
367 +
368 + def lock(self):
369 + """Grab an exclusive lock on the preserved libs registry."""
370 + self._lock = lockfile(self._filename)
371 +
372 + def unlock(self):
373 + """Release our exclusive lock on the preserved libs registry."""
374 + unlockfile(self._lock)
375
376 def load(self):
377 """ Reload the registry data from file """
378 @@ -56,10 +62,10 @@ class PreservedLibsRegistry(object):
379 if self._data is None:
380 self._data = {}
381 self._data_orig = self._data.copy()
382 + self.pruneNonExisting()
383 +
384 def store(self):
385 - """ Store the registry data to file. No need to call this if autocommit
386 - was enabled.
387 - """
388 + """ Store the registry data to file """
389 if os.environ.get("SANDBOX_ON") == "1" or \
390 self._data == self._data_orig:
391 return
392 @@ -94,8 +100,6 @@ class PreservedLibsRegistry(object):
393 del self._data[cps]
394 elif len(paths) > 0:
395 self._data[cps] = (cpv, counter, paths)
396 - if self._autocommit:
397 - self.store()
398
399 def unregister(self, cpv, slot, counter):
400 """ Remove a previous registration of preserved objects for the given package.
401 @@ -119,11 +123,11 @@ class PreservedLibsRegistry(object):
402 self._data[cps] = (cpv, counter, paths)
403 else:
404 del self._data[cps]
405 - if self._autocommit:
406 - self.store()
407
408 def hasEntries(self):
409 """ Check if this registry contains any records. """
410 + if self._data is None:
411 + self.load()
412 return len(self._data) > 0
413
414 def getPreservedLibs(self):
415 @@ -131,6 +135,8 @@ class PreservedLibsRegistry(object):
416 @returns mapping of package instances to preserved objects
417 @rtype Dict cpv->list-of-paths
418 """
419 + if self._data is None:
420 + self.load()
421 rValue = {}
422 for cps in self._data:
423 rValue[self._data[cps][0]] = self._data[cps][2]