Resolver.cc

Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 4 -*- */
00002 /* Resolver.cc
00003  *
00004  * Copyright (C) 2000-2002 Ximian, Inc.
00005  * Copyright (C) 2005 SUSE Linux Products GmbH
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License,
00009  * version 2, as published by the Free Software Foundation.
00010  *
00011  * This program is distributed in the hope that it will be useful, but
00012  * WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019  * 02111-1307, USA.
00020  */
00021 
00022 #include "zypp/solver/detail/Resolver.h"
00023 #include "zypp/solver/detail/Helper.h"
00024 
00025 #include "zypp/CapSet.h"
00026 #include "zypp/base/Logger.h"
00027 #include "zypp/base/String.h"
00028 #include "zypp/base/Gettext.h"
00029 
00030 #include "zypp/base/Algorithm.h"
00031 #include "zypp/ResPool.h"
00032 #include "zypp/ResFilters.h"
00033 #include "zypp/CapFilters.h"
00034 #include "zypp/ZYppFactory.h"
00035 #include "zypp/SystemResObject.h"
00036 
00037 
00039 namespace zypp
00040 { 
00041 
00042   namespace zypp_detail
00043   { 
00044     Arch defaultArchitecture();
00046   } // namespace zypp_detail
00048 
00050   namespace solver
00051   { 
00052 
00053     namespace detail
00054     { 
00055 
00056 using namespace std;
00057 
00058 IMPL_PTR_TYPE(Resolver);
00059 
00060 static const unsigned MAX_SECOND_RUNS( 3 );
00061 static const unsigned TIMOUT_SECOND_RUN( 30 );
00062 
00063 //---------------------------------------------------------------------------
00064 
00065 std::ostream &
00066 Resolver::dumpOn( std::ostream & os ) const
00067 {
00068     return os << "<resolver/>";
00069 }
00070 
00071 // Generating a system resolvable in the pool in order to trigger
00072 // modaliases and hals
00073 void assertSystemResObjectInPool()
00074 {
00075   ResPool pool( getZYpp()->pool() );
00076   if ( pool.byKindBegin<SystemResObject>()
00077        == pool.byKindEnd<SystemResObject>() )
00078     {
00079       // SystemResObject is missing in the pool ==> insert
00080       ResStore store;
00081       store.insert( SystemResObject::instance() );
00082       getZYpp()->addResolvables( store, true ); // true = is installed
00083     }
00084 
00085   // set lock
00086   if ( ! pool.byKindBegin<SystemResObject>()
00087          ->status().setLock( true, ResStatus::USER ) )
00088     {
00089       WAR << "Unable to set SystemResObject to lock" << endl;
00090     }
00091 }
00092 
00093 //---------------------------------------------------------------------------
00094 
00095 Resolver::Resolver (const ResPool & pool)
00096     : _pool (pool)
00097     , _timeout_seconds (0)
00098     , _maxSolverPasses (0)
00099     , _verifying (false)
00100     , _testing (false)
00101     , _tryAllPossibilities (false)
00102     , _scippedPossibilities (false)
00103     , _valid_solution_count (0)
00104     , _best_context (NULL)
00105     , _timed_out (false)
00106     , _architecture( zypp_detail::defaultArchitecture() )
00107     , _forceResolve (false)
00108     , _upgradeMode (false)
00109 {}
00110 
00111 
00112 Resolver::~Resolver()
00113 {
00114 }
00115 
00116 //---------------------------------------------------------------------------
00117 
00118 ResPool
00119 Resolver::pool (void) const
00120 {
00121     return _pool;
00122 }
00123 
00124 void
00125 Resolver::reset (void)
00126 {
00127     _verifying = false;
00128 
00129     _initial_items.clear();
00130 
00131     _items_to_install.clear();
00132     _items_to_remove.clear();
00133     _items_to_verify.clear();
00134     _items_to_establish.clear();
00135 
00136     _extra_caps.clear();
00137     _extra_conflicts.clear();
00138 
00139     _pending_queues.clear();
00140     _pruned_queues.clear();
00141     _complete_queues.clear();
00142     _deferred_queues.clear();
00143     _invalid_queues.clear();
00144 
00145     _valid_solution_count = 0;
00146 
00147     _best_context = NULL;
00148     _timed_out = false;
00149     
00150     _tryAllPossibilities = false;
00151     _scippedPossibilities = false;
00152     
00153 }
00154 
00155 
00156 ResolverContext_Ptr
00157 Resolver::context (void) const
00158 {
00159     if (_best_context) return _best_context;
00160     if (_invalid_queues.empty()) return NULL;
00161     ResolverQueue_Ptr invalid = _invalid_queues.front();
00162     return invalid->context();
00163 }
00164 
00165 //---------------------------------------------------------------------------
00166 
00167 void
00168 Resolver::addSubscribedSource (Source_Ref source)
00169 {
00170     _subscribed.insert(source);
00171 }
00172 
00173 void
00174 Resolver::addPoolItemToInstall (PoolItem_Ref item)
00175 {
00176     bool found = false;
00177     for (PoolItemList::const_iterator iter = _items_to_remove.begin();
00178          iter != _items_to_remove.end(); iter++) {
00179         if (*iter == item) {
00180             _items_to_remove.remove(*iter);
00181             found = true;
00182             break;
00183         }
00184     }
00185     if (!found)
00186         _items_to_install.push_back (item);
00187 }
00188 
00189 
00190 void
00191 Resolver::addPoolItemsToInstallFromList (PoolItemList & rl)
00192 {
00193     for (PoolItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) {
00194         addPoolItemToInstall (*iter);
00195     }
00196 }
00197 
00198 
00199 void
00200 Resolver::addPoolItemToRemove (PoolItem_Ref item)
00201 {
00202     bool found = false;
00203     for (PoolItemList::const_iterator iter = _items_to_install.begin();
00204          iter != _items_to_install.end(); iter++) {
00205         if (*iter == item) {
00206             _items_to_install.remove(*iter);
00207             found = true;
00208             break;
00209         }
00210     }
00211     if (!found)
00212         _items_to_remove.push_back (item);
00213 }
00214 
00215 
00216 void
00217 Resolver::addPoolItemsToRemoveFromList (PoolItemList & rl)
00218 {
00219     for (PoolItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) {
00220         addPoolItemToRemove (*iter);
00221     }
00222 }
00223 
00224 
00225 void
00226 Resolver::addPoolItemToEstablish (PoolItem_Ref item)
00227 {
00228     _items_to_establish.push_back (item);
00229 }
00230 
00231 
00232 void
00233 Resolver::addPoolItemsToEstablishFromList (PoolItemList & rl)
00234 {
00235     for (PoolItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) {
00236         addPoolItemToEstablish (*iter);
00237     }
00238 }
00239 
00240 
00241 void
00242 Resolver::addPoolItemToVerify (PoolItem_Ref item)
00243 {
00244 #if 0
00245 
00246   struct {
00248     bool operator()( PoolItem_Ref lhs, PoolItem_Ref rhs ) const
00249     {
00250       int res = lhs->name().compare( rhs->name() );
00251       if ( res )
00252         return res == -1; // lhs < rhs ?
00253       // here: lhs == rhs, so compare edition:
00254       return lhs->edition() < rhs->edition();
00255     }
00256   } order;
00257 #endif
00258 
00259     _items_to_verify.push_back (item);
00260 
00261 #warning Should order by name (and probably edition since with zypp we could have multiple editions installed in parallel)
00262 //    _items_to_verify.sort (order);                    //(GCompareFunc) rc_item_compare_name);
00263 }
00264 
00265 
00266 void
00267 Resolver::addExtraCapability (const Capability & capability)
00268 {
00269     _extra_caps.insert (capability);
00270 }
00271 
00272 
00273 void
00274 Resolver::addExtraConflict (const Capability & capability)
00275 {
00276     _extra_conflicts.insert (capability);
00277 }
00278 
00279 
00280 void
00281 Resolver::addIgnoreConflict (const PoolItem_Ref item,
00282                    const Capability & capability)
00283 {
00284     _ignoreConflicts.insert(make_pair(item, capability));
00285 }
00286 
00287 
00288 void
00289 Resolver::addIgnoreRequires (const PoolItem_Ref item,
00290                              const Capability & capability)
00291 {
00292     _ignoreRequires.insert(make_pair(item, capability));
00293 }
00294 
00295 void
00296 Resolver::addIgnoreObsoletes (const PoolItem_Ref item,
00297                               const Capability & capability)
00298 {
00299     _ignoreObsoletes.insert(make_pair(item, capability));
00300 }
00301 
00302 void
00303 Resolver::addIgnoreInstalledItem (const PoolItem_Ref item)
00304 {
00305     _ignoreInstalledItem.push_back (item);
00306 }
00307 
00308 void
00309 Resolver::addIgnoreArchitectureItem (const PoolItem_Ref item)
00310 {
00311     _ignoreArchitectureItem.push_back (item);
00312 }
00313 
00314 
00315 //---------------------------------------------------------------------------
00316 
00317 struct VerifySystem : public resfilter::PoolItemFilterFunctor
00318 {
00319     Resolver & resolver;
00320 
00321     VerifySystem (Resolver & r)
00322         : resolver (r)
00323     { }
00324 
00325     bool operator()( PoolItem_Ref provider )
00326     {
00327         resolver.addPoolItemToVerify (provider);
00328         return true;
00329     }
00330 };
00331 
00332 
00333 bool
00334 Resolver::verifySystem (void)
00335 {
00336     _DEBUG( "Resolver::verifySystem()" );
00337 
00338     VerifySystem info (*this);
00339 
00340     invokeOnEach( pool().byKindBegin( ResTraits<Package>::kind ),
00341                   pool().byKindEnd( ResTraits<Package>::kind ),
00342                   resfilter::ByInstalled ( ),
00343                   functor::functorRef<bool,PoolItem>(info) );
00344 
00345 
00346     _verifying = true;
00347 
00348     return resolveDependencies ();
00349 }
00350 
00351 
00352 //---------------------------------------------------------------------------
00353 
00354 // copy marked item from solution back to pool
00355 // if data != NULL, set as APPL_LOW (from establishPool())
00356 
00357 static void
00358 solution_to_pool (PoolItem_Ref item, const ResStatus & status, void *data)
00359 {
00360     bool r;
00361 
00362     if (status.isToBeInstalled()) {
00363         r = item.status().setToBeInstalled( (data != NULL) ? ResStatus::APPL_LOW : ResStatus::SOLVER );
00364         _XDEBUG("solution_to_pool(" << item << ", " << status << ") install !" << r);
00365     }
00366     else if (status.isToBeUninstalledDueToUpgrade()) {
00367         r = item.status().setToBeUninstalledDueToUpgrade( (data != NULL) ? ResStatus::APPL_LOW : ResStatus::SOLVER );
00368         _XDEBUG("solution_to_pool(" << item << ", " << status << ") upgrade !" << r);
00369     }
00370     else if (status.isToBeUninstalled()) {
00371         r = item.status().setToBeUninstalled( (data != NULL) ? ResStatus::APPL_LOW : ResStatus::SOLVER );
00372         _XDEBUG("solution_to_pool(" << item << ", " << status << ") remove !" << r);
00373     }
00374     else if (status.isIncomplete()
00375              || status.isNeeded()) {
00376         r = item.status().setIncomplete();
00377         _XDEBUG("solution_to_pool(" << item << ", " << status << ") incomplete !" << r);
00378     }
00379     else if (status.isUnneeded()) {
00380         r = item.status().setUnneeded();
00381         _XDEBUG("solution_to_pool(" << item << ", " << status << ") unneeded !" << r);
00382     }
00383     else if (status.isSatisfied()) {
00384         r = item.status().setSatisfied();
00385         _XDEBUG("solution_to_pool(" << item << ", " << status << ") satisfied !" << r);
00386     } else {
00387         _XDEBUG("solution_to_pool(" << item << ", " << status << ") unchanged !");
00388     }
00389     return;
00390 }
00391 
00392 
00393 //---------------------------------------------------------------------------
00394 // establish state
00395 
00396 struct EstablishState
00397 {
00398     Resolver & resolver;
00399 
00400     EstablishState (Resolver & r)
00401         : resolver (r)
00402     { }
00403 
00404     bool operator()( PoolItem_Ref provider )
00405     {
00406         resolver.addPoolItemToEstablish (provider);
00407         return true;
00408     }
00409 };
00410 
00411 
00412 void
00413 Resolver::establishState( ResolverContext_Ptr context )
00414 {
00415     _DEBUG( "Resolver::establishState ()" );
00416     typedef list<Resolvable::Kind> KindList;
00417     static KindList ordered;
00418     if (ordered.empty()) {
00419         ordered.push_back (ResTraits<zypp::Atom>::kind);
00420         ordered.push_back (ResTraits<zypp::Message>::kind);
00421         ordered.push_back (ResTraits<zypp::Script>::kind);
00422         ordered.push_back (ResTraits<zypp::Patch>::kind);
00423         ordered.push_back (ResTraits<zypp::Pattern>::kind);
00424         ordered.push_back (ResTraits<zypp::Product>::kind);
00425     }
00426 
00427     if (context == NULL)
00428         context = new ResolverContext(_pool, _architecture);
00429 
00430     context->setEstablishing (true);
00431     context->setIgnoreCababilities (_ignoreConflicts,
00432                                     _ignoreRequires,
00433                                     _ignoreObsoletes,
00434                                     _ignoreInstalledItem,
00435                                     _ignoreArchitectureItem);
00436     context->setForceResolve( _forceResolve );
00437     context->setUpgradeMode( _upgradeMode );
00438 
00439     for (KindList::const_iterator iter = ordered.begin(); iter != ordered.end(); iter++) {
00440         const Resolvable::Kind kind = *iter;
00441 
00442         _XDEBUG( "establishing state for kind " << kind.asString() );
00443 
00444         //world()->foreachResItemByKind (kind, trial_establish_cb, this);
00445 
00446         EstablishState info (*this);
00447 
00448         invokeOnEach( pool().byKindBegin( kind ),
00449                       pool().byKindEnd( kind ),
00450                       functor::functorRef<bool,PoolItem>(info) );
00451 
00452         // process the queue
00453         resolveDependencies( context );
00454 
00455         reset();
00456     }
00457 
00458     context->setEstablishing (false);
00459 
00460     _best_context = context;
00461 
00462     return;
00463 }
00464 
00465 
00466 bool
00467 Resolver::establishPool ()
00468 {
00469     MIL << "Resolver::establishPool()" << endl;
00470 
00471     establishState ();                                          // establish !
00472     ResolverContext_Ptr solution = bestContext();
00473 
00474     if (solution) {                                             // copy solution back to pool
00475         solution->foreachMarked (solution_to_pool, (void *)1);  // as APPL_LOW
00476     }
00477     else {
00478         ERR << "establishState did not return a bestContext" << endl;
00479         return false;
00480     }
00481 
00482     return true;
00483 }
00484 
00485 
00486 //---------------------------------------------------------------------------
00487 // freshen state
00488 
00489 typedef map<string, PoolItem_Ref> FreshenMap;
00490 
00491 // add item to itemmap
00492 //  check for item with same name and only keep
00493 //  best architecture, best version
00494 
00495 static void
00496 addToFreshen( PoolItem_Ref item, FreshenMap & itemmap )
00497 {
00498     FreshenMap::iterator it = itemmap.find( item->name() );
00499     if (it != itemmap.end()) {                                  // item with same name found
00500         int cmp = it->second->arch().compare( item->arch() );
00501         if (cmp < 0) {                                          // new item has better arch
00502             it->second = item;
00503         }
00504         else if (cmp == 0) {                                    // new item has equal arch
00505             if (it->second->edition().compare( item->edition() ) < 0) {
00506                 it->second = item;                              // new item has better edition
00507             }
00508         }
00509     }
00510     else {
00511         itemmap[item->name()] = item;
00512     }
00513     return;
00514 }
00515 
00516 
00517 struct FreshenState
00518 {
00519     FreshenMap itemmap;
00520 
00521     FreshenState()
00522     { }
00523 
00524     bool operator()( PoolItem_Ref item)
00525     {
00526         CapSet freshens( item->dep( Dep::FRESHENS ) );
00527         if (!freshens.empty()) {
00528             addToFreshen( item, itemmap );
00529         }
00530         else {                                  // if no freshens, look at supplements
00531             // Also regarding supplements e.g. in order to recognize
00532             // modalias dependencies. Bug #163140
00533             CapSet supplements( item->dep( Dep::SUPPLEMENTS ) );
00534             if (!supplements.empty()) {
00535                 addToFreshen( item, itemmap );
00536             }
00537         }
00538         return true;
00539     }
00540 };
00541 
00542 
00543 void
00544 Resolver::freshenState( ResolverContext_Ptr context )
00545 {
00546     _DEBUG( "Resolver::freshenState ()" );
00547 
00548     if (context == NULL)
00549         context = new ResolverContext( _pool, _architecture );
00550 
00551     context->setEstablishing( true );
00552     context->setIgnoreCababilities( _ignoreConflicts,
00553                                     _ignoreRequires,
00554                                     _ignoreObsoletes,
00555                                     _ignoreInstalledItem,
00556                                     _ignoreArchitectureItem );
00557     context->setForceResolve( _forceResolve );
00558     context->setUpgradeMode( _upgradeMode );
00559 
00560     FreshenState info;
00561 
00562     // collect items to be established
00563 
00564     invokeOnEach( pool().byKindBegin( ResTraits<zypp::Package>::kind ),
00565                       pool().byKindEnd( ResTraits<zypp::Package>::kind ),
00566                       functor::functorRef<bool,PoolItem>(info) );
00567 
00568     // schedule all collected items for establish
00569 
00570     for (FreshenMap::iterator it = info.itemmap.begin(); it != info.itemmap.end(); ++it) {
00571         addPoolItemToEstablish( it->second );
00572     }
00573 
00574     // process the queue
00575     resolveDependencies( context );
00576 
00577     reset();
00578 
00579     context->setEstablishing( false );
00580 
00581     _best_context = context;
00582 
00583     return;
00584 }
00585 
00586 
00587 bool
00588 Resolver::freshenPool ()
00589 {
00590     MIL << "Resolver::freshenPool()" << endl;
00591 
00592     freshenState ();                                            // establish all packages with freshens !
00593     ResolverContext_Ptr solution = bestContext();
00594 
00595     if (solution) {                                             // copy solution back to pool
00596         solution->foreachMarked (solution_to_pool, (void *)1);  // as APPL_LOW
00597     }
00598     else {
00599         ERR << "freshenState did not return a bestContext" << endl;
00600         return false;
00601     }
00602 
00603     return true;
00604 }
00605 
00606 //---------------------------------------------------------------------------
00607 
00608 bool
00609 Resolver::resolveDependencies (const ResolverContext_Ptr context)
00610 {
00611 
00612     time_t t_start, t_now;
00613 
00614     MIL << "Resolver::resolveDependencies()" << endl;
00615 
00616     _pending_queues.clear();
00617     _pruned_queues.clear();
00618     _complete_queues.clear();
00619     _deferred_queues.clear();
00620     _invalid_queues.clear();
00621     _valid_solution_count = 0;
00622     _best_context = NULL;
00623 
00624 #warning local items disabled
00625 #if 0
00626     bool have_local_items = false;
00627 
00628     /* Walk through are list of to-be-installed packages and see if any of them are local. */
00629 
00630     for (PoolItemList::const_iterator iter = _items_to_install.begin(); iter != _items_to_install.end(); iter++) {
00631         if ((*iter)->local()) {
00632             have_local_items = true;
00633             break;
00634         }
00635     }
00636 
00637     World_Ptr the_world = world();
00638     StoreWorld_Ptr local_world = NULL;
00639     MultiWorld_Ptr local_multiworld = NULL;
00640 
00641     Channel_Ptr local_channel = NULL;
00642 
00643     if (have_local_items) {
00644         local_multiworld = new MultiWorld();
00645         local_world = new StoreWorld();
00646 
00647         local_channel = new Channel ("", "Local ResItems", "@local", "");
00648 
00649         local_world->addChannel (local_channel);
00650 
00651         local_multiworld->addSubworld (local_world);
00652         local_multiworld->addSubworld (the_world);
00653 
00654         the_world = local_multiworld;
00655     }
00656 #endif
00657 
00658     // create initial_queue
00659 
00660     ResolverQueue_Ptr initial_queue = new ResolverQueue(_pool, _architecture, context);
00661 
00662     // adding "external" provides, the the requirements will be ignored
00663     IgnoreMap ignoreRequires = _ignoreRequires;
00664     ResPool::AdditionalCapSet additionalCapSet = pool().additionaProvide();
00665     for (ResPool::AdditionalCapSet::const_iterator it = additionalCapSet.begin();
00666          it != additionalCapSet.end(); it++) {
00667         CapSet cset = it->second;
00668         for (CapSet::const_iterator cit = cset.begin(); cit != cset.end(); ++cit) {
00669             ignoreRequires.insert(make_pair(PoolItem_Ref(), *cit));
00670         }
00671     }
00672     
00673     // Initialize all ignoring dependencies
00674     initial_queue->context()->setIgnoreCababilities (_ignoreConflicts,
00675                                     ignoreRequires,
00676                                     _ignoreObsoletes,
00677                                     _ignoreInstalledItem,
00678                                     _ignoreArchitectureItem);
00679     initial_queue->context()->setForceResolve( _forceResolve );
00680     initial_queue->context()->setUpgradeMode( _upgradeMode );
00681     initial_queue->context()->setTryAllPossibilities( _tryAllPossibilities );
00682     initial_queue->context()->setScippedPossibilities( _scippedPossibilities );
00683 
00684     /* If this is a verify, we do a "soft resolution" */
00685 
00686     initial_queue->context()->setVerifying( _verifying );
00687 
00688     /* Add extra items. */
00689 
00690     for (QueueItemList::const_iterator iter = _initial_items.begin(); iter != _initial_items.end(); iter++) {
00691         initial_queue->addItem (*iter);
00692     }
00693 
00694     for (PoolItemList::const_iterator iter = _items_to_install.begin(); iter != _items_to_install.end(); iter++) {
00695         PoolItem_Ref r = *iter;
00696 
00697 #warning local items disabled
00698 #if 0
00699         /* Add local packages to our dummy channel. */
00700         if (r->local()) {
00701             assert (local_channel != NULL);
00702             ResItem_Ptr r1 = const_pointer_cast<ResItem>(r);
00703             r1->setChannel (local_channel);
00704             local_world->addPoolItem_Ref (r);
00705         }
00706 #endif
00707         initial_queue->addPoolItemToInstall (r);
00708     }
00709 
00710     for (PoolItemList::const_iterator iter = _items_to_remove.begin(); iter != _items_to_remove.end(); iter++) {
00711         if (!_upgradeMode)
00712             initial_queue->addPoolItemToRemove (*iter, true /* remove-only mode */);
00713         else
00714             //   Checking old dependencies for packages which will be updated.
00715             //   E.g. foo provides a dependecy which foo-new does not provides anymore.
00716             //   So check, if there is a packages installed which requires foo.
00717             //   Testcase exercise-bug150844-test.xml
00718             //   Testcase Bug156439-test.xml
00719             initial_queue->addPoolItemToRemove (*iter, false /* no remove-only mode */);
00720     }
00721 
00722     for (PoolItemList::const_iterator iter = _items_to_verify.begin(); iter != _items_to_verify.end(); iter++) {
00723         initial_queue->addPoolItemToVerify (*iter);
00724     }
00725 
00726     for (PoolItemList::const_iterator iter = _items_to_establish.begin(); iter != _items_to_establish.end(); iter++) {
00727         initial_queue->addPoolItemToEstablish (*iter);
00728     }
00729 
00730     for (CapSet::const_iterator iter = _extra_caps.begin(); iter != _extra_caps.end(); iter++) {
00731         initial_queue->addExtraCapability (*iter);
00732     }
00733     
00734     // adding "external" requires
00735     additionalCapSet = pool().additionalRequire();
00736     for (ResPool::AdditionalCapSet::const_iterator it = additionalCapSet.begin();
00737          it != additionalCapSet.end(); it++) {
00738         CapSet cset = it->second;
00739         for (CapSet::const_iterator cit = cset.begin(); cit != cset.end(); ++cit) {
00740             initial_queue->addExtraCapability (*cit);       
00741         }
00742     }
00743 
00744     for (CapSet::const_iterator iter = _extra_conflicts.begin(); iter != _extra_conflicts.end(); iter++) {
00745         initial_queue->addExtraConflict (*iter);
00746     }
00747 
00748     // adding "external" conflicts
00749     additionalCapSet = pool().additionaConflict();
00750     for (ResPool::AdditionalCapSet::const_iterator it = additionalCapSet.begin();
00751          it != additionalCapSet.end(); it++) {
00752         CapSet cset = it->second;
00753         for (CapSet::const_iterator cit = cset.begin(); cit != cset.end(); ++cit) {
00754             initial_queue->addExtraConflict (*cit);         
00755         }
00756     }
00757 
00758     // Adding System resolvable
00759     assertSystemResObjectInPool();
00760 
00761     _XDEBUG( "Initial Queue: [" << *initial_queue << "]" );
00762 
00763     if (initial_queue->isEmpty()) {
00764         INT << "Empty Queue, nothing to resolve" << endl;
00765 
00766         return true;
00767     }
00768 
00769     _best_context = NULL;
00770 
00771     _pending_queues.push_front (initial_queue);
00772 
00773     time (&t_start);
00774 
00775     while (!_pending_queues.empty()) {
00776 
00777         _DEBUG( "Pend " << (long) _pending_queues.size()
00778                               << " / Cmpl " << (long) _complete_queues.size()
00779                               << " / Prun " << (long) _pruned_queues.size()
00780                               << " / Defr " << (long) _deferred_queues.size()
00781                               << " / Invl " << (long) _invalid_queues.size() );
00782 
00783               if (_timeout_seconds > 0) {
00784                     time (&t_now);
00785                     if (difftime (t_now, t_start) > _timeout_seconds) {
00786                         _timed_out = true;
00787                     MIL << "Timeout " << _timeout_seconds << " seconds reached"
00788                         << " -> exit" << endl;
00789                     break;
00790                 }
00791               }
00792               if (_maxSolverPasses > 0) {
00793                   if (_maxSolverPasses <= _complete_queues.size() +
00794                       _pruned_queues.size() +
00795                       _deferred_queues.size() +
00796                       _invalid_queues.size()) {
00797                       _timed_out = true;
00798                       MIL << "Max solver runs ( " << _maxSolverPasses
00799                           << " ) reached -> exit" << endl;
00800                       break;
00801                   }
00802               }             
00803               
00804             ResolverQueue_Ptr queue = _pending_queues.front();
00805             _pending_queues.pop_front();
00806             ResolverContext_Ptr context = queue->context();
00807 
00808             queue->process();
00809 
00810         if (queue->isInvalid ()) {
00811 
00812             _XDEBUG( "Invalid Queue\n" );
00813             _invalid_queues.push_back(queue);
00814 
00815         } else if (queue->isEmpty ()) {
00816 
00817             _XDEBUG( "Empty Queue\n" );
00818 
00819             _complete_queues.push_back(queue);
00820 
00821             ++_valid_solution_count;
00822 
00823             /* Compare this solution to our previous favorite.  In the case of a tie,
00824                the first solution wins --- yeah, I know this is lame, but it shouldn't
00825                be an issue too much of the time. */
00826 
00827             if (_best_context == NULL
00828                 || _best_context->compare (context) < 0)
00829             {
00830                 _best_context = context;
00831             }
00832 
00833         } else if (_best_context != NULL
00834                    && _best_context->partialCompare (context) > 0) {
00835 
00836             /* If we aren't currently as good as our previous best complete solution,
00837                this solution gets pruned. */
00838 
00839             _XDEBUG( "PRUNED!" );
00840 
00841             _pruned_queues.push_back(queue);
00842 
00843         } else {
00844 
00845             /* If our queue is isn't empty and isn't invalid, that can only mean
00846                one thing: we are down to nothing but branches. */
00847 
00848             queue->splitFirstBranch (_pending_queues, _deferred_queues);
00849         }
00850 
00851         /* If we have run out of pending queues w/o finding any solutions,
00852            and if we have deferred queues, make the first deferred queue
00853            pending. */
00854 
00855         if (_pending_queues.empty()
00856             && _complete_queues.empty()
00857             && !_deferred_queues.empty()) {
00858             _pending_queues.push_back(_deferred_queues.front());
00859         }
00860     }
00861     _DEBUG("Pend " << (long) _pending_queues.size()
00862                    << " / Cmpl " << (long) _complete_queues.size()
00863                    << " / Prun " << (long) _pruned_queues.size()
00864                    << " / Defr " << (long) _deferred_queues.size()
00865                    << " / Invl " << (long) _invalid_queues.size() );
00866     
00867     
00868     if ( !(_best_context && _best_context->isValid()) // no valid solution
00869          && !_tryAllPossibilities ) { // a second run with ALL possibilities has not been tried
00870 
00871         for (ResolverQueueList::iterator iter = _invalid_queues.begin();
00872              iter != _invalid_queues.end(); iter++) {
00873             // evaluate if there are other possibilities which have not been regarded
00874             ResolverQueue_Ptr invalid = *iter;              
00875             if (invalid->context()->scippedPossibilities()) {
00876                 _scippedPossibilities = true;
00877                 break;
00878             }
00879         }
00880         
00881         if (_scippedPossibilities) { // possible other solutions scipped         
00882             // lets try a second run with ALL possibilities
00883             _tryAllPossibilities = true;
00884             MIL << "================================================================"
00885                 << endl;
00886             MIL << "No valid solution, lets try a second run with ALL possibilities"
00887                 << endl;
00888             if (_maxSolverPasses <= 0) 
00889                 _maxSolverPasses = MAX_SECOND_RUNS;         
00890             if (_timeout_seconds <= 0) 
00891                 _timeout_seconds = TIMOUT_SECOND_RUN;
00892 
00893             MIL << "But no longer than " << MAX_SECOND_RUNS << " runs or "
00894                 << TIMOUT_SECOND_RUN << " seconds" << endl;
00895             MIL << "================================================================"
00896                 << endl;
00897             // saving invalid queue
00898             ResolverQueueList   save_queues = _invalid_queues;
00899             resolveDependencies ();
00900             if (!(_best_context && _best_context->isValid()))
00901                 _invalid_queues = save_queues; // take the old
00902         }
00903     }
00904 
00905     return _best_context && _best_context->isValid();
00906 }
00907 
00908 
00909 //----------------------------------------------------------------------------
00910 // undo
00911 
00912 struct UndoTransact : public resfilter::PoolItemFilterFunctor
00913 {
00914     UndoTransact ()
00915     { }
00916 
00917     bool operator()( PoolItem_Ref item )                // only transacts() items go here
00918     {
00919         item.status().resetTransact( ResStatus::APPL_LOW );// clear any solver/establish transactions
00920         return true;
00921     }
00922 };
00923 
00924 void
00925 Resolver::undo(void)
00926 {
00927     UndoTransact info;
00928     MIL << "*** undo ***" << endl;
00929     invokeOnEach ( _pool.begin(), _pool.end(),
00930                    resfilter::ByTransact( ),                    // collect transacts from Pool to resolver queue
00931                    functor::functorRef<bool,PoolItem>(info) );
00932     // These conflict should be ignored of the concering item
00933     _ignoreConflicts.clear();
00934     // These requires should be ignored of the concering item
00935     _ignoreRequires.clear();
00936     // These obsoletes should be ignored of the concering item
00937     _ignoreObsoletes.clear();
00938     // Ignore architecture of the item
00939     _ignoreArchitecture.clear();
00940     // Ignore the status "installed" of the item
00941     _ignoreInstalledItem.clear();
00942     // Ignore the architecture of the item
00943     _ignoreArchitectureItem.clear();
00944 
00945 
00946     return;
00947 }
00948 
00949 //----------------------------------------------------------------------------
00950 // resolvePool
00951 
00952 struct CollectTransact : public resfilter::PoolItemFilterFunctor
00953 {
00954     Resolver & resolver;
00955 
00956     CollectTransact (Resolver & r)
00957         : resolver (r)
00958     { }
00959 
00960     bool operator()( PoolItem_Ref item )                // only transacts() items go here
00961     {
00962         ResStatus status = item.status();
00963         _XDEBUG( "CollectTransact(" << item << ")" );
00964         bool by_solver = (status.isBySolver() || status.isByApplLow());
00965 
00966         if (by_solver) {
00967             item.status().resetTransact( ResStatus::APPL_LOW );// clear any solver/establish transactions
00968             return true;                                // back out here, dont re-queue former solver result
00969         }
00970 
00971         if (status.isToBeInstalled()) {
00972             resolver.addPoolItemToInstall(item);        // -> install!
00973         }
00974         if (status.isToBeUninstalled()) {
00975             resolver.addPoolItemToRemove(item);         // -> remove !
00976         }
00977         if (status.isIncomplete()) {                    // incomplete (re-install needed)
00978             PoolItem_Ref reinstall = Helper::findReinstallItem (resolver.pool(), item);
00979             if (reinstall) {
00980                 MIL << "Reinstall " << reinstall << " for incomplete " << item << endl;
00981                 resolver.addPoolItemToInstall(reinstall);       // -> install!
00982             }
00983             else {
00984                 WAR << "Can't find " << item << " for re-installation" << endl;
00985             }
00986         }
00987         return true;
00988     }
00989 };
00990 
00991 
00992 static void
00993 show_pool( ResPool pool )
00994 {
00995     int count = 1;
00996     static bool full_pool_shown = true;
00997 
00998     _XDEBUG( "---------------------------------------" );
00999     for (ResPool::const_iterator it = pool.begin(); it != pool.end(); ++it, ++count) {
01000 
01001         if (!full_pool_shown                                    // show item if not shown all before
01002             || it->status().transacts()                         // or transacts
01003             || !it->status().isUndetermined())                  // or established status
01004         {
01005             _DEBUG( count << ": " << *it );
01006         }
01007     }
01008     _XDEBUG( "---------------------------------------" );
01009     full_pool_shown = true;
01010 }
01011 
01012 //  This function loops over the pool and grabs
01013 //  all item.status().transacts() and item.status().byUser()
01014 //  It clears all previous bySolver() states also
01015 //
01016 //  Every toBeInstalled is passed to zypp::solver:detail::Resolver.addPoolItemToInstall()
01017 //  Every toBeUninstalled is passed to zypp::solver:detail::Resolver.addPoolItemToRemove()
01018 //
01019 //  Then zypp::solver:detail::Resolver.resolveDependencies() is called.
01020 //
01021 //  zypp::solver:detail::Resolver then returns a ResolverContext via bestContext() which
01022 //  describes the best solution. If bestContext() is NULL, no solution was found.
01023 //
01024 //  ResolverContext has a foreachMarked() iterator function which loops over all
01025 //  items of the solutions. These must be written back to the pool.
01026 
01027 
01028 bool
01029 Resolver::resolvePool ()
01030 {
01031 
01032     CollectTransact info (*this);
01033 
01034     // cleanup before next run
01035     reset();
01036 
01037 #if 1
01038 
01039     MIL << "Resolver::resolvePool()" << endl;
01040     _XDEBUG( "Pool before resolve" );
01041     show_pool( _pool );
01042 
01043 #endif
01044     invokeOnEach ( _pool.begin(), _pool.end(),
01045                    resfilter::ByTransact( ),                    // collect transacts from Pool to resolver queue
01046                    functor::functorRef<bool,PoolItem>(info) );
01047 
01048     bool have_solution = resolveDependencies ();                // resolve !
01049 
01050     if (have_solution) {                                        // copy solution back to pool
01051         MIL << "Have solution, copying back to pool" << endl;
01052         ResolverContext_Ptr solution = bestContext();
01053         solution->foreachMarked (solution_to_pool, NULL);
01054 #if 1
01055         _XDEBUG( "Pool after resolve" );
01056         show_pool( _pool );
01057 #endif
01058     }
01059     else {
01060         MIL << "!!! Have NO solution !!! Additional solver information:" << endl;
01061         int counter = 0;
01062         for (ResolverQueueList::iterator iter = _invalid_queues.begin();
01063              iter != _invalid_queues.end(); iter++) {
01064             counter++;
01065             MIL << "-----------------------------------------------------------------" << endl;
01066             MIL << counter++ << ". failed queue:" << endl;
01067             ResolverQueue_Ptr invalid = *iter;    
01068             invalid->context()->spewInfo ();
01069             MIL << *invalid->context() << endl;
01070             MIL << "-----------------------------------------------------------------" << endl;         
01071         }
01072     }
01073     return have_solution;
01074 }
01075 
01076 
01077 static void
01078 get_info_foreach_cb (ResolverInfo_Ptr info, void *data)
01079 {
01080     list<string> *stringList = (list<string> *)data;
01081     stringList->push_back (info->message());
01082 }
01083 
01084 
01085 // returns a string list of ResolverInfo of the LAST not valid solution
01086 std::list<std::string> Resolver::problemDescription( void ) const
01087 {
01088     list<string> retList;
01089     if (_invalid_queues.empty()) return retList;
01090     ResolverQueue_Ptr invalid = _invalid_queues.front();
01091     invalid->context()->foreachInfo (PoolItem_Ref(), -1, get_info_foreach_cb, (void *)&retList);;
01092     return retList;
01093 }
01094 
01095 
01096 //-----------------------------------------------------------------------------
01097 
01098 //
01099 // UI Helper
01100 // do a single (install/uninstall) transaction
01101 //  if a previously uninstalled item was just set to-be-installed, return it as 'added'
01102 
01103 static bool
01104 transactItems( PoolItem_Ref installed, PoolItem_Ref uninstalled, bool install, bool soft, PoolItem_Ref & added )
01105 {
01106         if (install) {
01107             if (compareByNVRA (installed.resolvable(), uninstalled.resolvable()) != 0) { // do not update itself Bug 174290
01108                 if (uninstalled
01109                     && !uninstalled.status().isLocked())
01110                 {
01111                     bool adding;        // check if we're succeeding with transaction
01112                     if (soft)
01113                         adding = uninstalled.status().setSoftTransact( true, ResStatus::APPL_LOW );
01114                     else
01115                         adding = uninstalled.status().setTransact( true, ResStatus::APPL_LOW );
01116                     if (adding) // if succeeded, return it as 'just added'
01117                         added = uninstalled;
01118                 }
01119                 if (installed
01120                     && !installed.status().isLocked())
01121                 {
01122                     installed.status().resetTransact( ResStatus::APPL_LOW );
01123                 }
01124             }
01125         } else {
01126             // uninstall
01127             if (uninstalled
01128                 && !uninstalled.status().isLocked())
01129             {
01130                 uninstalled.status().resetTransact( ResStatus::APPL_LOW );
01131             }
01132             if (installed
01133                 && !installed.status().isLocked())
01134             {
01135                 if (soft)
01136                     installed.status().setSoftTransact( true, ResStatus::APPL_LOW );
01137                 else
01138                     installed.status().setTransact( true, ResStatus::APPL_LOW );
01139             }
01140         }
01141         if (!uninstalled
01142             && !installed)
01143         {
01144             return false;
01145         }
01146     return true;
01147 }
01148 
01149 
01150 typedef struct { PoolItem_Ref installed; PoolItem_Ref uninstalled; } IandU;
01151 typedef map<string, IandU> IandUMap;
01152 
01153 // find best available providers for requested capability index
01154 // (use capability index instead of name in order to find e.g. ccb vs. x11)
01155 
01156 struct FindIandU
01157 {
01158     IandUMap iandu;             // install, and best uninstalled
01159 
01160     FindIandU ()
01161     { }
01162 
01163     bool operator()( const CapAndItem & cai )
01164     {
01165         PoolItem item( cai.item );
01166         string idx = cai.cap.index();
01167 
01168         if ( item.status().staysInstalled() ) {
01169             iandu[idx].installed = item;
01170         }
01171         else if ( item.status().isToBeInstalled() ) {                   // prefer already to-be-installed
01172             iandu[idx].uninstalled = item;
01173         }
01174         else if ( item.status().staysUninstalled() ) {                  // only look at uninstalled
01175             IandUMap::iterator it = iandu.find( idx );
01176 
01177             if (it != iandu.end()
01178                 && it->second.uninstalled)
01179             {                                                           // uninstalled with same name found
01180                 int cmp = it->second.uninstalled->arch().compare( item->arch() );
01181                 if (cmp < 0) {                                          // new item has better arch
01182                     it->second.uninstalled = item;
01183                 }
01184                 else if (cmp == 0) {                                    // new item has equal arch
01185                     if (it->second.uninstalled->edition().compare( item->edition() ) < 0) {
01186                         it->second.uninstalled = item;                  // new item has better edition
01187                     }
01188                 }
01189             }
01190             else {
01191                 iandu[idx].uninstalled = item;
01192             }
01193         }
01194         return true;
01195     }
01196 };
01197 
01198 
01199 //
01200 // transact list of capabilities (requires or recommends)
01201 //  return false if one couldn't be matched
01202 //
01203 // see Resolver::transactResObject
01204 //
01205 
01206 static bool
01207 transactCaps( const ResPool & pool, const CapSet & caps, bool install, bool soft, std::set<PoolItem_Ref> & added_items )
01208 {
01209     bool result = true;
01210 
01211     // loop over capabilities and find (best) matching provider
01212 
01213     for (CapSet::const_iterator cit = caps.begin(); cit != caps.end(); ++cit) {
01214 
01215         // find best providers of requested capability
01216 
01217         FindIandU callback;
01218         Dep dep( Dep::PROVIDES );
01219         invokeOnEach( pool.byCapabilityIndexBegin( cit->index(), dep ),
01220                       pool.byCapabilityIndexEnd( cit->index(), dep ),
01221                       resfilter::ByCapMatch( *cit ) ,
01222                       functor::functorRef<bool,CapAndItem>(callback) );
01223 
01224         // loop through providers and transact them accordingly
01225 
01226         for (IandUMap::const_iterator it = callback.iandu.begin(); it !=  callback.iandu.end(); ++it) {
01227             PoolItem_Ref just_added;
01228             just_added = PoolItem_Ref();
01229             if (!transactItems( it->second.installed, it->second.uninstalled, install, soft, just_added )) {
01230                 result = false;
01231             }
01232             else if (just_added) {
01233                 // transactItems just selected an item of the same kind we're currently processing
01234                 // add it to the list and handle it equivalent to the origin item
01235                 added_items.insert( just_added );
01236             }
01237         }
01238 
01239     }
01240     return result;
01241 }
01242 
01243 
01244 struct TransactSupplements : public resfilter::PoolItemFilterFunctor
01245 {
01246     const Resolvable::Kind &_kind;
01247     bool valid;
01248 
01249     TransactSupplements( const Resolvable::Kind & kind )
01250         : _kind( kind )
01251         , valid( false )
01252     { }
01253 
01254     bool operator()( PoolItem_Ref item )
01255     {
01256 //      MIL << "TransactSupplements(" << item << ")" << endl;
01257         if (item->kind() == _kind
01258             && (item.status().staysInstalled()
01259                 || item.status().isToBeInstalled()))
01260         {
01261             valid = true;
01262             return false;               // end search here
01263         }
01264         return true;
01265     }
01266 };
01267 
01268 //
01269 // transact due to a language dependency
01270 // -> look through the pool and run transactResObject() accordingly
01271 
01272 struct TransactLanguage : public resfilter::PoolItemFilterFunctor
01273 {
01274     Resolver & _resolver;
01275     ResObject::constPtr _langObj;
01276     bool _install;
01277 
01278     TransactLanguage( Resolver & r, ResObject::constPtr langObj, bool install )
01279         : _resolver( r )
01280         , _langObj( langObj )
01281         , _install( install )
01282     { }
01283 
01284     /* item has a freshens on _langObj
01285         _langObj just transacted to _install (true == to-be-installed, false == to-be-uninstalled)
01286     */
01287     bool operator()( const CapAndItem & cai )
01288     {
01289         /* check for supplements, if the item has supplements these also must match  */
01290 
01291         PoolItem_Ref item( cai.item );
01292 //      MIL << "TransactLanguage " << item << ", install " << _install << endl;
01293         CapSet supplements( item->dep( Dep::SUPPLEMENTS ) );
01294         if (!supplements.empty()) {
01295 //          MIL << "has supplements" << endl;
01296             bool valid = false;
01297             for (CapSet::const_iterator it = supplements.begin(); it != supplements.end(); ++it) {
01298 //              MIL << "Checking " << *it << endl;
01299                 TransactSupplements callback( it->refers() );
01300                 invokeOnEach( _resolver.pool().byNameBegin( it->index() ),
01301                               _resolver.pool().byNameEnd( it->index() ),
01302                               functor::functorRef<bool,PoolItem>( callback ) );
01303                 if (callback.valid) {
01304                     valid = true;               // found a supplements match
01305                     break;
01306                 }
01307             }
01308             if (!valid) {
01309 //              MIL << "All supplements false" << endl;
01310                 return true;                    // no supplements matched, we're done
01311             }
01312         }
01313 
01314         PoolItem_Ref dummy;
01315         if (_install) {
01316             if (item.status().staysUninstalled()) {
01317                 transactItems( PoolItem_Ref(), item, _install, true, dummy );
01318             }
01319         }
01320         else {
01321             if (item.status().staysInstalled()) {
01322                 transactItems( item, PoolItem_Ref(), _install, true, dummy );
01323             }
01324         }
01325         return true;
01326     }
01327 };
01328 
01329 
01330 
01331 //
01332 // transact a single object
01333 // -> do a 'single step' resolving either installing or removing
01334 //    required and recommended PoolItems
01335 
01336 bool
01337 Resolver::transactResObject( ResObject::constPtr robj, bool install,
01338                              bool recursive)
01339 {
01340     static std::set<PoolItem_Ref> alreadyTransactedObjects;
01341 
01342     if (!recursive) {
01343         alreadyTransactedObjects.clear(); // first call
01344     }
01345     
01346     if (robj == NULL) {
01347         ERR << "NULL ResObject" << endl;
01348     }
01349     _XDEBUG ( "transactResObject(" << *robj << ", " << (install?"install":"remove") << ")");
01350 
01351     if (robj->kind() == ResTraits<Language>::kind) {
01352         TransactLanguage callback( *this, robj, install );
01353         Dep dep( Dep::FRESHENS );
01354         invokeOnEach( pool().byCapabilityIndexBegin( robj->name(), dep ),
01355                       pool().byCapabilityIndexEnd( robj->name(), dep ),
01356                       functor::functorRef<bool,CapAndItem>( callback ) );
01357 
01358     }
01359     std::set<PoolItem_Ref> added;
01360 
01361     // loop over 'recommends' and 'requires' of this item and collect additional
01362     //  items of the same kind on the way
01363 
01364     transactCaps( _pool, robj->dep( Dep::RECOMMENDS ), install, true, added );
01365     transactCaps( _pool, robj->dep( Dep::REQUIRES ), install, false, added );
01366 
01367     // if any additional items were collected, call this functions again recursively
01368     //   This is guaranteed to finish since additional items are those which were not selected before
01369     //   and this function is only called for already selected items. So added really only contains
01370     //   'new' items.
01371 
01372     for (std::set<PoolItem_Ref>::const_iterator it = added.begin(); it != added.end(); ++it) {
01373         if ((*it)->kind() == robj->kind()) {
01374             std::set<PoolItem_Ref>::const_iterator itCmp = alreadyTransactedObjects.find (*it);
01375             if (itCmp == alreadyTransactedObjects.end())
01376             {
01377                 // not already transacted
01378                 alreadyTransactedObjects.insert (*it);
01379                 transactResObject( it->resolvable(), install,
01380                                    true //recursive
01381                                    );
01382             }
01383         }
01384     }
01385 
01386     // not used anyway
01387     return true;
01388 }
01389 
01390 //
01391 // helper to transact all objects of a specific kind
01392 //  see Resolver::transactResKind
01393 // item is to-be-installed (install == true) or to-be-uninstalled
01394 // -> run transactResObject() accordingly
01395 
01396 struct TransactKind : public resfilter::PoolItemFilterFunctor
01397 {
01398     Resolver & _resolver;
01399     bool install;               // true if to-be-installed, else to-be-uninstalled
01400     bool result;
01401 
01402     TransactKind( Resolver & r )
01403         : _resolver( r )
01404         , result( true )
01405     { }
01406 
01407     bool operator()( PoolItem_Ref item )
01408     {
01409         result = _resolver.transactResObject( item.resolvable(), install );
01410         return true;
01411     }
01412 };
01413 
01414 
01415 bool
01416 Resolver::transactResKind( Resolvable::Kind kind )
01417 {
01418     TransactKind callback (*this);
01419     _XDEBUG( "transactResKind(" << kind << ")" );
01420 
01421     // check all uninstalls
01422     callback.install = false;
01423     invokeOnEach( pool().byKindBegin( kind ),
01424                   pool().byKindEnd( kind ),
01425                   functor::chain( resfilter::ByTransact(), resfilter::ByInstalled ()),
01426                   functor::functorRef<bool,PoolItem>( callback ) );
01427 
01428     // check all installs
01429     callback.install = true;
01430     invokeOnEach( pool().byKindBegin( kind ),
01431                   pool().byKindEnd( kind ),
01432                   functor::chain( resfilter::ByTransact(), resfilter::ByUninstalled ()),
01433                   functor::functorRef<bool,PoolItem>( callback ) );
01434 
01435     return callback.result;
01436 }
01437 
01438 
01439 struct TransactReset : public resfilter::PoolItemFilterFunctor
01440 {
01441     ResStatus::TransactByValue _causer;
01442     TransactReset( ResStatus::TransactByValue causer )
01443         : _causer( causer )
01444     { }
01445 
01446     bool operator()( PoolItem_Ref item )                // only transacts() items go here
01447     {
01448         item.status().resetTransact( _causer );
01449         return true;
01450     }
01451 };
01452 
01453 
01454 void
01455 Resolver::transactReset( ResStatus::TransactByValue causer )
01456 {
01457     TransactReset info( causer );
01458     MIL << "transactReset(" << causer << ")" << endl;
01459     invokeOnEach ( _pool.begin(), _pool.end(),
01460                    resfilter::ByTransact( ),
01461                    functor::functorRef<bool,PoolItem>(info) );
01462     return;
01463 }
01464 
01466     };// namespace detail
01469   };// namespace solver
01472 };// namespace zypp
01474 

Generated on Tue Nov 28 16:49:30 2006 for zypp by  doxygen 1.5.0