summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Kalnischkies <kalnischkies@gmail.com>2011-04-02 15:47:14 +0200
committerDavid Kalnischkies <kalnischkies@gmail.com>2011-04-02 15:47:14 +0200
commit2029276f0343c96481d0d3cbbc367420b4a5f864 (patch)
tree284fa7ce71cd75381f61db74fbb9b215c6404c99
parent4128c84679e54e2afda7913946facaf9c52cd3eb (diff)
send the scenario through a pipe to the solver and get the solution back
The solution is NOT interpreted so far.
-rw-r--r--apt-pkg/algorithms.cc42
-rw-r--r--apt-pkg/edsp.cc28
-rw-r--r--apt-pkg/edsp.h2
3 files changed, 62 insertions, 10 deletions
diff --git a/apt-pkg/algorithms.cc b/apt-pkg/algorithms.cc
index aabb511a2..bbe315ef7 100644
--- a/apt-pkg/algorithms.cc
+++ b/apt-pkg/algorithms.cc
@@ -740,18 +740,46 @@ bool pkgProblemResolver::DoUpgrade(pkgCache::PkgIterator Pkg)
bool pkgProblemResolver::Resolve(bool BrokenFix)
{
std::string const solver = _config->Find("APT::Solver::Name", "internal");
+
if (solver != "internal")
{
- FILE* output = fopen("/tmp/scenario.log", "w");
+// std::string const file = _config->FindDir("Dir::Bin::Solvers") + solver;
+ std::string const file = solver;
+ if (RealFileExists(file.c_str()) == false)
+ return _error->Error("Can't call external solver '%s' as it is not available: %s", solver.c_str(), file.c_str());
+ int external[4] = {-1, -1, -1, -1};
+ if (pipe(external) != 0 || pipe(external + 2) != 0)
+ return _error->Errno("Resolve", "Can't create needed IPC pipes for EDSP");
+ for (int i = 0; i < 4; ++i)
+ SetCloseExec(external[i], true);
+
+ pid_t Solver = ExecFork();
+ if (Solver == 0)
+ {
+ dup2(external[0], STDIN_FILENO);
+ dup2(external[3], STDOUT_FILENO);
+ const char* calling[2] = { file.c_str(), 0 };
+ execv(calling[0], (char**) calling);
+ std::cerr << "Failed to execute solver '" << solver << "'!" << std::endl;
+ _exit(100);
+ }
+ close(external[0]);
+ close(external[3]);
+
+ if (WaitFd(external[1], true, 5) == false)
+ return _error->Errno("Resolve", "Waiting on availability of solver stdin timed out");
+
+ FILE* output = fdopen(external[1], "w");
+ if (output == NULL)
+ return _error->Errno("Resolve", "fdopen on solver stdin failed");
EDSP::WriteRequest(Cache, output);
EDSP::WriteScenario(Cache, output);
fclose(output);
- if (ResolveInternal(BrokenFix) == false)
- return false;
- output = fopen("/tmp/solution.log", "w");
- EDSP::WriteSolution(Cache, output);
- fclose(output);
- return true;
+
+ if (EDSP::ReadResponse(external[2], Cache) == false)
+ return _error->Error("Reading solver response failed");
+
+ return ExecWait(Solver, solver.c_str(), false);
}
return ResolveInternal(BrokenFix);
}
diff --git a/apt-pkg/edsp.cc b/apt-pkg/edsp.cc
index d93b05411..e6dc16536 100644
--- a/apt-pkg/edsp.cc
+++ b/apt-pkg/edsp.cc
@@ -10,6 +10,7 @@
#include <apt-pkg/configuration.h>
#include <apt-pkg/version.h>
#include <apt-pkg/policy.h>
+#include <apt-pkg/tagfile.h>
#include <apti18n.h>
#include <limits>
@@ -139,14 +140,37 @@ bool EDSP::WriteRequest(pkgDepCache &Cache, FILE* output, bool const Upgrade,
return true;
}
/*}}}*/
-bool EDSP::ReadResponse(FILE* input, pkgDepCache &Cache) { return false; }
+// EDSP::ReadResponse - from the given file descriptor /*{{{*/
+bool EDSP::ReadResponse(int const input, pkgDepCache &Cache) {
+ FileFd in;
+ in.OpenDescriptor(input, FileFd::ReadOnly);
+ pkgTagFile response(&in);
+ pkgTagSection section;
+ while (response.Step(section) == true) {
+ std::string type;
+ if (section.Exists("Install") == true)
+ type = "Install";
+ else if (section.Exists("Remove") == true)
+ type = "Remove";
+ //FIXME: handle progress
+ else
+ continue;
+
+ int const id = section.FindI(type.c_str(), -1);
+ if (id == -1)
+ return _error->Error("Unable to parse %s request!", type.c_str());
+ //FIXME: find version by id and mark it correctly
+ }
+ return true;
+}
+ /*}}}*/
// EDSP::ReadLine - first line from the given file descriptor /*{{{*/
// ---------------------------------------------------------------------
/* Little helper method to read a complete line into a string. Similar to
fgets but we need to use the low-level read() here as otherwise the
listparser will be confused later on as mixing of fgets and read isn't
- a supported action according to the manpages and result are undefined */
+ a supported action according to the manpages and results are undefined */
bool EDSP::ReadLine(int const input, std::string &line) {
char one;
ssize_t data = 0;
diff --git a/apt-pkg/edsp.h b/apt-pkg/edsp.h
index 75733c2d2..31f8891f3 100644
--- a/apt-pkg/edsp.h
+++ b/apt-pkg/edsp.h
@@ -22,7 +22,7 @@ public:
bool const distUpgrade = false,
bool const autoRemove = false);
bool static WriteScenario(pkgDepCache &Cache, FILE* output);
- bool static ReadResponse(FILE* input, pkgDepCache &Cache);
+ bool static ReadResponse(int const input, pkgDepCache &Cache);
// ReadScenario is provided by the listparser infrastructure
bool static ReadRequest(int const input, std::list<std::string> &install,