[Aptitude-svn-commit] r3871 - in branches/aptitude-0.3/aptitude: .
src/generic
Daniel Burrows
dburrows at costa.debian.org
Tue Aug 16 23:00:13 UTC 2005
Author: dburrows
Date: Tue Aug 16 23:00:09 2005
New Revision: 3871
Modified:
branches/aptitude-0.3/aptitude/ChangeLog
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/aptitude_resolver_universe.cc
branches/aptitude-0.3/aptitude/src/generic/aptitude_resolver_universe.h
Log:
Memoize is_interesting_dep.
Modified: branches/aptitude-0.3/aptitude/ChangeLog
==============================================================================
--- branches/aptitude-0.3/aptitude/ChangeLog (original)
+++ branches/aptitude-0.3/aptitude/ChangeLog Tue Aug 16 23:00:09 2005
@@ -1,5 +1,15 @@
2005-08-16 Daniel Burrows <dburrows at debian.org>
+ * src/generic/aptcache.cc, src/generic/aptitude_resolver.cc, src/generic/aptitude_resolver_universe.cc, src/generic/aptitude_resolver_universe.h:
+
+ Memoize calls to is_interesting_dep(). The major change caused
+ by this is that objects in the aptitude_universe store
+ backpointers to the universe, not the cache (because calls to
+ is_interesting_dep need to go through the universe).
+
+ NB: is_interesting_dep could also be a global function in
+ apt.cc; would it be useful there?
+
* src/generic/aptitude_resolver_universe.cc:
Redefine is_interesting_dep in terms of "subsumption": a
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 Tue Aug 16 23:00:09 2005
@@ -48,6 +48,9 @@
using namespace std;
+enum interesting_state {uncached = 0, uninteresting, interesting};
+static interesting_state *cached_deps_interesting = NULL;
+
aptitudeCacheFile *apt_cache_file=NULL;
signalling_config *aptcfg=NULL;
pkgRecords *apt_package_records=NULL;
@@ -207,6 +210,11 @@
apt_source_list=NULL;
}
+ if(cached_deps_interesting)
+ {
+ delete[] cached_deps_interesting;
+ }
+
aptitudeCacheFile *new_file=new aptitudeCacheFile;
apt_source_list=new pkgSourceList;
@@ -487,3 +495,219 @@
return true;
}
+
+/** \return \b true if d1 subsumes d2; that is, if one of the
+ * following holds:
+ *
+ * (a) d1 and d2 target the same package and are unversioned.
+ *
+ * (b) d1 and d2 are unversioned and some version of d2's target
+ * provides the target package of d1.
+ *
+ * (c) d1 and d2 target the same package, d1 is unversioned, and d2
+ * is versioned.
+ *
+ * (c) d1 and d2 target the same package and are versioned
+ * (with op1 ver1 and op2 ver2 being the operations and versions)
+ * and:
+ *
+ * - op1 is >=, op2 is >>, >=, or =, and ver1 <= ver2; or
+ * - op1 is <=, op2 is <<, <=, or =, and ver1 >= ver2; or
+ * - op1 is >>, op2 is >>, and ver1 <= ver2; or
+ * - op1 is >>, op2 is =, and ver1 < ver2; or
+ * - op1 is <<, op2 is <<, and ver1 >= ver2; or
+ * - op1 is <<, op2 is =, and ver1 > ver2; or
+ * - op1 is =, op2 is =, and ver1 = ver2; or
+ * - op1 is !=, op2 is !=, and ver1 = ver2.
+ */
+static bool subsumes(const pkgCache::DepIterator &d1,
+ const pkgCache::DepIterator &d2)
+{
+ pkgCache::PkgIterator target1 = const_cast<pkgCache::DepIterator &>(d1).TargetPkg();
+ pkgCache::PkgIterator target2 = const_cast<pkgCache::DepIterator &>(d2).TargetPkg();
+
+ if(!d1.TargetVer())
+ {
+ if(target1 == target2)
+ return true;
+
+ if(d2.TargetVer())
+ return false;
+
+ for(pkgCache::PrvIterator p = target1.ProvidesList();
+ !p.end(); ++p)
+ if(p.OwnerPkg() == target2)
+ return true;
+
+ return false;
+ }
+ else
+ {
+ if(target1 != target2)
+ return false;
+
+ if(!d2.TargetVer())
+ return false;
+
+ pkgCache::Dep::DepCompareOp t1 = (pkgCache::Dep::DepCompareOp) (d1->CompareOp &~ pkgCache::Dep::Or);
+ pkgCache::Dep::DepCompareOp t2 = (pkgCache::Dep::DepCompareOp) (d2->CompareOp &~ pkgCache::Dep::Or);
+
+ int cmpresult = _system->VS->DoCmpVersion(d1.TargetVer(), d1.TargetVer()+strlen(d1.TargetVer()),
+ d2.TargetVer(), d2.TargetVer()+strlen(d2.TargetVer()));
+
+ switch(t1)
+ {
+ case pkgCache::Dep::LessEq:
+ return
+ (t2 == pkgCache::Dep::Less ||
+ t2 == pkgCache::Dep::LessEq ||
+ t2 == pkgCache::Dep::Equals) &&
+ cmpresult >= 0;
+ case pkgCache::Dep::GreaterEq:
+ return
+ (t2 == pkgCache::Dep::Greater ||
+ t2 == pkgCache::Dep::LessEq ||
+ t2 == pkgCache::Dep::Equals) &&
+ cmpresult <= 0;
+ case pkgCache::Dep::Less:
+ return
+ (t2 == pkgCache::Dep::Less && cmpresult >= 0) ||
+ (t2 == pkgCache::Dep::Equals && cmpresult > 0);
+ case pkgCache::Dep::Greater:
+ return
+ (t2 == pkgCache::Dep::Greater && cmpresult <= 0) ||
+ (t2 == pkgCache::Dep::Equals && cmpresult < 0);
+ case pkgCache::Dep::Equals:
+ return
+ (t2 == pkgCache::Dep::Equals && cmpresult == 0);
+ case pkgCache::Dep::NotEquals:
+ return
+ (t2 == pkgCache::Dep::NotEquals && cmpresult == 0);
+
+ // These shouldn't happen:
+ case pkgCache::Dep::NoOp:
+ default:
+ abort();
+ }
+ }
+}
+
+/** \return \b true if the OR group of d1 subsumes the OR group of d2:
+ * that is, if every member of the OR group containing d2 has a
+ * subsuming element in the OR group containing d1.
+ */
+static bool or_group_subsumes(const pkgCache::DepIterator &d1,
+ const pkgCache::DepIterator &d2)
+{
+ pkgCache::DepIterator start1, end1, start2, end2;
+
+ surrounding_or(d1, start1, end1);
+ surrounding_or(d2, start2, end2);
+
+ for(pkgCache::DepIterator i = d1; i != end1; ++i)
+ {
+ bool found = false;
+
+ for(pkgCache::DepIterator j = d2; j != end2; ++j)
+ if(subsumes(i, j))
+ {
+ found = true;
+ break;
+ }
+
+ if(!found)
+ return false;
+ }
+
+ return true;
+}
+
+
+// Interesting deps are:
+//
+// - All critical deps
+// - All recommendations that are currently satisfied
+// - All recommendations that are unrelated under subsumption to
+// each recommendation of the current package version.
+static bool internal_is_interesting_dep(const pkgCache::DepIterator &d,
+ pkgDepCache *cache)
+{
+ if(const_cast<pkgCache::DepIterator &>(d).IsCritical())
+ return true;
+ else if(d->Type != pkgCache::Dep::Recommends)
+ return false;
+ else
+ {
+ pkgCache::DepIterator dtmp = d;
+ while(!dtmp.end() && dtmp->CompareOp & pkgCache::Dep::Or)
+ ++dtmp;
+ if((*cache)[d] & pkgDepCache::DepGNow)
+ return true;
+
+ pkgCache::VerIterator currver = const_cast<pkgCache::DepIterator &>(d).ParentPkg().CurrentVer();
+ pkgCache::VerIterator parver = const_cast<pkgCache::DepIterator &>(d).ParentVer();
+
+ if(currver == parver)
+ return false;
+ else if(currver.end())
+ return true;
+ else
+ // Check whether the current version of this package has a dep
+ // that either subsumes _or is subsumed by_ this
+ // recommendation. (for mathematical "correctness" we'd only
+ // check the first direction, but the goal is to not annoy the
+ // user unnecessarily; losing a few new recommendations is OK)
+ //
+ // NB: full correctness without annoyance means actually
+ // TRIMMING DOWN the target set of a recommendation by
+ // subtracting elements that are in the current version's
+ // recommendation list. Needless to say, I'm ignoring this
+ // for now.
+ {
+ pkgCache::DepIterator d2 = currver.DependsList();
+
+ while(!d2.end())
+ {
+ if(d2->Type == pkgCache::Dep::Recommends &&
+ or_group_subsumes(d2, d) || or_group_subsumes(d, d2))
+ return false;
+
+ while(!d2.end() && ((d2->CompareOp & pkgCache::Dep::Or) != 0))
+ ++d2;
+
+ if(!d2.end())
+ ++d2;
+ }
+
+ return true;
+ }
+ }
+}
+
+bool is_interesting_dep(const pkgCache::DepIterator &d,
+ pkgDepCache *cache)
+{
+ if(cached_deps_interesting == NULL)
+ {
+ cached_deps_interesting = new interesting_state[cache->Head().DependsCount];
+ for(unsigned long i = 0; i<cache->Head().DependsCount; ++i)
+ cached_deps_interesting[i] = uncached;
+ }
+
+ switch(cached_deps_interesting[d->ID])
+ {
+ case uncached:
+ {
+ bool rval = internal_is_interesting_dep(d, cache);
+
+ cached_deps_interesting[d->ID] = rval ? interesting : uninteresting;
+ return rval;
+ }
+ case interesting:
+ return true;
+ case uninteresting:
+ return false;
+ default:
+ abort();
+ }
+}
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 Tue Aug 16 23:00:09 2005
@@ -173,4 +173,15 @@
}
};
+/** \return \b true if the given dependency is "interesting":
+ * specifically, if it's either critical or a Recommends
+ * that's "new" or currently satisfied.
+ *
+ * \param d the dependency to test
+ * \param cache the cache in which to check d (used to find out whether
+ * d is currently satisfied).
+ */
+bool is_interesting_dep(const pkgCache::DepIterator &d,
+ pkgDepCache *cache);
+
#endif
Modified: branches/aptitude-0.3/aptitude/src/generic/aptitude_resolver_universe.cc
==============================================================================
--- branches/aptitude-0.3/aptitude/src/generic/aptitude_resolver_universe.cc (original)
+++ branches/aptitude-0.3/aptitude/src/generic/aptitude_resolver_universe.cc Tue Aug 16 23:00:09 2005
@@ -6,195 +6,6 @@
using namespace std;
-/** \return \b true if d1 subsumes d2; that is, if one of the
- * following holds:
- *
- * (a) d1 and d2 target the same package and are unversioned.
- *
- * (b) d1 and d2 are unversioned and some version of d2's target
- * provides the target package of d1.
- *
- * (c) d1 and d2 target the same package, d1 is unversioned, and d2
- * is versioned.
- *
- * (c) d1 and d2 target the same package and are versioned
- * (with op1 ver1 and op2 ver2 being the operations and versions)
- * and:
- *
- * - op1 is >=, op2 is >>, >=, or =, and ver1 <= ver2; or
- * - op1 is <=, op2 is <<, <=, or =, and ver1 >= ver2; or
- * - op1 is >>, op2 is >>, and ver1 <= ver2; or
- * - op1 is >>, op2 is =, and ver1 < ver2; or
- * - op1 is <<, op2 is <<, and ver1 >= ver2; or
- * - op1 is <<, op2 is =, and ver1 > ver2; or
- * - op1 is =, op2 is =, and ver1 = ver2; or
- * - op1 is !=, op2 is !=, and ver1 = ver2.
- */
-static bool subsumes(const pkgCache::DepIterator &d1,
- const pkgCache::DepIterator &d2)
-{
- pkgCache::PkgIterator target1 = const_cast<pkgCache::DepIterator &>(d1).TargetPkg();
- pkgCache::PkgIterator target2 = const_cast<pkgCache::DepIterator &>(d2).TargetPkg();
-
- if(!d1.TargetVer())
- {
- if(target1 == target2)
- return true;
-
- if(d2.TargetVer())
- return false;
-
- for(pkgCache::PrvIterator p = target1.ProvidesList();
- !p.end(); ++p)
- if(p.OwnerPkg() == target2)
- return true;
-
- return false;
- }
- else
- {
- if(target1 != target2)
- return false;
-
- if(!d2.TargetVer())
- return false;
-
- pkgCache::Dep::DepCompareOp t1 = (pkgCache::Dep::DepCompareOp) (d1->CompareOp &~ pkgCache::Dep::Or);
- pkgCache::Dep::DepCompareOp t2 = (pkgCache::Dep::DepCompareOp) (d2->CompareOp &~ pkgCache::Dep::Or);
-
- int cmpresult = _system->VS->DoCmpVersion(d1.TargetVer(), d1.TargetVer()+strlen(d1.TargetVer()),
- d2.TargetVer(), d2.TargetVer()+strlen(d2.TargetVer()));
-
- switch(t1)
- {
- case pkgCache::Dep::LessEq:
- return
- (t2 == pkgCache::Dep::Less ||
- t2 == pkgCache::Dep::LessEq ||
- t2 == pkgCache::Dep::Equals) &&
- cmpresult >= 0;
- case pkgCache::Dep::GreaterEq:
- return
- (t2 == pkgCache::Dep::Greater ||
- t2 == pkgCache::Dep::LessEq ||
- t2 == pkgCache::Dep::Equals) &&
- cmpresult <= 0;
- case pkgCache::Dep::Less:
- return
- (t2 == pkgCache::Dep::Less && cmpresult >= 0) ||
- (t2 == pkgCache::Dep::Equals && cmpresult > 0);
- case pkgCache::Dep::Greater:
- return
- (t2 == pkgCache::Dep::Greater && cmpresult <= 0) ||
- (t2 == pkgCache::Dep::Equals && cmpresult < 0);
- case pkgCache::Dep::Equals:
- return
- (t2 == pkgCache::Dep::Equals && cmpresult == 0);
- case pkgCache::Dep::NotEquals:
- return
- (t2 == pkgCache::Dep::NotEquals && cmpresult == 0);
-
- // These shouldn't happen:
- case pkgCache::Dep::NoOp:
- default:
- abort();
- }
- }
-}
-
-/** \return \b true if the OR group of d1 subsumes the OR group of d2:
- * that is, if every member of the OR group containing d2 has a
- * subsuming element in the OR group containing d1.
- */
-static bool or_group_subsumes(const pkgCache::DepIterator &d1,
- const pkgCache::DepIterator &d2)
-{
- pkgCache::DepIterator start1, end1, start2, end2;
-
- surrounding_or(d1, start1, end1);
- surrounding_or(d2, start2, end2);
-
- for(pkgCache::DepIterator i = d1; i != end1; ++i)
- {
- bool found = false;
-
- for(pkgCache::DepIterator j = d2; j != end2; ++j)
- if(subsumes(i, j))
- {
- found = true;
- break;
- }
-
- if(!found)
- return false;
- }
-
- return true;
-}
-
-// This should be a static member of the universe object, but it's
-// rather awkward to put it there right now.
-//
-// Interesting deps are:
-//
-// - All critical deps
-// - All recommendations that are currently satisfied
-// - All recommendations that are unrelated under subsumption to
-// each recommendation of the current package version.
-inline bool aptitude_universe::is_interesting_dep(const pkgCache::DepIterator &d)
-{
- if(const_cast<pkgCache::DepIterator &>(d).IsCritical())
- return true;
- else if(d->Type != pkgCache::Dep::Recommends)
- return false;
- else
- {
- pkgCache::DepIterator dtmp = d;
- while(!dtmp.end() && dtmp->CompareOp & pkgCache::Dep::Or)
- ++dtmp;
- if((*apt_cache_file)[d] & pkgDepCache::DepGNow)
- return true;
-
- pkgCache::VerIterator currver = const_cast<pkgCache::DepIterator &>(d).ParentPkg().CurrentVer();
- pkgCache::VerIterator parver = const_cast<pkgCache::DepIterator &>(d).ParentVer();
-
- if(currver == parver)
- return false;
- else if(currver.end())
- return true;
- else
- // Check whether the current version of this package has a dep
- // that either subsumes _or is subsumed by_ this
- // recommendation. (for mathematical "correctness" we'd only
- // check the first direction, but the goal is to not annoy the
- // user unnecessarily; losing a few new recommendations is OK)
- //
- // NB: full correctness without annoyance means actually
- // TRIMMING DOWN the target set of a recommendation by
- // subtracting elements that are in the current version's
- // recommendation list. Needless to say, I'm ignoring this
- // for now.
- {
- pkgCache::DepIterator d2 = currver.DependsList();
-
- while(!d2.end())
- {
- if(d2->Type == pkgCache::Dep::Recommends &&
- or_group_subsumes(d2, d) || or_group_subsumes(d, d2))
- return false;
-
- while(!d2.end() && ((d2->CompareOp & pkgCache::Dep::Or) != 0))
- ++d2;
-
- if(!d2.end())
- ++d2;
- }
-
- return true;
- }
- }
-}
-
string aptitude_resolver_version::get_name() const
{
if(!ver.end())
@@ -237,7 +48,7 @@
bool aptitude_resolver_version::revdep_iterator::applicable() const
{
- if(!aptitude_universe::is_interesting_dep(dep_lst))
+ if(!is_interesting_dep(dep_lst, cache))
return false;
// Unversioned deps always apply.
@@ -255,7 +66,7 @@
void aptitude_resolver_version::revdep_iterator::normalize()
{
while(!dep_lst.end() &&
- (!aptitude_universe::is_interesting_dep(dep_lst) || !applicable()))
+ (!is_interesting_dep(dep_lst, cache) || !applicable()))
++dep_lst;
if(dep_lst.end() && !provides_open)
@@ -266,7 +77,7 @@
{
dep_lst=prv_lst.ParentPkg().RevDependsList();
while(!dep_lst.end() &&
- (!aptitude_universe::is_interesting_dep(dep_lst) || !applicable()))
+ (!is_interesting_dep(dep_lst, cache) || !applicable()))
++dep_lst;
}
provides_open=true;
@@ -284,7 +95,7 @@
dep_lst=prv_lst.ParentPkg().RevDependsList();
while(!dep_lst.end() &&
- (!aptitude_universe::is_interesting_dep(dep_lst) || !applicable()))
+ (!is_interesting_dep(dep_lst, cache) || !applicable()))
++dep_lst;
}
}
@@ -317,7 +128,7 @@
// dependency.
while(!dep.end() &&
(dep.ParentPkg() == dep.TargetPkg() ||
- !aptitude_universe::is_interesting_dep(dep)))
+ !is_interesting_dep(dep, cache)))
++dep;
// If we ran out of deps, we're done!
@@ -562,7 +373,7 @@
void aptitude_universe::broken_dep_iterator::normalize()
{
while(!the_dep.end() &&
- !(aptitude_universe::is_interesting_dep(the_dep) &&
+ !(is_interesting_dep(the_dep, cache) &&
dep_is_inst_broken(the_dep)))
++the_dep;
@@ -584,7 +395,7 @@
the_dep=ver.DependsList();
while(!the_dep.end() &&
- !(aptitude_universe::is_interesting_dep(the_dep) &&
+ !(is_interesting_dep(the_dep, cache) &&
dep_is_inst_broken(the_dep)))
++the_dep;
@@ -593,7 +404,7 @@
}
}
- assert(the_dep.end() || aptitude_universe::is_interesting_dep(the_dep));
+ assert(the_dep.end() || is_interesting_dep(the_dep, cache));
// Now dep is a broken critical dep or an end dep. If it is a
// conflicts, we might need to push down into Provides...
Modified: branches/aptitude-0.3/aptitude/src/generic/aptitude_resolver_universe.h
==============================================================================
--- branches/aptitude-0.3/aptitude/src/generic/aptitude_resolver_universe.h (original)
+++ branches/aptitude-0.3/aptitude/src/generic/aptitude_resolver_universe.h Tue Aug 16 23:00:09 2005
@@ -877,8 +877,6 @@
// PackageCount is added to make room for the UNINST versions.
return cache->Head().VersionCount+cache->Head().PackageCount;
}
-
- static bool is_interesting_dep(const pkgCache::DepIterator &d);
};
#endif
More information about the Aptitude-svn-commit
mailing list