summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2007-06-13 05:16:00 +0000
committerZac Medico <zmedico@gentoo.org>2007-06-13 05:16:00 +0000
commit508b26fefac889837c98557b2b2e1b43647b9714 (patch)
treeb9e3117e0ded6e4ec7ccabe5ad9c70f8fa768210
parent050aae0a2fe7477ba8181e9d8144fe51f1b0b3c4 (diff)
downloadportage-508b26fefac889837c98557b2b2e1b43647b9714.tar.gz
portage-508b26fefac889837c98557b2b2e1b43647b9714.tar.bz2
portage-508b26fefac889837c98557b2b2e1b43647b9714.zip
Cache dblink instances for security checks and reference counts during merge/unmerge so that each CONTENTS only has to be parsed once. These can also be reused for collision-protect.
svn path=/main/trunk/; revision=6823
-rw-r--r--pym/portage/dbapi/vartree.py98
1 files changed, 53 insertions, 45 deletions
diff --git a/pym/portage/dbapi/vartree.py b/pym/portage/dbapi/vartree.py
index 855310608..d1f46bc45 100644
--- a/pym/portage/dbapi/vartree.py
+++ b/pym/portage/dbapi/vartree.py
@@ -975,7 +975,7 @@ class dblink(object):
return pkgfiles
def unmerge(self, pkgfiles=None, trimworld=1, cleanup=1,
- ldpath_mtimes=None, new_contents=None):
+ ldpath_mtimes=None, others_in_slot=None):
"""
Calls prerm
Unmerges a given package (CPV)
@@ -991,8 +991,8 @@ class dblink(object):
@type cleanup: Boolean
@param ldpath_mtimes: mtimes to pass to env_update (see env_update)
@type ldpath_mtimes: Dictionary
- @param new_contents: contents from a new instance that will replace this one
- @type new_contents: Dictionary
+ @param others_in_slot: all dblink instances in this slot, excluding self
+ @type others_in_slot: list
@rtype: Integer
@returns:
1. os.EX_OK if everything went well.
@@ -1003,14 +1003,20 @@ class dblink(object):
before and after this method.
"""
- # When new_contents is supplied, the security check has already been
+ # When others_in_slot is supplied, the security check has already been
# done for this slot, so it shouldn't be repeated until the next
# replacement or unmerge operation.
- if new_contents is None:
+ if others_in_slot is None:
slot = self.vartree.dbapi.aux_get(self.mycpv, ["SLOT"])[0]
slot_matches = self.vartree.dbapi.match(
"%s:%s" % (dep_getkey(self.mycpv), slot))
- retval = self._security_check(slot_matches)
+ others_in_slot = []
+ for cur_cpv in slot_matches:
+ if cur_cpv == self.mycpv:
+ continue
+ others_in_slot.append(dblink(self.cat, catsplit(cur_cpv)[1],
+ self.vartree.root, self.settings, vartree=self.vartree))
+ retval = self._security_check([self] + others_in_slot)
if retval:
return retval
@@ -1067,7 +1073,7 @@ class dblink(object):
writemsg("!!! FAILED prerm: %s\n" % retval, noiselevel=-1)
return retval
- self._unmerge_pkgfiles(pkgfiles, new_contents=new_contents)
+ self._unmerge_pkgfiles(pkgfiles, others_in_slot)
# Remove the registration of preserved libs for this pkg instance
self.vartree.dbapi.plib_registry.unregister(self.mycpv, self.settings["SLOT"], self.settings["COUNTER"])
@@ -1112,7 +1118,7 @@ class dblink(object):
contents=contents, env=self.settings.environ())
return os.EX_OK
- def _unmerge_pkgfiles(self, pkgfiles, new_contents=None):
+ def _unmerge_pkgfiles(self, pkgfiles, others_in_slot):
"""
Unmerges the contents of a package from the liveFS
@@ -1120,8 +1126,8 @@ class dblink(object):
@param pkgfiles: typically self.getcontents()
@type pkgfiles: Dictionary { filename: [ 'type', '?', 'md5sum' ] }
- @param new_contents: contents from a new instance that will replace this one
- @type new_contents: Dictionary
+ @param others_in_slot: all dblink instances in this slot, excluding self
+ @type others_in_slot: list
@rtype: None
"""
@@ -1129,21 +1135,20 @@ class dblink(object):
writemsg_stdout("No package files given... Grabbing a set.\n")
pkgfiles = self.getcontents()
- counter = self.vartree.dbapi.cpv_counter(self.mycpv)
- slot = self.vartree.dbapi.aux_get(self.mycpv, ["SLOT"])[0]
- slot_matches = self.vartree.dbapi.match(
- "%s:%s" % (dep_getkey(self.mycpv), slot))
+ if others_in_slot is None:
+ others_in_slot = []
+ slot = self.vartree.dbapi.aux_get(self.mycpv, ["SLOT"])[0]
+ slot_matches = self.vartree.dbapi.match(
+ "%s:%s" % (dep_getkey(self.mycpv), slot))
+ for cur_cpv in slot_matches:
+ if cur_cpv == self.mycpv:
+ continue
+ others_in_slot.append(dblink(self.cat, catsplit(cur_cpv)[1],
+ self.vartree.root, self.settings,
+ vartree=self.vartree))
claimed_paths = set()
- if new_contents:
- claimed_paths.update(new_contents)
- for cur_cpv in slot_matches:
- cur_counter = self.vartree.dbapi.cpv_counter(cur_cpv)
- if cur_counter == counter and \
- cur_cpv == self.mycpv:
- continue
- claimed_paths.update(dblink(self.cat, catsplit(cur_cpv)[1],
- self.vartree.root, self.settings,
- vartree=self.vartree).getcontents())
+ for dblnk in others_in_slot:
+ claimed_paths.update(dblnk.getcontents())
if pkgfiles:
mykeys = pkgfiles.keys()
@@ -1465,14 +1470,12 @@ class dblink(object):
except OSError:
pass
- def _security_check(self, slot_matches):
- if not slot_matches:
+ def _security_check(self, installed_instances):
+ if not installed_instances:
return 0
file_paths = set()
- for cpv in slot_matches:
- file_paths.update(dblink(self.cat, catsplit(cpv)[1],
- self.vartree.root, self.settings,
- vartree=self.vartree).getcontents())
+ for dblnk in installed_instances:
+ file_paths.update(dblnk.getcontents())
inode_map = {}
for path in file_paths:
try:
@@ -1556,23 +1559,25 @@ class dblink(object):
slot_matches = self.vartree.dbapi.match(
"%s:%s" % (self.mysplit[0], self.settings["SLOT"]))
- retval = self._security_check(slot_matches)
+ others_in_slot = []
+ for cur_cpv in slot_matches:
+ others_in_slot.append(dblink(self.cat, catsplit(cur_cpv)[1],
+ self.vartree.root, self.settings,
+ vartree=self.vartree))
+ retval = self._security_check(others_in_slot)
if retval:
return retval
if slot_matches:
# Used by self.isprotected().
- max_cpv = None
+ max_dblnk = None
max_counter = -1
- for cur_cpv in slot_matches:
- cur_counter = self.vartree.dbapi.cpv_counter(cur_cpv)
+ for dblnk in others_in_slot:
+ cur_counter = self.vartree.dbapi.cpv_counter(dblnk.mycpv)
if cur_counter > max_counter:
max_counter = cur_counter
- max_cpv = cur_cpv
- slot_matches = [max_cpv]
- self._installed_instance = dblink(self.cat,
- catsplit(slot_matches[0])[1], destroot, self.settings,
- vartree=self.vartree)
+ max_dblnk = dblnk
+ self._installed_instance = max_dblnk
# get current counter value (counter_tick also takes care of incrementing it)
# XXX Need to make this destroot, but it needs to be initialized first. XXX
@@ -1696,15 +1701,18 @@ class dblink(object):
#if we opened it, close it
outfile.flush()
outfile.close()
- self.contentscache = None
- new_contents = self.getcontents()
- if os.path.exists(self.dbpkgdir):
+ for dblnk in others_in_slot:
+ if dblnk.mycpv != self.mycpv:
+ continue
writemsg_stdout(">>> Safely unmerging already-installed instance...\n")
- dblink(self.cat, self.pkg, destroot, self.settings,
- vartree=self.vartree).unmerge(trimworld=0,
- ldpath_mtimes=prev_mtimes, new_contents=new_contents)
+ self.contentscache = None
+ others_in_slot.append(self) # self has just been merged
+ others_in_slot.remove(dblnk) # dblnk will unmerge itself now
+ dblnk.unmerge(trimworld=0, ldpath_mtimes=prev_mtimes,
+ others_in_slot=others_in_slot)
writemsg_stdout(">>> Original instance of package unmerged safely.\n")
+ break
# We hold both directory locks.
self.dbdir = self.dbpkgdir