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

Generated on Tue Sep 25 19:23:06 2007 for libzypp by  doxygen 1.5.3