summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Kalnischkies <david@kalnischkies.de>2016-05-14 23:52:47 +0200
committerDavid Kalnischkies <david@kalnischkies.de>2016-06-27 11:43:09 +0200
commitdae197476f1831269d13f4e990276ce25c483842 (patch)
treeecc186359b5c92a88a54465d3156c44cb25b3a98
parent7b197262212f49b3b355b1124edf2ba9adb73411 (diff)
eipp: output at most two versions per package
We can trim generation time and size of the EIPP scenario considerable if we we avoid telling the planers about "uninteresting" packages. This is one of the simpler but already very effective reductions: Do not tell planers about versions which are neither installed nor are to be installed as they have no effect on the plan we don't need to tell the planer about them. EDSP solvers need to know about all versions for better choice and error messages, but planers really don't. Git-Dch: Ignore
-rw-r--r--apt-pkg/edsp.cc73
-rwxr-xr-xtest/integration/test-external-installation-planer-protocol28
2 files changed, 81 insertions, 20 deletions
diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc
index 58982ade2..e37ab04b4 100644
--- a/apt-pkg/edsp.cc
+++ b/apt-pkg/edsp.cc
@@ -1143,7 +1143,7 @@ bool EIPP::WriteRequest(pkgDepCache &Cache, FileFd &output, /*{{{*/
return WriteOkay(Okay, output, "\n");
}
/*}}}*/
-static bool WriteScenarioEIPPVersion(pkgDepCache &Cache, FileFd &output, pkgCache::PkgIterator const &Pkg,/*{{{*/
+static bool WriteScenarioEIPPVersion(pkgDepCache &, FileFd &output, pkgCache::PkgIterator const &Pkg,/*{{{*/
pkgCache::VerIterator const &Ver)
{
bool Okay = true;
@@ -1159,37 +1159,70 @@ static bool WriteScenarioEIPPVersion(pkgDepCache &Cache, FileFd &output, pkgCach
case pkgCache::State::TriggersPending: WriteOkay(Okay, output, "\nStatus: triggers-pending"); break;
case pkgCache::State::Installed: WriteOkay(Okay, output, "\nStatus: installed"); break;
}
- if (Pkg->SelectedState == pkgCache::State::Hold)
- WriteOkay(Okay, output, "\nHold: yes");
- // FIXME: Ideally, an EIPP request contains at most two versions (installed and to install)
- if (Cache.GetCandidateVersion(Pkg) == Ver)
- WriteOkay(Okay, output, "\nAPT-Candidate: yes");
return Okay;
}
/*}}}*/
// EIPP::WriteScenario - to the given file descriptor /*{{{*/
+template<typename forVersion> void forAllInterestingVersions(pkgDepCache &Cache, pkgCache::PkgIterator const &Pkg, forVersion const &func)
+{
+ if (Pkg->CurrentState == pkgCache::State::NotInstalled)
+ {
+ auto P = Cache[Pkg];
+ if (P.Install() == false)
+ return;
+ func(Pkg, P.InstVerIter(Cache));
+ }
+ else
+ {
+ if (Pkg->CurrentVer != 0)
+ func(Pkg, Pkg.CurrentVer());
+ auto P = Cache[Pkg];
+ auto const V = P.InstVerIter(Cache);
+ if (P.Delete() == false && Pkg.CurrentVer() != V)
+ func(Pkg, V);
+ }
+}
+
bool EIPP::WriteScenario(pkgDepCache &Cache, FileFd &output, OpProgress * const Progress)
{
if (Progress != NULL)
- Progress->SubProgress(Cache.Head().VersionCount, _("Send scenario to planer"));
+ Progress->SubProgress(Cache.Head().PackageCount, _("Send scenario to planer"));
unsigned long p = 0;
bool Okay = output.Failed() == false;
std::vector<std::string> archs = APT::Configuration::getArchitectures();
- std::vector<bool> pkgset(Cache.Head().VersionCount, true);
- for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false && likely(Okay); ++Pkg)
- {
- std::string const arch = Pkg.Arch();
- if (std::find(archs.begin(), archs.end(), arch) == archs.end())
- continue;
- for (pkgCache::VerIterator Ver = Pkg.VersionList(); Ver.end() == false && likely(Okay); ++Ver, ++p)
+ std::vector<bool> pkgset(Cache.Head().PackageCount, false);
+ auto const MarkVersion = [&](pkgCache::PkgIterator const &Pkg, pkgCache::VerIterator const &Ver) {
+ pkgset[Pkg->ID] = true;
+ for (auto D = Ver.DependsList(); D.end() == false; ++D)
{
- Okay &= WriteScenarioVersion(output, Pkg, Ver);
- Okay &= WriteScenarioEIPPVersion(Cache, output, Pkg, Ver);
- Okay &= WriteScenarioLimitedDependency(output, Ver, pkgset, true);
- WriteOkay(Okay, output, "\n");
- if (Progress != NULL && p % 100 == 0)
- Progress->Progress(p);
+ if (D.IsCritical() == false)
+ continue;
+ auto const P = D.TargetPkg();
+ for (auto Prv = P.ProvidesList(); Prv.end() == false; ++Prv)
+ {
+ auto const V = Prv.OwnerVer();
+ auto const PV = V.ParentPkg();
+ if (V == PV.CurrentVer() || V == Cache[PV].InstVerIter(Cache))
+ pkgset[PV->ID] = true;
+ }
+ pkgset[P->ID] = true;
}
+ };
+ for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false; ++Pkg)
+ forAllInterestingVersions(Cache, Pkg, MarkVersion);
+ auto const WriteVersion = [&](pkgCache::PkgIterator const &Pkg, pkgCache::VerIterator const &Ver) {
+ Okay &= WriteScenarioVersion(output, Pkg, Ver);
+ Okay &= WriteScenarioEIPPVersion(Cache, output, Pkg, Ver);
+ Okay &= WriteScenarioLimitedDependency(output, Ver, pkgset, true);
+ WriteOkay(Okay, output, "\n");
+ if (Progress != NULL && p % 100 == 0)
+ Progress->Progress(p);
+ };
+ for (pkgCache::PkgIterator Pkg = Cache.PkgBegin(); Pkg.end() == false && likely(Okay); ++Pkg, ++p)
+ {
+ if (pkgset[Pkg->ID] == false || Pkg->VersionList == 0)
+ continue;
+ forAllInterestingVersions(Cache, Pkg, WriteVersion);
}
return true;
}
diff --git a/test/integration/test-external-installation-planer-protocol b/test/integration/test-external-installation-planer-protocol
new file mode 100755
index 000000000..db43675e1
--- /dev/null
+++ b/test/integration/test-external-installation-planer-protocol
@@ -0,0 +1,28 @@
+#!/bin/sh
+set -e
+
+TESTDIR="$(readlink -f "$(dirname "$0")")"
+. "$TESTDIR/framework"
+setupenvironment
+configarchitecture 'amd64'
+
+buildsimplenativepackage 'libfoo' 'amd64' '3' 'experimental' 'Multi-Arch: same'
+buildsimplenativepackage 'foo' 'all' '3' 'experimental' 'Depends: newstuff'
+buildsimplenativepackage 'foo' 'all' '2' 'unstable' 'Depends: libfoo:amd64, stuff
+Conflicts: bar, libfoo:i386
+Recommends: unrelated'
+buildsimplenativepackage 'libfoo' 'amd64' '2' 'unstable' 'Multi-Arch: same'
+buildsimplenativepackage 'unrelated-2' 'amd64' '2' 'unstable'
+insertinstalledpackage 'foo' 'all' '1'
+insertinstalledpackage 'bar' 'all' '1'
+insertinstalledpackage 'stuff' 'all' '1'
+insertinstalledpackage 'unrelated-1' 'all' '1'
+
+setupaptarchive --no-update
+
+testsuccess apt update
+export APT_EDSP_DUMP_FILENAME="${TMPWORKINGDIRECTORY}/eipp.dump"
+testfailure aptget install foo --planer dump -y
+testfailure grep 'unrelated-2' "$APT_EDSP_DUMP_FILENAME"
+testsuccessequal '2' grep -c '^Package: foo$' "$APT_EDSP_DUMP_FILENAME"
+testsuccessequal '1' grep -c '^Package: libfoo$' "$APT_EDSP_DUMP_FILENAME"