Kaynağa Gözat

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
David Kalnischkies 10 yıl önce
ebeveyn
işleme
dae197476f

+ 53 - 20
apt-pkg/edsp.cc

@@ -1143,7 +1143,7 @@ bool EIPP::WriteRequest(pkgDepCache &Cache, FileFd &output,		/*{{{*/
    return WriteOkay(Okay, output, "\n");
    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)
 				pkgCache::VerIterator const &Ver)
 {
 {
    bool Okay = true;
    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::TriggersPending: WriteOkay(Okay, output, "\nStatus: triggers-pending"); break;
 	 case pkgCache::State::Installed: WriteOkay(Okay, output, "\nStatus: installed"); 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;
    return Okay;
 }
 }
 									/*}}}*/
 									/*}}}*/
 // EIPP::WriteScenario - to the given file descriptor			/*{{{*/
 // 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)
 bool EIPP::WriteScenario(pkgDepCache &Cache, FileFd &output, OpProgress * const Progress)
 {
 {
    if (Progress != NULL)
    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;
    unsigned long p = 0;
    bool Okay = output.Failed() == false;
    bool Okay = output.Failed() == false;
    std::vector<std::string> archs = APT::Configuration::getArchitectures();
    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;
    return true;
 }
 }

+ 28 - 0
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"