summaryrefslogtreecommitdiffstats
path: root/pym/portage
diff options
context:
space:
mode:
authorZac Medico <zmedico@gentoo.org>2008-07-10 15:00:17 +0000
committerZac Medico <zmedico@gentoo.org>2008-07-10 15:00:17 +0000
commit8bcd4a33e914f362cec4b7421c019a0969aa7276 (patch)
tree4b796f42a93b56a6e1210b86b68b36a8106b3f77 /pym/portage
parent84d0df9bcd2ad92d5c06ada47e608841c9fd3659 (diff)
downloadportage-8bcd4a33e914f362cec4b7421c019a0969aa7276.tar.gz
portage-8bcd4a33e914f362cec4b7421c019a0969aa7276.tar.bz2
portage-8bcd4a33e914f362cec4b7421c019a0969aa7276.zip
Add support for parallel --regen, using the existing --jobs and --load-average
options: * Split out a PollLoop base class from Scheduler and derive a MetadataRegen class to handle parallel scheduling for --regen. * Add pordbapi._metadata_process() and _metadata_callback() methods to implement asynchronous metadata generation. One method returns an EbuildMetadataPhase instance to encapsulate the async task. The other method is called to save the metadata when the process completes successfully. These methods share code with aux_get to avoid duplicate code. svn path=/main/trunk/; revision=11012
Diffstat (limited to 'pym/portage')
-rw-r--r--pym/portage/__init__.py7
-rw-r--r--pym/portage/dbapi/porttree.py168
2 files changed, 108 insertions, 67 deletions
diff --git a/pym/portage/__init__.py b/pym/portage/__init__.py
index bd800b4e2..453096f67 100644
--- a/pym/portage/__init__.py
+++ b/pym/portage/__init__.py
@@ -5011,7 +5011,12 @@ def doebuild(myebuild, mydo, myroot, mysettings, debug=0, listonly=0,
if mydo == "depend":
writemsg("!!! DEBUG: dbkey: %s\n" % str(dbkey), 2)
droppriv = "userpriv" in mysettings.features
- if isinstance(dbkey, dict):
+ if returnpid:
+ mypids = spawn(_shell_quote(ebuild_sh_binary) + " depend",
+ mysettings, fd_pipes=fd_pipes, returnpid=True,
+ droppriv=droppriv)
+ return mypids
+ elif isinstance(dbkey, dict):
mysettings["dbkey"] = ""
pr, pw = os.pipe()
fd_pipes = {
diff --git a/pym/portage/dbapi/porttree.py b/pym/portage/dbapi/porttree.py
index dd8015cc1..797c886f2 100644
--- a/pym/portage/dbapi/porttree.py
+++ b/pym/portage/dbapi/porttree.py
@@ -229,6 +229,104 @@ class portdbapi(dbapi):
return[file, x]
return None, 0
+ def _metadata_process(self, cpv, ebuild_path, repo_path):
+ """
+ Create an EbuildMetadataPhase instance to generate metadata for the
+ give ebuild.
+ @rtype: EbuildMetadataPhase
+ @returns: A new EbuildMetadataPhase instance, or None if the
+ metadata cache is already valid.
+ """
+ metadata, st, emtime = self._pull_valid_cache(cpv, ebuild_path, repo_path)
+ if metadata is not None:
+ return None
+
+ import _emerge
+ process = _emerge.EbuildMetadataPhase(cpv=cpv, ebuild_path=ebuild_path,
+ ebuild_mtime=emtime, metadata_callback=self._metadata_callback,
+ portdb=self, repo_path=repo_path, settings=self.doebuild_settings)
+ return process
+
+ def _metadata_callback(self, cpv, ebuild_path, repo_path, metadata, mtime):
+
+ i = metadata
+ if hasattr(metadata, "iteritems"):
+ i = metadata.iteritems()
+ metadata = dict(i)
+
+ if "EAPI" not in metadata or not metadata["EAPI"].strip():
+ metadata["EAPI"] = "0"
+
+ if not eapi_is_supported(metadata["EAPI"]):
+ # if newer version, wipe everything and negate eapi
+ eapi = metadata["EAPI"]
+ metadata = {}
+ map(lambda x: metadata.setdefault(x, ""), auxdbkeys)
+ metadata["EAPI"] = "-" + eapi
+
+ if metadata.get("INHERITED", False):
+ metadata["_eclasses_"] = \
+ self.eclassdb.get_eclass_data(metadata["INHERITED"].split())
+ else:
+ metadata["_eclasses_"] = {}
+
+ metadata.pop("INHERITED", None)
+ metadata["_mtime_"] = mtime
+ self.auxdb[repo_path][cpv] = metadata
+
+ def _pull_valid_cache(self, cpv, ebuild_path, repo_path):
+
+ try:
+ st = os.stat(ebuild_path)
+ emtime = st[stat.ST_MTIME]
+ except OSError:
+ writemsg("!!! aux_get(): ebuild for " + \
+ "'%s' does not exist at:\n" % (cpv,), noiselevel=-1)
+ writemsg("!!! %s\n" % ebuild_path, noiselevel=-1)
+ raise KeyError(cpv)
+
+ # Pull pre-generated metadata from the metadata/cache/
+ # directory if it exists and is valid, otherwise fall
+ # back to the normal writable cache.
+ auxdbs = []
+ pregen_auxdb = self._pregen_auxdb.get(repo_path)
+ if pregen_auxdb is not None:
+ auxdbs.append(pregen_auxdb)
+ auxdbs.append(self.auxdb[repo_path])
+
+ doregen = True
+ for auxdb in auxdbs:
+ try:
+ metadata = auxdb[cpv]
+ eapi = metadata.get("EAPI","").strip()
+ if not eapi:
+ eapi = "0"
+ if eapi.startswith("-") and eapi_is_supported(eapi[1:]):
+ pass
+ elif emtime != int(metadata.get("_mtime_", 0)):
+ pass
+ elif len(metadata.get("_eclasses_", [])) > 0:
+ if self.eclassdb.is_eclass_data_valid(
+ metadata["_eclasses_"]):
+ doregen = False
+ else:
+ doregen = False
+ except KeyError:
+ pass
+ except CacheError:
+ if auxdb is not pregen_auxdb:
+ try:
+ del auxdb[cpv]
+ except KeyError:
+ pass
+ if not doregen:
+ break
+
+ if doregen:
+ metadata = None
+
+ return (metadata, st, emtime)
+
def aux_get(self, mycpv, mylist, mytree=None):
"stub code for returning auxilliary db information, such as SLOT, DEPEND, etc."
'input: "sys-apps/foo-1.0",["SLOT","DEPEND","HOMEPAGE"]'
@@ -294,52 +392,8 @@ class portdbapi(dbapi):
writemsg("!!! Manifest is missing or inaccessable: %(manifest)s\n" % {"manifest":myManifestPath},
noiselevel=-1)
-
- try:
- st = os.stat(myebuild)
- emtime = st[stat.ST_MTIME]
- except OSError:
- writemsg("!!! aux_get(): ebuild for '%(cpv)s' does not exist at:\n" % {"cpv":mycpv},
- noiselevel=-1)
- writemsg("!!! %s\n" % myebuild,
- noiselevel=-1)
- raise KeyError(mycpv)
-
- # Pull pre-generated metadata from the metadata/cache/
- # directory if it exists and is valid, otherwise fall
- # back to the normal writable cache.
- auxdbs = []
- pregen_auxdb = self._pregen_auxdb.get(mylocation)
- if pregen_auxdb is not None:
- auxdbs.append(pregen_auxdb)
- auxdbs.append(self.auxdb[mylocation])
-
- doregen = True
- for auxdb in auxdbs:
- try:
- mydata = auxdb[mycpv]
- eapi = mydata.get("EAPI","").strip()
- if not eapi:
- eapi = "0"
- if eapi.startswith("-") and eapi_is_supported(eapi[1:]):
- pass
- elif emtime != long(mydata.get("_mtime_", 0)):
- pass
- elif len(mydata.get("_eclasses_", [])) > 0:
- if self.eclassdb.is_eclass_data_valid(mydata["_eclasses_"]):
- doregen = False
- else:
- doregen = False
- except KeyError:
- pass
- except CacheError:
- if auxdb is not pregen_auxdb:
- try:
- del auxdb[mycpv]
- except KeyError:
- pass
- if not doregen:
- break
+ mydata, st, emtime = self._pull_valid_cache(mycpv, myebuild, mylocation)
+ doregen = mydata is None
writemsg("auxdb is valid: "+str(not doregen)+" "+str(pkg)+"\n", 2)
@@ -360,26 +414,8 @@ class portdbapi(dbapi):
self._broken_ebuilds.add(myebuild)
raise KeyError(mycpv)
- if "EAPI" not in mydata or not mydata["EAPI"].strip():
- mydata["EAPI"] = "0"
-
- if not eapi_is_supported(mydata["EAPI"]):
- # if newer version, wipe everything and negate eapi
- eapi = mydata["EAPI"]
- mydata = {}
- map(lambda x: mydata.setdefault(x, ""), auxdbkeys)
- mydata["EAPI"] = "-"+eapi
-
- if mydata.get("INHERITED", False):
- mydata["_eclasses_"] = self.eclassdb.get_eclass_data(mydata["INHERITED"].split())
- else:
- mydata["_eclasses_"] = {}
-
- del mydata["INHERITED"]
-
- mydata["_mtime_"] = emtime
-
- self.auxdb[mylocation][mycpv] = mydata
+ self._metadata_callback(
+ mycpv, myebuild, mylocation, mydata, emtime)
if not mydata.setdefault("EAPI", "0"):
mydata["EAPI"] = "0"