[Aptitude-svn-commit] r4082 - in branches/aptitude-0.3/aptitude: . src src/cmdline src/generic

Daniel Burrows dburrows at costa.debian.org
Wed Sep 14 19:55:42 UTC 2005


Author: dburrows
Date: Wed Sep 14 19:55:38 2005
New Revision: 4082

Added:
   branches/aptitude-0.3/aptitude/src/generic/resolver_manager.cc
   branches/aptitude-0.3/aptitude/src/generic/resolver_manager.h
Modified:
   branches/aptitude-0.3/aptitude/ChangeLog
   branches/aptitude-0.3/aptitude/src/broken_indicator.cc
   branches/aptitude-0.3/aptitude/src/cmdline/cmdline_prompt.cc
   branches/aptitude-0.3/aptitude/src/cmdline/cmdline_resolver.cc
   branches/aptitude-0.3/aptitude/src/generic/Makefile.am
   branches/aptitude-0.3/aptitude/src/generic/apt.cc
   branches/aptitude-0.3/aptitude/src/generic/apt.h
   branches/aptitude-0.3/aptitude/src/generic/aptcache.cc
   branches/aptitude-0.3/aptitude/src/generic/aptcache.h
   branches/aptitude-0.3/aptitude/src/solution_dialog.cc
   branches/aptitude-0.3/aptitude/src/solution_screen.cc
   branches/aptitude-0.3/aptitude/src/ui.cc
Log:
Split out the resolver management functions of the cache file.

Modified: branches/aptitude-0.3/aptitude/ChangeLog
==============================================================================
--- branches/aptitude-0.3/aptitude/ChangeLog	(original)
+++ branches/aptitude-0.3/aptitude/ChangeLog	Wed Sep 14 19:55:38 2005
@@ -1,5 +1,10 @@
 2005-09-14  Daniel Burrows  <dburrows at debian.org>
 
+	* src/broken_indicator.cc, src/cmdline/cmdline_prompt.cc, src/cmdline/cmdline_resolver.cc, src/generic/aptcache.cc, src/generic/aptcache.h, src/generic/apt.cc, src/generic/apt.h, src/generic/Makefile.am, src/generic/resolver_manager.cc, src/generic/resolver_manager.h, src/solution_dialog.cc, src/solution_screen.cc, src/ui.cc:
+
+	  Factor the resolver management functions of the cache file out
+	  into a separate class.
+
 	* src/generic/problemresolver/problemresolver.h:
 
 	  includes is in namespace std, add a qualifier (why did this ever

Modified: branches/aptitude-0.3/aptitude/src/broken_indicator.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/broken_indicator.cc	(original)
+++ branches/aptitude-0.3/aptitude/src/broken_indicator.cc	Wed Sep 14 19:55:38 2005
@@ -27,6 +27,7 @@
 #include <generic/aptitude_resolver_universe.h>
 #include <generic/problemresolver/exceptions.h>
 #include <generic/problemresolver/solution.h>
+#include <generic/resolver_manager.h>
 #include <generic/util.h>
 
 #include <vscreen/config/colors.h>
@@ -64,7 +65,7 @@
     if(apt_cache_file)
       {
 	(*apt_cache_file)->package_state_changed.connect(sigc::mem_fun(*this, &broken_indicator::update));
-	(*apt_cache_file)->selected_solution_changed.connect(sigc::mem_fun(*this, &broken_indicator::update));
+	resman->selected_solution_changed.connect(sigc::mem_fun(*this, &broken_indicator::update));
       }
 
     update();
@@ -76,7 +77,7 @@
     if(apt_cache_file)
       {
 	(*apt_cache_file)->package_state_changed.connect(sigc::mem_fun(*this, &broken_indicator::update));
-	(*apt_cache_file)->selected_solution_changed.connect(sigc::mem_fun(*this, &broken_indicator::update));
+	resman->selected_solution_changed.connect(sigc::mem_fun(*this, &broken_indicator::update));
       }
 
     cache_closed.connect(sigc::mem_fun(*this, &broken_indicator::update));
@@ -94,7 +95,7 @@
 
   void update()
   {
-    if((!apt_cache_file) || !(*apt_cache_file)->resolver_exists())
+    if((!apt_cache_file) || !resman->resolver_exists())
       {
 	set_fragment(fragf(""));
 	last_sol.nullify();
@@ -111,13 +112,13 @@
     // it.
     try
       {
-	aptitude_solution sol=(*apt_cache_file)->get_current_solution();
+	aptitude_solution sol=resman->get_current_solution();
 
-	if(sol == last_sol && (*apt_cache_file)->solution_generation_complete() == last_complete)
+	if(sol == last_sol && resman->solution_generation_complete() == last_complete)
 	  return;
 
 	last_sol = sol;
-	last_complete = (*apt_cache_file)->solution_generation_complete();
+	last_complete = resman->solution_generation_complete();
 
 	if(sol.get_actions().empty())
 	  {
@@ -168,9 +169,9 @@
 	    vector<fragment *> fragments;
 
 	    string countstr
-	      = ssprintf((*apt_cache_file)->solution_generation_complete()?"[%d/%d]":"[%d(%d)/...]",
-			 (*apt_cache_file)->get_selected_solution()+1,
-			 (*apt_cache_file)->generated_solution_count());
+	      = ssprintf(resman->solution_generation_complete()?"[%d/%d]":"[%d(%d)/...]",
+			 resman->get_selected_solution()+1,
+			 resman->generated_solution_count());
 	    fragments.push_back(fragf("%s ", countstr.c_str()));
 
 	    fragments.push_back(fragf(_("Suggest ")));

Modified: branches/aptitude-0.3/aptitude/src/cmdline/cmdline_prompt.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/cmdline/cmdline_prompt.cc	(original)
+++ branches/aptitude-0.3/aptitude/src/cmdline/cmdline_prompt.cc	Wed Sep 14 19:55:38 2005
@@ -712,7 +712,7 @@
 	 !always_prompt &&
 	 (*apt_cache_file)->BrokenCount()==0)
 	cont=true;
-      else if((*apt_cache_file)->resolver_exists())
+      else if((*apt_cache_file)->BrokenCount() > 0)
 	{
 	  if(!cmdline_resolve_deps(to_install,
 				   to_hold,

Modified: branches/aptitude-0.3/aptitude/src/cmdline/cmdline_resolver.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/cmdline/cmdline_resolver.cc	(original)
+++ branches/aptitude-0.3/aptitude/src/cmdline/cmdline_resolver.cc	Wed Sep 14 19:55:38 2005
@@ -34,6 +34,7 @@
 #include <generic/config_signal.h>
 #include <generic/problemresolver/exceptions.h>
 #include <generic/problemresolver/solution.h>
+#include <generic/resolver_manager.h>
 #include <generic/util.h>
 
 #include <vscreen/fragment.h>
@@ -78,13 +79,13 @@
 			   pkgset &to_purge,
 			   bool force_no_change)
 {
-  (*apt_cache_file)->set_resolver_debug(aptcfg->FindB(PACKAGE "::CmdLine::Resolver-Debug", false));
+  resman->set_debug(aptcfg->FindB(PACKAGE "::CmdLine::Resolver-Debug", false));
 
   // For all packages that the user listed on the command-line (i.e.,
   // all in to_install, to_hold, to_remove, and to_purge), tell the
   // resolver to try *really really hard* to avoid altering their
   // state.
-  if(force_no_change && (*apt_cache_file)->resolver_exists())
+  if(force_no_change && resman->resolver_exists())
     {
       pkgset *sets[4]={&to_install, &to_hold, &to_remove, &to_purge};
       int tweak_amt=aptcfg->FindI(PACKAGE "::CmdLine::Request-Strictness", 1000);
@@ -102,12 +103,12 @@
 	      for(pkgCache::VerIterator v=p->VersionList();
 		  !v.end(); ++v)
 		if(instver == v)
-		  (*apt_cache_file)->tweak_score(*p, v,
-						 tweak_amt);
+		  resman->tweak_score(*p, v,
+				     tweak_amt);
 
 	      if(instver.end())
-		(*apt_cache_file)->tweak_score(*p, pkgCache::VerIterator(*apt_cache_file),
-					       tweak_amt);
+		resman->tweak_score(*p, pkgCache::VerIterator(*apt_cache_file),
+				   tweak_amt);
 	    }
 	}
     }
@@ -274,7 +275,7 @@
 
       if(is_reject)
 	{
-	  if((*apt_cache_file)->resolver_is_rejected(ver))
+	  if(resman->is_rejected(ver))
 	    {
 	      if(ver.get_ver().end())
 		cout << ssprintf(_("Allowing the removal of %s"),
@@ -285,7 +286,7 @@
 				 ver.get_ver().VerStr(),
 				 archives_text(ver.get_ver()).c_str()) << endl;
 
-	      (*apt_cache_file)->resolver_unreject_version(ver);
+	      resman->unreject_version(ver);
 	    }
 	  else
 	    {
@@ -298,12 +299,12 @@
 				 ver.get_ver().VerStr(),
 				 archives_text(ver.get_ver()).c_str()) << endl;
 
-	      (*apt_cache_file)->resolver_reject_version(ver);
+	      resman->reject_version(ver);
 	    }
 	}
       else
 	{
-	  if((*apt_cache_file)->resolver_is_mandatory(ver))
+	  if(resman->is_mandatory(ver))
 	    {
 	      if(ver.get_ver().end())
 		cout << ssprintf(_("No longer requiring the removal of %s"),
@@ -313,7 +314,7 @@
 				 pkg.Name(), ver.get_ver().VerStr(),
 				 archives_text(ver.get_ver()).c_str()) << endl;
 
-	      (*apt_cache_file)->resolver_unmandate_version(ver);
+	      resman->unmandate_version(ver);
 	    }
 	  else
 	    {
@@ -325,7 +326,7 @@
 				 pkg.Name(), ver.get_ver().VerStr(),
 				 archives_text(ver.get_ver()).c_str()) << endl;
 
-	      (*apt_cache_file)->resolver_mandate_version(ver);
+	      resman->mandate_version(ver);
 	    }
 	}
     }
@@ -354,7 +355,7 @@
 	  {
 	    try
 	      {
-		aptitude_solution sol=(*apt_cache_file)->get_current_solution();
+		aptitude_solution sol=resman->get_current_solution();
 
 		if(_error->PendingError())
 		  _error->DumpErrors();
@@ -390,17 +391,17 @@
 		switch(toupper(response[loc]))
 		  {
 		  case 'Y':
-		    (*apt_cache_file)->apply_current_solution(NULL);
+		    (*apt_cache_file)->apply_solution(resman->get_current_solution(), NULL);
 		    modified_pkgs=true;
 		    break;
 		  case 'N':
 		    {
-		      int curr_count=(*apt_cache_file)->generated_solution_count();
+		      int curr_count = resman->generated_solution_count();
 
 		      // Move to the last cached solution.
 		      if(curr_count>0)
-			while((*apt_cache_file)->get_selected_solution()<curr_count)
-			  (*apt_cache_file)->next_solution();
+			while(resman->get_selected_solution()<curr_count)
+			  resman->next_solution();
 		    }
 		    break;
 		  case 'Q':
@@ -425,11 +426,11 @@
 		    reject_or_mandate_version(string(response, 1), false);
 		    break;
 		  case '.':
-		    (*apt_cache_file)->next_solution();
+		    resman->next_solution();
 		    break;
 		  case ',':
 		    // As above, errors pop to the outer 'catch'
-		    (*apt_cache_file)->previous_solution();
+		    resman->previous_solution();
 		    break;
 		  case '?':
 		    cout << _("The following commands are available:") << endl;
@@ -453,7 +454,7 @@
 			_error->Errno("dump_resolver", _("Unable to open %s for writing"), fn.c_str());
 		      else
 			{
-			  (*apt_cache_file)->dump_resolver(f);
+			  resman->dump(f);
 			  if(!f)
 			    _error->Errno("dump_resolver", _("Error writing resolver state to %s"), fn.c_str());
 			  else
@@ -487,7 +488,7 @@
 		      case 'Y':
 			try
 			  {
-			    (*apt_cache_file)->next_solution();
+			    resman->next_solution();
 			    done=true;
 			  }
 			catch(NoMoreTime)
@@ -507,7 +508,7 @@
 	  }
 	catch(NoMoreSolutions)
 	  {
-	    if((*apt_cache_file)->generated_solution_count()==0)
+	    if(resman->generated_solution_count()==0)
 	      {
 		cout << _("Unable to resolve dependencies!  Giving up...") << endl;
 		return false;

Modified: branches/aptitude-0.3/aptitude/src/generic/Makefile.am
==============================================================================
--- branches/aptitude-0.3/aptitude/src/generic/Makefile.am	(original)
+++ branches/aptitude-0.3/aptitude/src/generic/Makefile.am	Wed Sep 14 19:55:38 2005
@@ -42,6 +42,8 @@
 	pkg_changelog.cc\
 	pkg_hier.h	\
 	pkg_hier.cc	\
+	resolver_manager.h\
+	resolver_manager.cc\
 	rev_dep_iterator.h \
 	strhash.h	\
 	tags.h		\

Modified: branches/aptitude-0.3/aptitude/src/generic/apt.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/generic/apt.cc	(original)
+++ branches/aptitude-0.3/aptitude/src/generic/apt.cc	Wed Sep 14 19:55:38 2005
@@ -25,6 +25,7 @@
 
 #include "config_signal.h"
 #include "pkg_hier.h"
+#include "resolver_manager.h"
 #include "rev_dep_iterator.h"
 #include "tags.h"
 #include "tasks.h"
@@ -61,6 +62,7 @@
 pkgSourceList *apt_source_list=NULL;
 undo_list *apt_undos=NULL;
 pkg_hier *user_pkg_hier=NULL;
+resolver_manager *resman = NULL;
 
 string *pendingerr=NULL;
 bool erroriswarning=false;
@@ -233,6 +235,12 @@
       apt_source_list=NULL;
     }
 
+  if(resman)
+    {
+      delete resman;
+      resman = NULL;
+    }
+
   aptitudeCacheFile *new_file=new aptitudeCacheFile;
 
   apt_source_list=new pkgSourceList;
@@ -284,6 +292,8 @@
       hier_reloaded();
     }
 
+  resman = new resolver_manager(*new_file);
+
   cache_reloaded();
 }
 

Modified: branches/aptitude-0.3/aptitude/src/generic/apt.h
==============================================================================
--- branches/aptitude-0.3/aptitude/src/generic/apt.h	(original)
+++ branches/aptitude-0.3/aptitude/src/generic/apt.h	Wed Sep 14 19:55:38 2005
@@ -35,13 +35,14 @@
 class pkg_hier;
 class signalling_config;
 class undo_list;
+class resolver_manager;
 
+// Global state variables for the apt stuff:
 extern signalling_config *aptcfg;
 extern aptitudeCacheFile *apt_cache_file;
+extern resolver_manager *resman;
 extern pkgSourceList *apt_source_list;
 extern pkgRecords *apt_package_records;
-// I'm confused about whether this (the records object) really needs to be
-// globally allocated.
 
 pkg_hier *get_user_pkg_hier();
 // Currently, package hierarchies are (by default) loaded using

Modified: branches/aptitude-0.3/aptitude/src/generic/aptcache.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/generic/aptcache.cc	(original)
+++ branches/aptitude-0.3/aptitude/src/generic/aptcache.cc	Wed Sep 14 19:55:38 2005
@@ -21,10 +21,11 @@
 
 #include "apt.h"
 #include "aptcache.h"
-#include "aptitude_resolver.h"
+#include "aptitude_resolver_universe.h"
 #include "aptitudepolicy.h"
 #include "config_signal.h"
 #include "matchers.h"
+#include "problemresolver/solution.h"
 #include "undo.h"
 
 #include <apt-pkg/error.h>
@@ -165,8 +166,7 @@
 
 aptitudeDepCache::aptitudeDepCache(pkgCache *Cache, Policy *Plcy)
   :pkgDepCache(Cache, Plcy), dirty(false), package_states(NULL), lock(-1),
-   group_level(0), mark_and_sweep_in_progress(false),
-   resolver(NULL), out_of_time(false), selected_solution(0)
+   group_level(0), mark_and_sweep_in_progress(false)
 {
   // When the "install recommended packages" flag changes, collect garbage.
   aptcfg->connect(PACKAGE "::Recommends-Important",
@@ -174,11 +174,6 @@
 					   &aptitudeDepCache::mark_and_sweep),
 			     (undo_group *) NULL));
 
-  aptcfg->connect(PACKAGE "::Recommends-Important",
-		  sigc::bind(sigc::mem_fun(*this,
-					   &aptitudeDepCache::discard_resolver),
-			     (undo_group *) NULL));
-
   // sim.
   aptcfg->connect(PACKAGE "::Keep-Suggests",
 		  sigc::bind(sigc::mem_fun(*this,
@@ -195,11 +190,6 @@
 {
   delete[] package_states;
 
-  for(unsigned int i=0; i<solutions.size(); ++i)
-    delete solutions[i];
-
-  delete resolver;
-
   if(lock!=-1)
     close(lock);
 }
@@ -658,12 +648,7 @@
   // Finds any packages whose states have changed and: (a) updates the
   // selected_state if it's not already updated; (b) adds an item to the
   // undo group.
-  //
-  // Also handles (since any change invalidates partial solutions)
-  // destroying and recreating (if necessary) a problem resolver.
 {
-  discard_resolver(undo);
-
   for(pkgCache::PkgIterator pkg=PkgBegin(); !pkg.end(); pkg++)
     {
       if(PkgState[pkg->ID].Mode!=backup_state.PkgState[pkg->ID].Mode ||
@@ -732,9 +717,6 @@
 					  backup_state.AptitudeState[pkg->ID]));
 	}
     }
-
-  if(BrokenCount()>0)
-    create_resolver();
 }
 
 void aptitudeDepCache::internal_mark_install(const PkgIterator &Pkg,
@@ -885,8 +867,6 @@
 	  if(undo)
 	    undo->add_item(new candver_undoer(prev, this));
 
-	  discard_resolver(undo);
-
 	  mark_and_sweep(undo);
 
 	  //if(BrokenCount()>0)
@@ -1312,210 +1292,12 @@
   end_action_group(undo);
 }
 
-////////////////// PROBLEM RESOLVER INTERFACE FOLLOWS //////////////////
-
-void aptitudeDepCache::discard_resolver(undo_group *undo)
-{
-  delete resolver;
-  solutions.clear();
-  resolver=NULL;
-  out_of_time=false;
-}
-
-void aptitudeDepCache::create_resolver()
-{
-  assert(resolver==NULL);
-
-  // NOTE: the performance of the resolver is highly sensitive to
-  // these settings; choosing bad ones can result in hitting
-  // exponential cases in practical situations.  In general,
-  // penalizing actions means that the resolver will be more likely to
-  // blow up trying to avoid them, with the danger increasing as the
-  // penalty does.  Thus, aside from broken deps (which are penalized
-  // to guide us towards a solution), I only penalize removals (which
-  // are usually either unnecessary or easy to prove necessary) and
-  // leaving soft dependencies (recommendations) unfixed.  The
-  // relative penalties of these are also important; for instance,
-  // penalizing unfixed soft deps more than removals means that the
-  // resolver will actually remove packages rather than leaving their
-  // Recommends: field unsatisfied!
-
-  resolver=new aptitude_resolver(aptcfg->FindI(PACKAGE "::ProblemResolver::StepScore", 10),
-				 aptcfg->FindI(PACKAGE "::ProblemResolver::BrokenScore", -100),
-				 aptcfg->FindI(PACKAGE "::ProblemResolver::UnfixedSoftScore", -200),
-				 aptcfg->FindI(PACKAGE "::ProblemResolver::Infinity", 1000000),
-				 aptcfg->FindI(PACKAGE "::ProblemResolver::Max-Successors", 0),
-				 aptcfg->FindI(PACKAGE "::ProblemResolver::ResolutionScore", 50),
-				 this);
-
-  resolver->add_action_scores(aptcfg->FindI(PACKAGE "::ProblemResolver::PreserveManualScore", 60),
-			      aptcfg->FindI(PACKAGE "::ProblemResolver::PreserveAutoScore", 0),
-			      aptcfg->FindI(PACKAGE "::ProblemResolver::RemoveScore", -300),
-			      aptcfg->FindI(PACKAGE "::ProblemResolver::KeepScore", 0),
-			      aptcfg->FindI(PACKAGE "::ProblemResolver::InstallScore", -20),
-			      aptcfg->FindI(PACKAGE "::ProblemResolver::UpgradeScore", 0),
-			      aptcfg->FindI(PACKAGE "::ProblemResolver::NonDefaultScore", -40),
-			      aptcfg->FindI(PACKAGE "::ProblemResolver::EssentialRemoveScore", -100000),
-			      aptcfg->FindI(PACKAGE "::ProblemResolver::BreakHoldScore", -300));
-
-  resolver->add_priority_scores(aptcfg->FindI(PACKAGE "::ProblemResolver::ImportantScore", 5),
-				aptcfg->FindI(PACKAGE "::ProblemResolver::RequiredScore", 4),
-				aptcfg->FindI(PACKAGE "::ProblemResolver::StandardScore", 3),
-				aptcfg->FindI(PACKAGE "::ProblemResolver::OptionalScore", 1),
-				aptcfg->FindI(PACKAGE "::ProblemResolver::ExtraScore", -1));
-}
-
-void aptitudeDepCache::set_resolver_debug(bool activate)
-{
-  assert(resolver_exists());
-
-  resolver->set_debug(activate);
-}
-
-bool aptitudeDepCache::resolver_exists() const
-{
-  return resolver != NULL;
-}
-
-unsigned int aptitudeDepCache::generated_solution_count() const
-{
-  return solutions.size();
-}
-
-bool aptitudeDepCache::solution_generation_complete() const
-{
-  return resolver->exhausted();
-}
-
-bool aptitudeDepCache::solutions_exhausted() const
-{
-  if(!resolver_exists())
-    return true;
-  else
-    return selected_solution+1 == generated_solution_count() &&
-      solution_generation_complete();
-}
-
-bool aptitudeDepCache::solutions_at_start() const
-{
-  if(!resolver_exists())
-    return true;
-  else
-    return selected_solution == 0;
-}
-
-const aptitude_resolver::solution &aptitudeDepCache::get_current_solution()
-{
-  assert(resolver);
-
-  if(out_of_time)
-    throw NoMoreTime();
-  else if(!solutions.empty())
-    return *solutions[selected_solution];
-  else
-    return next_solution();
-}
-
-// At the moment the undo argument is ignored; it's there for future
-// use.
-void aptitudeDepCache::resolver_reject_version(const aptitude_resolver_version &ver)
-{
-  assert(resolver);
-
-  resolver->reject_version(ver);
-}
-
-void aptitudeDepCache::resolver_unreject_version(const aptitude_resolver_version &ver)
-{
-  assert(resolver);
-
-  resolver->unreject_version(ver);
-
-  selected_solution_changed();
-}
-
-bool aptitudeDepCache::resolver_is_rejected(const aptitude_resolver_version &ver)
-{
-  assert(resolver);
-
-  return resolver->is_rejected(ver);
-}
-
-void aptitudeDepCache::resolver_mandate_version(const aptitude_resolver_version &ver)
-{
-  assert(resolver);
-
-  resolver->mandate_version(ver);
-}
-
-void aptitudeDepCache::resolver_unmandate_version(const aptitude_resolver_version &ver)
-{
-  assert(resolver);
-
-  resolver->unmandate_version(ver);
-
-  selected_solution_changed();
-}
-
-bool aptitudeDepCache::resolver_is_mandatory(const aptitude_resolver_version &ver)
-{
-  assert(resolver);
-
-  return resolver->is_mandatory(ver);
-}
-
-void aptitudeDepCache::resolver_harden_dep(const aptitude_resolver_dep &dep)
-{
-  assert(resolver);
-
-  resolver->harden(dep);
-}
-
-void aptitudeDepCache::resolver_unharden_dep(const aptitude_resolver_dep &dep)
-{
-  assert(resolver);
-
-  resolver->unharden(dep);
-
-  selected_solution_changed();
-}
-
-bool aptitudeDepCache::resolver_is_hardened(const aptitude_resolver_dep &dep)
-{
-  assert(resolver);
-
-  return resolver->is_hardened(dep);
-}
-
-void aptitudeDepCache::resolver_force_break_dep(const aptitude_resolver_dep &dep)
-{
-  assert(resolver);
-
-  resolver->force_break(dep);
-}
-
-void aptitudeDepCache::resolver_unforce_break_dep(const aptitude_resolver_dep &dep)
-{
-  assert(resolver);
-
-  resolver->unforce_break(dep);
-
-  selected_solution_changed();
-}
-
-bool aptitudeDepCache::resolver_is_forced_broken(const aptitude_resolver_dep &dep)
-{
-  assert(resolver);
-
-  return resolver->is_forced_broken(dep);
-}
-
-void aptitudeDepCache::apply_solution(const aptitude_resolver::solution &sol,
+void aptitudeDepCache::apply_solution(const generic_solution<aptitude_universe> &sol,
 				      undo_group *undo)
 {
   begin_action_group();
 
-  for(imm::map<aptitude_resolver::package, aptitude_resolver::action>::const_iterator
+  for(imm::map<aptitude_resolver_package, generic_solution<aptitude_universe>::action>::const_iterator
 	i = sol.get_actions().begin();
       i != sol.get_actions().end(); ++i)
     {
@@ -1547,102 +1329,6 @@
   end_action_group(undo);  
 }
 
-void aptitudeDepCache::apply_current_solution(undo_group *undo)
-{
-  apply_solution(get_current_solution(), undo);
-}
-
-const aptitude_resolver::solution &aptitudeDepCache::next_solution()
-{
-  if(solutions.empty())
-    {
-      try
-	{
-	  solutions.push_back(new aptitude_resolver::solution(resolver->find_next_solution(aptcfg->FindI(PACKAGE "::ProblemResolver::StepLimit", 5000))));
-	  selected_solution=0;
-	  out_of_time=false;
-	  selected_solution_changed();
-	  return *solutions.back();
-	}
-      catch(NoMoreTime) {
-	out_of_time=true;
-	throw NoMoreTime();
-      }
-      catch(NoMoreSolutions) {
-	selected_solution_changed();
-	throw NoMoreSolutions();
-      }
-    }
-  else if(selected_solution<solutions.size()-1)
-    {
-      ++selected_solution;
-      selected_solution_changed();
-      return *solutions[selected_solution];
-    }
-  else
-    {
-      // otherwise weirdness is happening.
-      assert(!out_of_time);
-
-      try
-	{
-	  solutions.push_back(new aptitude_resolver::solution(resolver->find_next_solution(aptcfg->FindI(PACKAGE "::ProblemResolver::StepLimit", 5000))));
-	}
-      catch(NoMoreSolutions)
-	{
-	  selected_solution_changed();
-	  throw NoMoreSolutions();
-	}
-      ++selected_solution;
-      selected_solution_changed();
-      return *solutions.back();
-    }
-}
-
-const aptitude_resolver::solution &aptitudeDepCache::previous_solution()
-{
-  if(solutions.empty() || selected_solution == 0)
-    throw NoMoreSolutions();
-
-  --selected_solution;
-  selected_solution_changed();
-  return *solutions[selected_solution];
-}
-
-void aptitudeDepCache::tweak_score(const pkgCache::PkgIterator &pkg,
-				   const pkgCache::VerIterator &ver,
-				   int score)
-{
-  assert(resolver_exists());
-  assert(resolver->fresh());
-
-  resolver->add_version_score(aptitude_resolver_version(pkg, ver, this),
-			      score);
-}
-
-void aptitudeDepCache::dump_resolver(ostream &out)
-{
-  if(!resolver_exists())
-    return;
-
-  // First, dump the universe.
-  dump_universe(resolver->get_universe(), out);
-
-  // Now dump the scores as a test instruction.
-  out << "TEST " << resolver->get_step_score() << " "
-      << resolver->get_broken_score() << " "
-      << resolver->get_unresolved_soft_dep_score() << " "
-      << resolver->get_infinity() << " "
-      << resolver->get_max_successors() << " "
-      << resolver->get_full_solution_score() << " ";
-
-  resolver->dump_scores(out);
-
-  out << "EXPECT ( " << aptcfg->FindI(PACKAGE "::Resolver::StepLimit", 5000) << " ANY )" << endl;
-}
-
-//////////////////// END PROBLEM RESOLVER INTERFACE ////////////////////
-
 aptitudeCacheFile::aptitudeCacheFile()
   :Map(NULL), Cache(NULL), DCache(NULL), have_system_lock(false), Policy(NULL)
 {

Modified: branches/aptitude-0.3/aptitude/src/generic/aptcache.h
==============================================================================
--- branches/aptitude-0.3/aptitude/src/generic/aptcache.h	(original)
+++ branches/aptitude-0.3/aptitude/src/generic/aptcache.h	Wed Sep 14 19:55:38 2005
@@ -42,10 +42,7 @@
 class undo_group;
 class pkgProblemResolver;
 class aptitude_universe;
-class aptitude_resolver_dep;
-class aptitude_resolver_version;
-class aptitude_resolver;
-template<class PkgUniverse> class generic_solution;
+template<typename PackageUniverse> class generic_solution;
 
 class aptitudeDepCache:public pkgDepCache, public sigc::trackable
 {
@@ -211,29 +208,6 @@
   apt_state_snapshot backup_state;
   // Stores what the cache was like just before an action was performed
 
-  /** The current problem resolver.  This is destroyed (if it exists)
-   *  in cleanup_after_change, then created again if broken packages
-   *  exist.
-   */
-  aptitude_resolver *resolver;
-
-  /** If \b true, there are no solutions and the last attempt to
-   *  calculate one failed with NoMoreTime.
-   *
-   *  This is used so that the return value of get_current_solution()
-   *  is stable.
-   */
-  bool out_of_time;
-
-  /** All the solutions generated since the last change to the cache.
-   */
-  std::vector<generic_solution<aptitude_universe> *> solutions;
-
-  /** The currently "selected" solution, as an index in the solutions
-   *  array.
-   */
-  unsigned int selected_solution;
-
   /** Call whenever the cache state is modified; discards the
    *  state of the active resolver.
    *
@@ -357,71 +331,6 @@
   // Marks the given package as having been autoinstalled (so it will be
   // removed automatically) or having been installed manually.
 
-
-  /** \return \b true if automatic aptitude upgrades should ignore this
-   *  package.
-   */
-  bool is_held(const PkgIterator &pkg);
-
-  bool all_upgrade(bool with_autoinst, undo_group *undo);
-  // Wrapper for pkgAllUpgrade (the engine of "apt-get upgrade")
-
-  /** If \b true, then a resolver has been created, indicating that
-      problems may exist.
-   */
-  bool resolver_exists() const;
-
-  /** Requires that resolver_exists() is \b true.
-   *
-   *  \param activate if \b true, enable debugging to cout.  Any
-   *  change to the state of any package will reset this to the
-   *  default (off).  \todo allow any ostream.
-   */
-  void set_resolver_debug(bool activate);
-
-  /** The number of solutions generated. */
-  unsigned int generated_solution_count() const;
-
-  /** Get the selection location, which will be in the range
-   *  [0,generated_solution_count()-1).  Note that this is meaningless
-   *  if generated_solution_count==0.
-   */
-  unsigned int get_selected_solution() const {return selected_solution;}
-
-  /** If \b true, all solutions have been generated. */
-  bool solution_generation_complete() const;
-
-  /** If \b true, then either there is no resolver, or the resolver
-   *  has been exhausted and the solution pointer is set to the last
-   *  solution.
-   */
-  bool solutions_exhausted() const;
-
-  /** If \b true, the solution pointer is set to the first
-   *  solution.
-   */
-  bool solutions_at_start() const;
-
-  // NB: the reason for returning references below is because
-  // otherwise you have circular dependencies between code and nothing
-  // compiles :(
-
-  /** Requires that resolver_exists() is \b true.  If no solutions
-   *  have been calculated yet, will calculate and return the first
-   *  solution.
-   *
-   *  \return the currently selected solution.  This reference is not
-   *  guaranteed to persist if any other operation is performed on the
-   *  cache; a stack variable should be instantiated from it.
-   *
-   *  \throws NoMoreSolutions if there are no solutions and the search
-   *  is exhausted.
-   *
-   *  \throws NoMoreTime if there are no solutions and the last effort
-   *  ran out of time.
-   */
-  const generic_solution<aptitude_universe> &get_current_solution();
-
   /** Apply the given solution as a resolver result; any actions
    *  that it requests will be marked as having been performed to
    *  fulfill dependencies.
@@ -429,119 +338,13 @@
   void apply_solution(const generic_solution<aptitude_universe> &solution,
 		      undo_group *undo);
 
-  /** Requires that resolver_exists() is \b true.  If no solutions
-   *  have been calculated yet, will calculate and apply the first
-   *  solution.
-   *
-   *  \param undo an undo group in which to accumulate the actions of
-   *  the current solution.  If an exception is thrown, undo was not
-   *  used and can be discarded.
-   *
-   *  \throws NoMoreSolutions if there are no solutions and the search
-   *  is exhausted.
-   *
-   *  \throws NoMoreTime if there are no solutions and the last effort
-   *  ran out of time.
-   */
-  void apply_current_solution(undo_group *undo);
-
-  /** Requires that resolver_exists() is \b true.  Temporarily rejects
-   *  any solutions generated by the currently active installer that
-   *  involve installing the given version.  This is distinct from our
-   *  own version forbidding mechanism in that it completely prevents
-   *  the generation of solutions containing this version, but it
-   *  doesn't outlast a single resolution session.
-   */
-  void resolver_reject_version(const aptitude_resolver_version &ver);
-
-  /** Requires that resolver_exists() is \b true.  Cancels a
-   *  rejection created via resolver_reject_version().
-   */
-  void resolver_unreject_version(const aptitude_resolver_version &ver);
-
-  /** Requires the resolver_exists() is \b true.  Returns \b true if
-   *  the given version is currently rejected.
-   */
-  bool resolver_is_rejected(const aptitude_resolver_version &ver);
-
-  /** Requires that resolver_exists() is \b true.  Like
-   *  resolver_reject_version, but rejects any solution that does \b
-   *  not install the given version.
-   */
-  void resolver_mandate_version(const aptitude_resolver_version &ver);
-
-  /** Cancels a resolver_mandate_version call. */
-  void resolver_unmandate_version(const aptitude_resolver_version &ver);
-
-  /** \return \b true if the given version is mandatory. */
-  bool resolver_is_mandatory(const aptitude_resolver_version &ver);
-
-
-
-  /** Requires that resolver_exists is \b true.  Force the resolver to
-   *  treat the given soft dependency as a hard dependency; as above,
-   *  you can always cancel this instruction later.
-   */
-  void resolver_harden_dep(const aptitude_resolver_dep &dep);
-
-  /** Cancels a resolver_harden_dep call. */
-  void resolver_unharden_dep(const aptitude_resolver_dep &dep);
-
-  /** \return \b true if the given dep is hardened. */
-  bool resolver_is_hardened(const aptitude_resolver_dep &dep);
-
-  /** Requires that resolver_exists is \b true.  Force the resolver to
-   *  leave the given soft dependency broken.
-   */
-  void resolver_force_break_dep(const aptitude_resolver_dep &dep);
-
-  /** Cancels a resolver_force_break_dep call. */
-  void resolver_unforce_break_dep(const aptitude_resolver_dep &dep);
-
-  /** \return \b true if the given dep is forced-broken. */
-  bool resolver_is_forced_broken(const aptitude_resolver_dep &dep);
-
-
-
-  /** Advance to the next solution.
-   *
-   *  \return the next solution.  This reference is not guaranteed to
-   *  persist if any other operation is performed on the cache; a
-   *  stack variable should be instantiated from it.
-   *
-   *  \throws NoMoreSolutions if there are no more solutions
-   *  \throws NoMoreTime if a solution could not be found before the
-   *                     cutoff time expired.
-   */
-  const generic_solution<aptitude_universe> &next_solution();
-
-  /** Return to the previous solution.
-   *
-   *  \return the previous solution.  This reference is not guaranteed
-   *  to persist if any other operation is performed on the cache; a
-   *  stack variable should be instantiated from it.
-   *
-   *  \throws NoMoreSolutions if solutions_at_start()==0
+  /** \return \b true if automatic aptitude upgrades should ignore this
+   *  package.
    */
-  const generic_solution<aptitude_universe> &previous_solution();
-
-  /** Tweak the resolver score of a particular package/version.  This
-   *  requires that resolver_exists() and that the resolver is "fresh"
-   *  (i.e., that next_solution() and current_solution() have never
-   *  been called)
-   *
-   *  \param pkg the package to adjust
-   *  \param ver the version to adjust
-   *  \param score an adjustment to be added to the score of pkg:ver
-   */
-  void tweak_score(const pkgCache::PkgIterator &pkg,
-		   const pkgCache::VerIterator &ver,
-		   int score);
+  bool is_held(const PkgIterator &pkg);
 
-  /** If a resolver exists, write its state (including scores, etc)
-   *  to the given stream.
-   */
-  void dump_resolver(std::ostream &out);
+  bool all_upgrade(bool with_autoinst, undo_group *undo);
+  // Wrapper for pkgAllUpgrade (the engine of "apt-get upgrade")
 
   bool try_fix_broken(undo_group *undo);
   // Attempts to fix any broken packages, dumping the changes the problem
@@ -569,12 +372,6 @@
    */
   sigc::signal0<void> package_state_changed;
 
-  /** This signal is emitted when the selected solution changes, or
-   *  when the user takes an action that might change the number of
-   *  available solutions (such as un-rejecting a package).
-   */
-  sigc::signal0<void> selected_solution_changed;
-
   // Emitted when a package's categorization is potentially changed.
   // (in particular, when package "new" states are forgotten)
   sigc::signal0<void> package_category_changed;

Added: branches/aptitude-0.3/aptitude/src/generic/resolver_manager.cc
==============================================================================
--- (empty file)
+++ branches/aptitude-0.3/aptitude/src/generic/resolver_manager.cc	Wed Sep 14 19:55:38 2005
@@ -0,0 +1,340 @@
+// resolver_manager.cc
+//
+//   Copyright (C) 2005 Daniel Burrows
+//
+//   This program is free software; you can redistribute it and/or
+//   modify it under the terms of the GNU General Public License as
+//   published by the Free Software Foundation; either version 2 of
+//   the License, or (at your option) any later version.
+//
+//   This program is distributed in the hope that it will be useful,
+//   but WITHOUT ANY WARRANTY; without even the implied warranty of
+//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//   General Public License for more details.
+//
+//   You should have received a copy of the GNU General Public License
+//   along with this program; see the file COPYING.  If not, write to
+//   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+//   Boston, MA 02111-1307, USA.
+
+#include "resolver_manager.h"
+
+#include "apt.h"
+#include "aptitude_resolver.h"
+#include "aptitude_resolver_universe.h"
+#include "config_signal.h"
+
+#include "problemresolver/problemresolver.h"
+
+#include <sigc++/functors/mem_fun.h>
+
+resolver_manager::resolver_manager(aptitudeDepCache *_cache)
+  :cache(_cache), resolver(0), selected_solution(0), out_of_time(false)
+{
+  cache->pre_package_state_changed.connect(sigc::mem_fun(this, &resolver_manager::discard_resolver));
+  cache->package_state_changed.connect(sigc::mem_fun(this, &resolver_manager::maybe_create_resolver));
+
+  aptcfg->connect(PACKAGE "::Recommends-Important",
+		  sigc::mem_fun(this,
+				&resolver_manager::discard_resolver));
+}
+
+resolver_manager::~resolver_manager()
+{
+  delete resolver;
+
+  for(unsigned int i = 0; i < solutions.size(); ++i)
+    delete solutions[i];
+}
+
+void resolver_manager::maybe_create_resolver()
+{
+  if(cache->BrokenCount() > 0)
+    create_resolver();
+}
+
+void resolver_manager::discard_resolver()
+{
+  delete resolver;
+  solutions.clear();
+  resolver=NULL;
+  out_of_time=false;
+}
+
+void resolver_manager::create_resolver()
+{
+  assert(resolver==NULL);
+
+  // NOTE: the performance of the resolver is highly sensitive to
+  // these settings; choosing bad ones can result in hitting
+  // exponential cases in practical situations.  In general,
+  // penalizing actions means that the resolver will be more likely to
+  // blow up trying to avoid them, with the danger increasing as the
+  // penalty does.  Thus, aside from broken deps (which are penalized
+  // to guide us towards a solution), I only penalize removals (which
+  // are usually either unnecessary or easy to prove necessary) and
+  // leaving soft dependencies (recommendations) unfixed.  The
+  // relative penalties of these are also important; for instance,
+  // penalizing unfixed soft deps more than removals means that the
+  // resolver will actually remove packages rather than leaving their
+  // Recommends: field unsatisfied!
+
+  resolver=new aptitude_resolver(aptcfg->FindI(PACKAGE "::ProblemResolver::StepScore", 10),
+				 aptcfg->FindI(PACKAGE "::ProblemResolver::BrokenScore", -100),
+				 aptcfg->FindI(PACKAGE "::ProblemResolver::UnfixedSoftScore", -200),
+				 aptcfg->FindI(PACKAGE "::ProblemResolver::Infinity", 1000000),
+				 aptcfg->FindI(PACKAGE "::ProblemResolver::Max-Successors", 0),
+				 aptcfg->FindI(PACKAGE "::ProblemResolver::ResolutionScore", 50),
+				 cache);
+
+  resolver->add_action_scores(aptcfg->FindI(PACKAGE "::ProblemResolver::PreserveManualScore", 60),
+			      aptcfg->FindI(PACKAGE "::ProblemResolver::PreserveAutoScore", 0),
+			      aptcfg->FindI(PACKAGE "::ProblemResolver::RemoveScore", -300),
+			      aptcfg->FindI(PACKAGE "::ProblemResolver::KeepScore", 0),
+			      aptcfg->FindI(PACKAGE "::ProblemResolver::InstallScore", -20),
+			      aptcfg->FindI(PACKAGE "::ProblemResolver::UpgradeScore", 0),
+			      aptcfg->FindI(PACKAGE "::ProblemResolver::NonDefaultScore", -40),
+			      aptcfg->FindI(PACKAGE "::ProblemResolver::EssentialRemoveScore", -100000),
+			      aptcfg->FindI(PACKAGE "::ProblemResolver::BreakHoldScore", -300));
+
+  resolver->add_priority_scores(aptcfg->FindI(PACKAGE "::ProblemResolver::ImportantScore", 5),
+				aptcfg->FindI(PACKAGE "::ProblemResolver::RequiredScore", 4),
+				aptcfg->FindI(PACKAGE "::ProblemResolver::StandardScore", 3),
+				aptcfg->FindI(PACKAGE "::ProblemResolver::OptionalScore", 1),
+				aptcfg->FindI(PACKAGE "::ProblemResolver::ExtraScore", -1));
+}
+
+void resolver_manager::set_debug(bool activate)
+{
+  assert(resolver_exists());
+
+  resolver->set_debug(activate);
+}
+
+bool resolver_manager::resolver_exists() const
+{
+  return resolver != NULL;
+}
+
+unsigned int resolver_manager::generated_solution_count() const
+{
+  return solutions.size();
+}
+
+bool resolver_manager::solution_generation_complete() const
+{
+  return resolver->exhausted();
+}
+
+bool resolver_manager::solutions_exhausted() const
+{
+  if(!resolver_exists())
+    return true;
+  else
+    return selected_solution+1 == generated_solution_count() &&
+      solution_generation_complete();
+}
+
+bool resolver_manager::solutions_at_start() const
+{
+  if(!resolver_exists())
+    return true;
+  else
+    return selected_solution == 0;
+}
+
+const aptitude_resolver::solution &resolver_manager::get_current_solution()
+{
+  assert(resolver);
+
+  if(out_of_time)
+    throw NoMoreTime();
+  else if(!solutions.empty())
+    return *solutions[selected_solution];
+  else
+    return next_solution();
+}
+
+// At the moment the undo argument is ignored; it's there for future
+// use.
+void resolver_manager::reject_version(const aptitude_resolver_version &ver)
+{
+  assert(resolver);
+
+  resolver->reject_version(ver);
+}
+
+void resolver_manager::unreject_version(const aptitude_resolver_version &ver)
+{
+  assert(resolver);
+
+  resolver->unreject_version(ver);
+
+  selected_solution_changed();
+}
+
+bool resolver_manager::is_rejected(const aptitude_resolver_version &ver)
+{
+  assert(resolver);
+
+  return resolver->is_rejected(ver);
+}
+
+void resolver_manager::mandate_version(const aptitude_resolver_version &ver)
+{
+  assert(resolver);
+
+  resolver->mandate_version(ver);
+}
+
+void resolver_manager::unmandate_version(const aptitude_resolver_version &ver)
+{
+  assert(resolver);
+
+  resolver->unmandate_version(ver);
+
+  selected_solution_changed();
+}
+
+bool resolver_manager::is_mandatory(const aptitude_resolver_version &ver)
+{
+  assert(resolver);
+
+  return resolver->is_mandatory(ver);
+}
+
+void resolver_manager::harden_dep(const aptitude_resolver_dep &dep)
+{
+  assert(resolver);
+
+  resolver->harden(dep);
+}
+
+void resolver_manager::unharden_dep(const aptitude_resolver_dep &dep)
+{
+  assert(resolver);
+
+  resolver->unharden(dep);
+
+  selected_solution_changed();
+}
+
+bool resolver_manager::is_hardened(const aptitude_resolver_dep &dep)
+{
+  assert(resolver);
+
+  return resolver->is_hardened(dep);
+}
+
+void resolver_manager::force_break_dep(const aptitude_resolver_dep &dep)
+{
+  assert(resolver);
+
+  resolver->force_break(dep);
+}
+
+void resolver_manager::unforce_break_dep(const aptitude_resolver_dep &dep)
+{
+  assert(resolver);
+
+  resolver->unforce_break(dep);
+
+  selected_solution_changed();
+}
+
+bool resolver_manager::is_forced_broken(const aptitude_resolver_dep &dep)
+{
+  assert(resolver);
+
+  return resolver->is_forced_broken(dep);
+}
+
+
+const aptitude_resolver::solution &resolver_manager::next_solution()
+{
+  if(solutions.empty())
+    {
+      try
+	{
+	  solutions.push_back(new aptitude_resolver::solution(resolver->find_next_solution(aptcfg->FindI(PACKAGE "::ProblemResolver::StepLimit", 5000))));
+	  selected_solution=0;
+	  out_of_time=false;
+	  selected_solution_changed();
+	  return *solutions.back();
+	}
+      catch(NoMoreTime) {
+	out_of_time=true;
+	throw NoMoreTime();
+      }
+      catch(NoMoreSolutions) {
+	selected_solution_changed();
+	throw NoMoreSolutions();
+      }
+    }
+  else if(selected_solution<solutions.size()-1)
+    {
+      ++selected_solution;
+      selected_solution_changed();
+      return *solutions[selected_solution];
+    }
+  else
+    {
+      // otherwise weirdness is happening.
+      assert(!out_of_time);
+
+      try
+	{
+	  solutions.push_back(new aptitude_resolver::solution(resolver->find_next_solution(aptcfg->FindI(PACKAGE "::ProblemResolver::StepLimit", 5000))));
+	}
+      catch(NoMoreSolutions)
+	{
+	  selected_solution_changed();
+	  throw NoMoreSolutions();
+	}
+      ++selected_solution;
+      selected_solution_changed();
+      return *solutions.back();
+    }
+}
+
+const aptitude_resolver::solution &resolver_manager::previous_solution()
+{
+  if(solutions.empty() || selected_solution == 0)
+    throw NoMoreSolutions();
+
+  --selected_solution;
+  selected_solution_changed();
+  return *solutions[selected_solution];
+}
+
+void resolver_manager::tweak_score(const pkgCache::PkgIterator &pkg,
+				   const pkgCache::VerIterator &ver,
+				   int score)
+{
+  assert(resolver_exists());
+  assert(resolver->fresh());
+
+  resolver->add_version_score(aptitude_resolver_version(pkg, ver, cache),
+			      score);
+}
+
+void resolver_manager::dump(ostream &out) const
+{
+  if(!resolver_exists())
+    return;
+
+  // First, dump the universe.
+  dump_universe(resolver->get_universe(), out);
+
+  // Now dump the scores as a test instruction.
+  out << "TEST " << resolver->get_step_score() << " "
+      << resolver->get_broken_score() << " "
+      << resolver->get_unresolved_soft_dep_score() << " "
+      << resolver->get_infinity() << " "
+      << resolver->get_max_successors() << " "
+      << resolver->get_full_solution_score() << " ";
+
+  resolver->dump_scores(out);
+
+  out << "EXPECT ( " << aptcfg->FindI(PACKAGE "::Resolver::StepLimit", 5000) << " ANY )" << std::endl;
+}

Added: branches/aptitude-0.3/aptitude/src/generic/resolver_manager.h
==============================================================================
--- (empty file)
+++ branches/aptitude-0.3/aptitude/src/generic/resolver_manager.h	Wed Sep 14 19:55:38 2005
@@ -0,0 +1,242 @@
+// resolver_manager.h                                -*-c++-*-
+//
+//   Copyright (C) 2005 Daniel Burrows
+//
+//   This program is free software; you can redistribute it and/or
+//   modify it under the terms of the GNU General Public License as
+//   published by the Free Software Foundation; either version 2 of
+//   the License, or (at your option) any later version.
+//
+//   This program is distributed in the hope that it will be useful,
+//   but WITHOUT ANY WARRANTY; without even the implied warranty of
+//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+//   General Public License for more details.
+//
+//   You should have received a copy of the GNU General Public License
+//   along with this program; see the file COPYING.  If not, write to
+//   the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+//   Boston, MA 02111-1307, USA.
+//
+// A higher-level resolver interface.  This code is responsible for
+// maintaining a list of previously observed solutions, for passing
+// certain actions on to the underlying resolver (protecting users
+// from having to actually import the whole resolver definition), and
+// for managing the resolver in the face of cache reloads and resets.
+
+#ifndef RESOLVER_MANAGER_H
+#define RESOLVER_MANAGER_H
+
+#include <apt-pkg/pkgcache.h>
+
+#include <sigc++/signal.h>
+#include <sigc++/trackable.h>
+
+#include <vector>
+
+class aptitudeDepCache;
+class aptitude_universe;
+class aptitude_resolver_version;
+class aptitude_resolver_dep;
+template<typename PackageUniverse> class generic_solution;
+class aptitude_resolver;
+
+class resolver_manager : public sigc::trackable
+{
+  /** The cache file on which this manager operates. */
+  aptitudeDepCache *cache;
+
+  /** The active resolver, or \b NULL if none is active. */
+  aptitude_resolver *resolver;
+
+  /** The solutions generated by this manager since the last change to
+   *  the cache.
+   */
+  std::vector<generic_solution<aptitude_universe> *> solutions;
+
+  /** The index of the currently selected solution. */
+  unsigned int selected_solution;
+
+  /** If \b true, there are no solutions and the last attempt to
+   *  calculate one failed with NoMoreTime.
+   *
+   *  This is used so that the return value of get_current_solution()
+   *  is stable.
+   */
+  bool out_of_time;
+
+  void discard_resolver();
+  void create_resolver();
+
+  /** Create a resolver if necessary. */
+  void maybe_create_resolver();
+public:
+  /** Create a new resolver manager for the given cache file. */
+  resolver_manager(aptitudeDepCache *cache);
+
+  virtual ~resolver_manager();
+
+  /** If \b true, then a resolver has been created, indicating that
+   *  problems may exist in the cache.
+   */
+  bool resolver_exists() const;
+
+
+  /** Requires that resolver_exists() is \b true.
+   *
+   *  \param activate if \b true, enable debugging to cout.  Any
+   *  change to the state of any package will reset this to the
+   *  default (off).  \todo allow any ostream.
+   */
+  void set_debug(bool activate);
+
+  /** The number of solutions generated. */
+  unsigned int generated_solution_count() const;
+
+  /** Get the selection location, which will be in the range
+   *  [0,generated_solution_count()-1).  Note that this is meaningless
+   *  if generated_solution_count==0.
+   */
+  unsigned int get_selected_solution() const {return selected_solution;}
+
+
+  /** If \b true, all solutions have been generated. */
+  bool solution_generation_complete() const;
+
+  /** If \b true, then either there is no resolver, or the resolver
+   *  has been exhausted and the solution pointer is set to the last
+   *  solution.
+   */
+  bool solutions_exhausted() const;
+
+  /** If \b true, the solution pointer is set to the first
+   *  solution.
+   */
+  bool solutions_at_start() const;
+
+  // NB: the reason for returning references below is because
+  // otherwise you have circular dependencies between code and nothing
+  // compiles :(
+
+  /** Requires that resolver_exists() is \b true.  If no solutions
+   *  have been calculated yet, will calculate and return the first
+   *  solution.
+   *
+   *  \return the currently selected solution.  This reference is not
+   *  guaranteed to persist if any other operation is performed on the
+   *  cache; a stack variable should be instantiated from it.
+   *
+   *  \throws NoMoreSolutions if there are no solutions and the search
+   *  is exhausted.
+   *
+   *  \throws NoMoreTime if there are no solutions and the last effort
+   *  ran out of time.
+   */
+  const generic_solution<aptitude_universe> &get_current_solution();
+
+
+  /** Requires that resolver_exists() is \b true.  Temporarily rejects
+   *  any solutions generated by the currently active installer that
+   *  involve installing the given version.  This is distinct from our
+   *  own version forbidding mechanism in that it completely prevents
+   *  the generation of solutions containing this version, but it
+   *  doesn't outlast a single resolution session.
+   */
+  void reject_version(const aptitude_resolver_version &ver);
+
+  /** Requires that resolver_exists() is \b true.  Cancels a
+   *  rejection created via resolver_reject_version().
+   */
+  void unreject_version(const aptitude_resolver_version &ver);
+
+  /** Requires the resolver_exists() is \b true.  Returns \b true if
+   *  the given version is currently rejected.
+   */
+  bool is_rejected(const aptitude_resolver_version &ver);
+
+  /** Requires that resolver_exists() is \b true.  Like
+   *  resolver_reject_version, but rejects any solution that does \b
+   *  not install the given version.
+   */
+  void mandate_version(const aptitude_resolver_version &ver);
+
+  /** Cancels a resolver_mandate_version call. */
+  void unmandate_version(const aptitude_resolver_version &ver);
+
+  /** \return \b true if the given version is mandatory. */
+  bool is_mandatory(const aptitude_resolver_version &ver);
+
+
+
+  /** Requires that resolver_exists is \b true.  Force the resolver to
+   *  treat the given soft dependency as a hard dependency; as above,
+   *  you can always cancel this instruction later.
+   */
+  void harden_dep(const aptitude_resolver_dep &dep);
+
+  /** Cancels a resolver_harden_dep call. */
+  void unharden_dep(const aptitude_resolver_dep &dep);
+
+  /** \return \b true if the given dep is hardened. */
+  bool is_hardened(const aptitude_resolver_dep &dep);
+
+  /** Requires that resolver_exists is \b true.  Force the resolver to
+   *  leave the given soft dependency broken.
+   */
+  void force_break_dep(const aptitude_resolver_dep &dep);
+
+  /** Cancels a resolver_force_break_dep call. */
+  void unforce_break_dep(const aptitude_resolver_dep &dep);
+
+  /** \return \b true if the given dep is forced-broken. */
+  bool is_forced_broken(const aptitude_resolver_dep &dep);
+
+
+
+  /** Advance to the next solution.
+   *
+   *  \return the next solution.  This reference is not guaranteed to
+   *  persist if any other operation is performed on the cache; a
+   *  stack variable should be instantiated from it.
+   *
+   *  \throws NoMoreSolutions if there are no more solutions
+   *  \throws NoMoreTime if a solution could not be found before the
+   *                     cutoff time expired.
+   */
+  const generic_solution<aptitude_universe> &next_solution();
+
+  /** Return to the previous solution.
+   *
+   *  \return the previous solution.  This reference is not guaranteed
+   *  to persist if any other operation is performed on the cache; a
+   *  stack variable should be instantiated from it.
+   *
+   *  \throws NoMoreSolutions if solutions_at_start()==0
+   */
+  const generic_solution<aptitude_universe> &previous_solution();
+
+  /** Tweak the resolver score of a particular package/version.  This
+   *  requires that resolver_exists() and that the resolver is "fresh"
+   *  (i.e., that next_solution() and current_solution() have never
+   *  been called)
+   *
+   *  \param pkg the package to adjust
+   *  \param ver the version to adjust
+   *  \param score an adjustment to be added to the score of pkg:ver
+   */
+  void tweak_score(const pkgCache::PkgIterator &pkg,
+		   const pkgCache::VerIterator &ver,
+		   int score);
+
+  /** If a resolver exists, write its state (including scores, etc)
+   *  to the given stream.
+   */
+  void dump(std::ostream &out) const;
+
+  /** This signal is emitted when the selected solution changes, or
+   *  when the user takes an action that might change the number of
+   *  available solutions (such as un-rejecting a package).
+   */
+  sigc::signal0<void> selected_solution_changed;
+};
+
+#endif

Modified: branches/aptitude-0.3/aptitude/src/solution_dialog.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/solution_dialog.cc	(original)
+++ branches/aptitude-0.3/aptitude/src/solution_dialog.cc	Wed Sep 14 19:55:38 2005
@@ -37,6 +37,7 @@
 #include <generic/aptitude_resolver_universe.h>
 #include <generic/problemresolver/exceptions.h>
 #include <generic/problemresolver/solution.h>
+#include <generic/resolver_manager.h>
 
 #include <sigc++/bind.h>
 
@@ -51,7 +52,7 @@
     if(apt_cache_file)
       {
 	(*apt_cache_file)->package_state_changed.connect(sigc::mem_fun(*this, &solution_dialog::update));
-	(*apt_cache_file)->selected_solution_changed.connect(sigc::mem_fun(*this, &solution_dialog::update));
+	resman->selected_solution_changed.connect(sigc::mem_fun(*this, &solution_dialog::update));
       }
 
     update();
@@ -63,7 +64,7 @@
     if(apt_cache_file)
       {
 	(*apt_cache_file)->package_state_changed.connect(sigc::mem_fun(*this, &solution_dialog::update));
-	(*apt_cache_file)->selected_solution_changed.connect(sigc::mem_fun(*this, &solution_dialog::update));
+	resman->selected_solution_changed.connect(sigc::mem_fun(*this, &solution_dialog::update));
       }
 
     cache_closed.connect(sigc::mem_fun(*this, &solution_dialog::update));
@@ -87,7 +88,7 @@
 	return;
       }
 
-    if(!(*apt_cache_file)->resolver_exists())
+    if(!resman->resolver_exists())
       {
 	// This makes ASS-U-MPTIONS about how resolver_exists works.
 	set_fragment(fragf("%s", _("No packages are broken.")));
@@ -97,7 +98,7 @@
 
     try
       {
-	aptitude_solution sol=(*apt_cache_file)->get_current_solution();
+	aptitude_solution sol = resman->get_current_solution();
 
 	if(sol == last_sol)
 	  return;

Modified: branches/aptitude-0.3/aptitude/src/solution_screen.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/solution_screen.cc	(original)
+++ branches/aptitude-0.3/aptitude/src/solution_screen.cc	Wed Sep 14 19:55:38 2005
@@ -25,6 +25,7 @@
 #include <generic/aptitude_resolver_universe.h>
 #include <generic/problemresolver/exceptions.h>
 #include <generic/problemresolver/solution.h>
+#include <generic/resolver_manager.h>
 #include <generic/util.h>
 
 #include <vscreen/fragment.h>
@@ -240,37 +241,37 @@
 
   bool is_rejected()
   {
-    assert((*apt_cache_file)->resolver_exists());
+    assert(resman->resolver_exists());
 
-    return (*apt_cache_file)->resolver_is_rejected(ver);
+    return resman->is_rejected(ver);
   }
 
   // Dual of rejecting.
   bool is_mandatory()
   {
-    assert((*apt_cache_file)->resolver_exists());
+    assert(resman->resolver_exists());
 
-    return (*apt_cache_file)->resolver_is_mandatory(ver);
+    return resman->is_mandatory(ver);
   }
 
   void reject()
   {
-    (*apt_cache_file)->resolver_reject_version(ver);
+    resman->reject_version(ver);
   }
 
   void unreject()
   {
-    (*apt_cache_file)->resolver_unreject_version(ver);
+    resman->unreject_version(ver);
   }
 
   void mandate()
   {
-    (*apt_cache_file)->resolver_mandate_version(ver);
+    resman->mandate_version(ver);
   }
 
   void unmandate()
   {
-    (*apt_cache_file)->resolver_unmandate_version(ver);
+    resman->unmandate_version(ver);
   }
 
   aptitude_universe::version get_ver() const
@@ -550,34 +551,34 @@
 
   bool is_rejected()
   {
-    return (*apt_cache_file)->resolver_is_hardened(d);
+    return resman->is_hardened(d);
     return false;
   }
 
   bool is_mandatory()
   {
-    return (*apt_cache_file)->resolver_is_forced_broken(d);
+    return resman->is_forced_broken(d);
     return false;
   }
 
   void reject()
   {
-    (*apt_cache_file)->resolver_harden_dep(d);
+    resman->harden_dep(d);
   }
 
   void unreject()
   {
-    (*apt_cache_file)->resolver_unharden_dep(d);
+    resman->unharden_dep(d);
   }
 
   void mandate()
   {
-    (*apt_cache_file)->resolver_force_break_dep(d);
+    resman->force_break_dep(d);
   }
 
   void unmandate()
   {
-    (*apt_cache_file)->resolver_unforce_break_dep(d);
+    resman->unforce_break_dep(d);
   }
 
   void paint(vs_tree *win, int y, bool hierarchical, const style &st)
@@ -766,7 +767,7 @@
     if(apt_cache_file)
       {
 	(*apt_cache_file)->package_state_changed.connect(sigc::mem_fun(*this, &solution_screen::update));
-	(*apt_cache_file)->selected_solution_changed.connect(sigc::mem_fun(*this, &solution_screen::update));
+	resman->selected_solution_changed.connect(sigc::mem_fun(*this, &solution_screen::update));
       }
   }
 
@@ -824,7 +825,7 @@
 	return;
       }
 
-    if(!(*apt_cache_file)->resolver_exists())
+    if(!resman->resolver_exists())
       {
 	// No packages are broken; remove this screen.
 	destroy();
@@ -833,7 +834,7 @@
 
     try
       {
-	aptitude_solution sol=(*apt_cache_file)->get_current_solution();
+	aptitude_solution sol = resman->get_current_solution();
 
 	if(sol == last_sol)
 	  return;

Modified: branches/aptitude-0.3/aptitude/src/ui.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/ui.cc	(original)
+++ branches/aptitude-0.3/aptitude/src/ui.cc	Wed Sep 14 19:55:38 2005
@@ -82,6 +82,7 @@
 #include <generic/config_signal.h>
 #include <generic/problemresolver/exceptions.h>
 #include <generic/problemresolver/solution.h>
+#include <generic/resolver_manager.h>
 #include <generic/util.h>
 
 #include "dep_item.h"
@@ -1047,11 +1048,11 @@
 
   try
     {
-      assert((*apt_cache_file)->resolver_exists());
+      assert(resman->resolver_exists());
 
-      aptitude_solution sol=(*apt_cache_file)->get_current_solution();
+      aptitude_solution sol = resman->get_current_solution();
 
-      (*apt_cache_file)->apply_current_solution(undo);
+      (*apt_cache_file)->apply_solution(sol, undo);
       show_message(fragf("%s%n%n%F",
 			 _("Some packages were broken and have been fixed:"),
 			 solution_fragment(sol)),
@@ -1425,10 +1426,10 @@
 
 void do_next_solution()
 {
-  if(apt_cache_file && !(*apt_cache_file)->solutions_exhausted())
+  if(apt_cache_file && !resman->solutions_exhausted())
     try
       {
-	(*apt_cache_file)->next_solution();
+	resman->next_solution();
       }
     catch(NoMoreSolutions)
       {
@@ -1446,20 +1447,21 @@
 
 void do_previous_solution()
 {
-  if(apt_cache_file && !(*apt_cache_file)->solutions_at_start())
-    (*apt_cache_file)->previous_solution();
+  if(apt_cache_file && !resman->solutions_at_start())
+    resman->previous_solution();
   else
     beep();
 }
 
 void do_apply_solution()
 {
-  if(apt_cache_file && (*apt_cache_file)->resolver_exists())
+  if(apt_cache_file && resman->resolver_exists())
     {
       undo_group *undo=new apt_undo_group;
       try
 	{
-	  (*apt_cache_file)->apply_current_solution(undo);
+	  (*apt_cache_file)->apply_solution(resman->get_current_solution(),
+					    undo);
 	}
       catch(NoMoreSolutions)
 	{
@@ -1506,7 +1508,7 @@
 
 static void handle_dump_resolver_response(const wstring &s)
 {
-  if((*apt_cache_file)->resolver_exists())
+  if(resman->resolver_exists())
     {
       ofstream out(transcode(s).c_str());
 
@@ -1514,7 +1516,7 @@
 	_error->Errno("dump_resolver", _("Unable to open %ls"), s.c_str());
       else
 	{
-	  (*apt_cache_file)->dump_resolver(out);
+	  resman->dump(out);
 
 	  if(!out)
 	    _error->Errno("dump_resolver", _("Error while dumping resolver state"));
@@ -1526,7 +1528,7 @@
 {
   static vs_editline::history_list history;
 
-  if((*apt_cache_file)->resolver_exists())
+  if(resman->resolver_exists())
     prompt_string(_("File to which the resolver state should be dumped:"),
 		  "",
 		  arg(sigc::ptr_fun(handle_dump_resolver_response)),
@@ -2003,7 +2005,7 @@
   //
   // Note that it *should* be visible if we enter this code from the
   // command-line (i.e., with the cache already loaded).  More hack?
-  if(apt_cache_file && (*apt_cache_file)->resolver_exists())
+  if(resman->resolver_exists())
     b->show();
   else
     b->hide();



More information about the Aptitude-svn-commit mailing list