00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <sys/utsname.h>
00023
00024 #include "zypp/solver/detail/Resolver.h"
00025 #include "zypp/solver/detail/Helper.h"
00026
00027 #include "zypp/CapSet.h"
00028 #include "zypp/base/Logger.h"
00029 #include "zypp/base/String.h"
00030 #include "zypp/base/Gettext.h"
00031
00032 #include "zypp/base/Algorithm.h"
00033 #include "zypp/ResPool.h"
00034 #include "zypp/ResFilters.h"
00035 #include "zypp/CapFilters.h"
00036 #include "zypp/ZYppFactory.h"
00037 #include "zypp/SystemResObject.h"
00038
00039
00040
00042 namespace zypp
00043 {
00044
00045 namespace solver
00046 {
00047
00048 namespace detail
00049 {
00050
00051 using namespace std;
00052
00053 IMPL_PTR_TYPE(Resolver);
00054
00055
00056
00057 std::ostream &
00058 Resolver::dumpOn( std::ostream & os ) const
00059 {
00060 return os << "<resolver/>";
00061 }
00062
00063
00064
00065 void assertSystemResObjectInPool()
00066 {
00067 ResPool pool( getZYpp()->pool() );
00068 if ( pool.byKindBegin<SystemResObject>()
00069 == pool.byKindEnd<SystemResObject>() )
00070 {
00071
00072 ResStore store;
00073 store.insert( SystemResObject::instance() );
00074 getZYpp()->addResolvables( store, true );
00075 }
00076
00077
00078 if ( ! pool.byKindBegin<SystemResObject>()
00079 ->status().setLock( true, ResStatus::USER ) )
00080 {
00081 WAR << "Unable to set SystemResObject to lock" << endl;
00082 }
00083 }
00084
00085
00086
00087 Resolver::Resolver (const ResPool & pool)
00088 : _pool (pool)
00089 , _timeout_seconds (0)
00090 , _verifying (false)
00091 , _testing (false)
00092 , _valid_solution_count (0)
00093 , _best_context (NULL)
00094 , _timed_out (false)
00095 , _forceResolve (false)
00096 , _upgradeMode (false)
00097 {
00098 struct utsname buf;
00099 if (uname (&buf) < 0) {
00100 ERR << "Can't determine system architecture" << endl;
00101 }
00102 else {
00103 MIL << "System architecture is '" << buf.machine << "'" << endl;
00104 _architecture = Arch(buf.machine);
00105 }
00106 }
00107
00108
00109 Resolver::~Resolver()
00110 {
00111 }
00112
00113
00114
00115 ResPool
00116 Resolver::pool (void) const
00117 {
00118 return _pool;
00119 }
00120
00121 void
00122 Resolver::reset (void)
00123 {
00124 _timeout_seconds = 0;
00125 _verifying = false;
00126
00127 _initial_items.clear();
00128
00129 _items_to_install.clear();
00130 _items_to_remove.clear();
00131 _items_to_verify.clear();
00132 _items_to_establish.clear();
00133
00134 _extra_caps.clear();
00135 _extra_conflicts.clear();
00136
00137 _pending_queues.clear();
00138 _pruned_queues.clear();
00139 _complete_queues.clear();
00140 _deferred_queues.clear();
00141 _invalid_queues.clear();
00142
00143 _valid_solution_count = 0;
00144
00145 _best_context = NULL;
00146 _timed_out = false;
00147 }
00148
00149
00150 ResolverContext_Ptr
00151 Resolver::context (void) const
00152 {
00153 if (_best_context) return _best_context;
00154 if (_invalid_queues.empty()) return NULL;
00155 ResolverQueue_Ptr invalid = _invalid_queues.front();
00156 return invalid->context();
00157 }
00158
00159
00160
00161 void
00162 Resolver::addSubscribedSource (Source_Ref source)
00163 {
00164 _subscribed.insert(source);
00165 }
00166
00167 void
00168 Resolver::addPoolItemToInstall (PoolItem_Ref item)
00169 {
00170 bool found = false;
00171 for (PoolItemList::const_iterator iter = _items_to_remove.begin();
00172 iter != _items_to_remove.end(); iter++) {
00173 if (*iter == item) {
00174 _items_to_remove.remove(*iter);
00175 found = true;
00176 break;
00177 }
00178 }
00179 if (!found)
00180 _items_to_install.push_back (item);
00181 }
00182
00183
00184 void
00185 Resolver::addPoolItemsToInstallFromList (PoolItemList & rl)
00186 {
00187 for (PoolItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) {
00188 addPoolItemToInstall (*iter);
00189 }
00190 }
00191
00192
00193 void
00194 Resolver::addPoolItemToRemove (PoolItem_Ref item)
00195 {
00196 bool found = false;
00197 for (PoolItemList::const_iterator iter = _items_to_install.begin();
00198 iter != _items_to_install.end(); iter++) {
00199 if (*iter == item) {
00200 _items_to_install.remove(*iter);
00201 found = true;
00202 break;
00203 }
00204 }
00205 if (!found)
00206 _items_to_remove.push_back (item);
00207 }
00208
00209
00210 void
00211 Resolver::addPoolItemsToRemoveFromList (PoolItemList & rl)
00212 {
00213 for (PoolItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) {
00214 addPoolItemToRemove (*iter);
00215 }
00216 }
00217
00218
00219 void
00220 Resolver::addPoolItemToEstablish (PoolItem_Ref item)
00221 {
00222 _items_to_establish.push_back (item);
00223 }
00224
00225
00226 void
00227 Resolver::addPoolItemsToEstablishFromList (PoolItemList & rl)
00228 {
00229 for (PoolItemList::const_iterator iter = rl.begin(); iter != rl.end(); iter++) {
00230 addPoolItemToEstablish (*iter);
00231 }
00232 }
00233
00234
00235 void
00236 Resolver::addPoolItemToVerify (PoolItem_Ref item)
00237 {
00238 #if 0
00239
00240 struct {
00242 bool operator()( PoolItem_Ref lhs, PoolItem_Ref rhs ) const
00243 {
00244 int res = lhs->name().compare( rhs->name() );
00245 if ( res )
00246 return res == -1;
00247
00248 return lhs->edition() < rhs->edition();
00249 }
00250 } order;
00251 #endif
00252
00253 _items_to_verify.push_back (item);
00254
00255 #warning Should order by name (and probably edition since with zypp we could have multiple editions installed in parallel)
00256
00257 }
00258
00259
00260 void
00261 Resolver::addExtraCapability (const Capability & capability)
00262 {
00263 _extra_caps.insert (capability);
00264 }
00265
00266
00267 void
00268 Resolver::addExtraConflict (const Capability & capability)
00269 {
00270 _extra_conflicts.insert (capability);
00271 }
00272
00273
00274 void
00275 Resolver::addIgnoreConflict (const PoolItem_Ref item,
00276 const Capability & capability)
00277 {
00278 _ignoreConflicts.insert(make_pair(item, capability));
00279 }
00280
00281
00282 void
00283 Resolver::addIgnoreRequires (const PoolItem_Ref item,
00284 const Capability & capability)
00285 {
00286 _ignoreRequires.insert(make_pair(item, capability));
00287 }
00288
00289 void
00290 Resolver::addIgnoreObsoletes (const PoolItem_Ref item,
00291 const Capability & capability)
00292 {
00293 _ignoreObsoletes.insert(make_pair(item, capability));
00294 }
00295
00296 void
00297 Resolver::addIgnoreInstalledItem (const PoolItem_Ref item)
00298 {
00299 _ignoreInstalledItem.push_back (item);
00300 }
00301
00302 void
00303 Resolver::addIgnoreArchitectureItem (const PoolItem_Ref item)
00304 {
00305 _ignoreArchitectureItem.push_back (item);
00306 }
00307
00308
00309
00310
00311 struct VerifySystem : public resfilter::PoolItemFilterFunctor
00312 {
00313 Resolver & resolver;
00314
00315 VerifySystem (Resolver & r)
00316 : resolver (r)
00317 { }
00318
00319 bool operator()( PoolItem_Ref provider )
00320 {
00321 resolver.addPoolItemToVerify (provider);
00322 return true;
00323 }
00324 };
00325
00326
00327 bool
00328 Resolver::verifySystem (void)
00329 {
00330 _DEBUG( "Resolver::verifySystem()" );
00331
00332 VerifySystem info (*this);
00333
00334 invokeOnEach( pool().byKindBegin( ResTraits<Package>::kind ),
00335 pool().byKindEnd( ResTraits<Package>::kind ),
00336 resfilter::ByInstalled ( ),
00337 functor::functorRef<bool,PoolItem>(info) );
00338
00339
00340 _verifying = true;
00341
00342 return resolveDependencies ();
00343 }
00344
00345
00346
00347
00348
00349
00350
00351 static void
00352 solution_to_pool (PoolItem_Ref item, const ResStatus & status, void *data)
00353 {
00354 bool r;
00355
00356 if (status.isToBeInstalled()) {
00357 r = item.status().setToBeInstalled( (data != NULL) ? ResStatus::APPL_LOW : ResStatus::SOLVER );
00358 _XDEBUG("solution_to_pool(" << item << ", " << status << ") install !" << r);
00359 }
00360 else if (status.isToBeUninstalledDueToUpgrade()) {
00361 r = item.status().setToBeUninstalledDueToUpgrade( (data != NULL) ? ResStatus::APPL_LOW : ResStatus::SOLVER );
00362 _XDEBUG("solution_to_pool(" << item << ", " << status << ") upgrade !" << r);
00363 }
00364 else if (status.isToBeUninstalled()) {
00365 r = item.status().setToBeUninstalled( (data != NULL) ? ResStatus::APPL_LOW : ResStatus::SOLVER );
00366 _XDEBUG("solution_to_pool(" << item << ", " << status << ") remove !" << r);
00367 }
00368 else if (status.isIncomplete()
00369 || status.isNeeded()) {
00370 r = item.status().setIncomplete();
00371 _XDEBUG("solution_to_pool(" << item << ", " << status << ") incomplete !" << r);
00372 }
00373 else if (status.isUnneeded()) {
00374 r = item.status().setUnneeded();
00375 _XDEBUG("solution_to_pool(" << item << ", " << status << ") unneeded !" << r);
00376 }
00377 else if (status.isSatisfied()) {
00378 r = item.status().setSatisfied();
00379 _XDEBUG("solution_to_pool(" << item << ", " << status << ") satisfied !" << r);
00380 } else {
00381 _XDEBUG("solution_to_pool(" << item << ", " << status << ") unchanged !");
00382 }
00383 return;
00384 }
00385
00386
00387
00388
00389
00390 struct EstablishState
00391 {
00392 Resolver & resolver;
00393
00394 EstablishState (Resolver & r)
00395 : resolver (r)
00396 { }
00397
00398 bool operator()( PoolItem_Ref provider )
00399 {
00400 resolver.addPoolItemToEstablish (provider);
00401 return true;
00402 }
00403 };
00404
00405
00406 void
00407 Resolver::establishState( ResolverContext_Ptr context )
00408 {
00409 _DEBUG( "Resolver::establishState ()" );
00410 typedef list<Resolvable::Kind> KindList;
00411 static KindList ordered;
00412 if (ordered.empty()) {
00413 ordered.push_back (ResTraits<zypp::Atom>::kind);
00414 ordered.push_back (ResTraits<zypp::Patch>::kind);
00415 ordered.push_back (ResTraits<zypp::Pattern>::kind);
00416 ordered.push_back (ResTraits<zypp::Product>::kind);
00417 }
00418
00419 if (context == NULL)
00420 context = new ResolverContext(_pool, _architecture);
00421
00422 context->setEstablishing (true);
00423 context->setIgnoreCababilities (_ignoreConflicts,
00424 _ignoreRequires,
00425 _ignoreObsoletes,
00426 _ignoreInstalledItem,
00427 _ignoreArchitectureItem);
00428 context->setForceResolve( _forceResolve );
00429 context->setUpgradeMode( _upgradeMode );
00430
00431 for (KindList::const_iterator iter = ordered.begin(); iter != ordered.end(); iter++) {
00432 const Resolvable::Kind kind = *iter;
00433
00434 DBG << "establishing state for kind " << kind.asString() << endl;
00435
00436
00437
00438 EstablishState info (*this);
00439
00440 invokeOnEach( pool().byKindBegin( kind ),
00441 pool().byKindEnd( kind ),
00442 functor::functorRef<bool,PoolItem>(info) );
00443
00444
00445 resolveDependencies( context );
00446
00447 reset();
00448 }
00449
00450 context->setEstablishing (false);
00451
00452 _best_context = context;
00453
00454 return;
00455 }
00456
00457
00458 bool
00459 Resolver::establishPool ()
00460 {
00461 MIL << "Resolver::establishPool()" << endl;
00462
00463 establishState ();
00464 ResolverContext_Ptr solution = bestContext();
00465
00466 if (solution) {
00467 solution->foreachMarked (solution_to_pool, (void *)1);
00468 }
00469 else {
00470 ERR << "establishState did not return a bestContext" << endl;
00471 return false;
00472 }
00473
00474 return true;
00475 }
00476
00477
00478
00479
00480
00481 typedef map<string, PoolItem_Ref> FreshenMap;
00482
00483
00484
00485
00486
00487 static void
00488 addToFreshen( PoolItem_Ref item, FreshenMap & itemmap )
00489 {
00490 FreshenMap::iterator it = itemmap.find( item->name() );
00491 if (it != itemmap.end()) {
00492 int cmp = it->second->arch().compare( item->arch() );
00493 if (cmp < 0) {
00494 it->second = item;
00495 }
00496 else if (cmp == 0) {
00497 if (it->second->edition().compare( item->edition() ) < 0) {
00498 it->second = item;
00499 }
00500 }
00501 }
00502 else {
00503 itemmap[item->name()] = item;
00504 }
00505 return;
00506 }
00507
00508
00509 struct FreshenState
00510 {
00511 FreshenMap itemmap;
00512
00513 FreshenState()
00514 { }
00515
00516 bool operator()( PoolItem_Ref item)
00517 {
00518 CapSet freshens( item->dep( Dep::FRESHENS ) );
00519 if (!freshens.empty()) {
00520 addToFreshen( item, itemmap );
00521 }
00522 else {
00523
00524
00525 CapSet supplements( item->dep( Dep::SUPPLEMENTS ) );
00526 if (!supplements.empty()) {
00527 addToFreshen( item, itemmap );
00528 }
00529 }
00530 return true;
00531 }
00532 };
00533
00534
00535 void
00536 Resolver::freshenState( ResolverContext_Ptr context )
00537 {
00538 _DEBUG( "Resolver::freshenState ()" );
00539
00540 if (context == NULL)
00541 context = new ResolverContext( _pool, _architecture );
00542
00543 context->setEstablishing( true );
00544 context->setIgnoreCababilities( _ignoreConflicts,
00545 _ignoreRequires,
00546 _ignoreObsoletes,
00547 _ignoreInstalledItem,
00548 _ignoreArchitectureItem );
00549 context->setForceResolve( _forceResolve );
00550 context->setUpgradeMode( _upgradeMode );
00551
00552 FreshenState info;
00553
00554
00555
00556 invokeOnEach( pool().byKindBegin( ResTraits<zypp::Package>::kind ),
00557 pool().byKindEnd( ResTraits<zypp::Package>::kind ),
00558 functor::functorRef<bool,PoolItem>(info) );
00559
00560
00561
00562 for (FreshenMap::iterator it = info.itemmap.begin(); it != info.itemmap.end(); ++it) {
00563 addPoolItemToEstablish( it->second );
00564 }
00565
00566
00567 resolveDependencies( context );
00568
00569 reset();
00570
00571 context->setEstablishing( false );
00572
00573 _best_context = context;
00574
00575 return;
00576 }
00577
00578
00579 bool
00580 Resolver::freshenPool ()
00581 {
00582 MIL << "Resolver::freshenPool()" << endl;
00583
00584 freshenState ();
00585 ResolverContext_Ptr solution = bestContext();
00586
00587 if (solution) {
00588 solution->foreachMarked (solution_to_pool, (void *)1);
00589 }
00590 else {
00591 ERR << "freshenState did not return a bestContext" << endl;
00592 return false;
00593 }
00594
00595 return true;
00596 }
00597
00598
00599
00600 bool
00601 Resolver::resolveDependencies (const ResolverContext_Ptr context)
00602 {
00603
00604 time_t t_start, t_now;
00605
00606 MIL << "Resolver::resolveDependencies()" << endl;
00607
00608 _pending_queues.clear();
00609 _pruned_queues.clear();
00610 _complete_queues.clear();
00611 _deferred_queues.clear();
00612 _invalid_queues.clear();
00613 _valid_solution_count = 0;
00614 _best_context = NULL;
00615
00616 #warning local items disabled
00617 #if 0
00618 bool have_local_items = false;
00619
00620
00621
00622 for (PoolItemList::const_iterator iter = _items_to_install.begin(); iter != _items_to_install.end(); iter++) {
00623 if ((*iter)->local()) {
00624 have_local_items = true;
00625 break;
00626 }
00627 }
00628
00629 World_Ptr the_world = world();
00630 StoreWorld_Ptr local_world = NULL;
00631 MultiWorld_Ptr local_multiworld = NULL;
00632
00633 Channel_Ptr local_channel = NULL;
00634
00635 if (have_local_items) {
00636 local_multiworld = new MultiWorld();
00637 local_world = new StoreWorld();
00638
00639 local_channel = new Channel ("", "Local ResItems", "@local", "");
00640
00641 local_world->addChannel (local_channel);
00642
00643 local_multiworld->addSubworld (local_world);
00644 local_multiworld->addSubworld (the_world);
00645
00646 the_world = local_multiworld;
00647 }
00648 #endif
00649
00650
00651
00652 ResolverQueue_Ptr initial_queue = new ResolverQueue(_pool, _architecture, context);
00653
00654
00655 initial_queue->context()->setIgnoreCababilities (_ignoreConflicts,
00656 _ignoreRequires,
00657 _ignoreObsoletes,
00658 _ignoreInstalledItem,
00659 _ignoreArchitectureItem);
00660 initial_queue->context()->setForceResolve( _forceResolve );
00661 initial_queue->context()->setUpgradeMode( _upgradeMode );
00662
00663
00664
00665 initial_queue->context()->setVerifying( _verifying );
00666
00667
00668
00669 for (QueueItemList::const_iterator iter = _initial_items.begin(); iter != _initial_items.end(); iter++) {
00670 initial_queue->addItem (*iter);
00671 }
00672
00673 for (PoolItemList::const_iterator iter = _items_to_install.begin(); iter != _items_to_install.end(); iter++) {
00674 PoolItem_Ref r = *iter;
00675
00676 #warning local items disabled
00677 #if 0
00678
00679 if (r->local()) {
00680 assert (local_channel != NULL);
00681 ResItem_Ptr r1 = const_pointer_cast<ResItem>(r);
00682 r1->setChannel (local_channel);
00683 local_world->addPoolItem_Ref (r);
00684 }
00685 #endif
00686 initial_queue->addPoolItemToInstall (r);
00687 }
00688
00689 for (PoolItemList::const_iterator iter = _items_to_remove.begin(); iter != _items_to_remove.end(); iter++) {
00690 if (!_upgradeMode)
00691 initial_queue->addPoolItemToRemove (*iter, true );
00692 else
00693
00694
00695
00696
00697
00698 initial_queue->addPoolItemToRemove (*iter, false );
00699 }
00700
00701 for (PoolItemList::const_iterator iter = _items_to_verify.begin(); iter != _items_to_verify.end(); iter++) {
00702 initial_queue->addPoolItemToVerify (*iter);
00703 }
00704
00705 for (PoolItemList::const_iterator iter = _items_to_establish.begin(); iter != _items_to_establish.end(); iter++) {
00706 initial_queue->addPoolItemToEstablish (*iter);
00707 }
00708
00709 for (CapSet::const_iterator iter = _extra_caps.begin(); iter != _extra_caps.end(); iter++) {
00710 initial_queue->addExtraCapability (*iter);
00711 }
00712
00713 for (CapSet::const_iterator iter = _extra_conflicts.begin(); iter != _extra_conflicts.end(); iter++) {
00714 initial_queue->addExtraConflict (*iter);
00715 }
00716
00717
00718 assertSystemResObjectInPool();
00719
00720 _DEBUG( "Initial Queue: [" << *initial_queue << "]" );
00721
00722 if (initial_queue->isEmpty()) {
00723 INT << "Empty Queue, nothing to resolve" << endl;
00724
00725 return true;
00726 }
00727
00728 _best_context = NULL;
00729
00730 _pending_queues.push_front (initial_queue);
00731
00732 time (&t_start);
00733
00734 while (!_pending_queues.empty()) {
00735
00736 _DEBUG( "Pend " << (long) _pending_queues.size()
00737 << " / Cmpl " << (long) _complete_queues.size()
00738 << " / Prun " << (long) _pruned_queues.size()
00739 << " / Defr " << (long) _deferred_queues.size()
00740 << " / Invl " << (long) _invalid_queues.size() );
00741
00742 if (_timeout_seconds > 0) {
00743 time (&t_now);
00744 if (difftime (t_now, t_start) > _timeout_seconds) {
00745 _timed_out = true;
00746 break;
00747 }
00748 }
00749
00750 ResolverQueue_Ptr queue = _pending_queues.front();
00751 _pending_queues.pop_front();
00752 ResolverContext_Ptr context = queue->context();
00753
00754 queue->process();
00755
00756 if (queue->isInvalid ()) {
00757
00758 DBG << "Invalid Queue\n" << endl;;
00759 _invalid_queues.push_back(queue);
00760
00761 } else if (queue->isEmpty ()) {
00762
00763 DBG <<"Empty Queue\n" << endl;
00764
00765 _complete_queues.push_back(queue);
00766
00767 ++_valid_solution_count;
00768
00769
00770
00771
00772
00773 if (_best_context == NULL
00774 || _best_context->compare (context) < 0) {
00775 _best_context = context;
00776 }
00777
00778 } else if (_best_context != NULL
00779 && _best_context->partialCompare (context) > 0) {
00780
00781
00782
00783
00784 DBG << "PRUNED!" << endl;
00785
00786 _pruned_queues.push_back(queue);
00787
00788 } else {
00789
00790
00791
00792
00793 queue->splitFirstBranch (_pending_queues, _deferred_queues);
00794 }
00795
00796
00797
00798
00799
00800 if (_pending_queues.empty()
00801 && _complete_queues.empty()
00802 && !_deferred_queues.empty()) {
00803 _pending_queues.push_back(_deferred_queues.front());
00804 }
00805 }
00806 _DEBUG("Pend " << (long) _pending_queues.size()
00807 << " / Cmpl " << (long) _complete_queues.size()
00808 << " / Prun " << (long) _pruned_queues.size()
00809 << " / Defr " << (long) _deferred_queues.size()
00810 << " / Invl " << (long) _invalid_queues.size() );
00811
00812 return _best_context && _best_context->isValid();
00813 }
00814
00815
00816
00817
00818
00819 struct UndoTransact : public resfilter::PoolItemFilterFunctor
00820 {
00821 UndoTransact ()
00822 { }
00823
00824 bool operator()( PoolItem_Ref item )
00825 {
00826 item.status().resetTransact( ResStatus::APPL_LOW );
00827 return true;
00828 }
00829 };
00830
00831 void
00832 Resolver::undo(void)
00833 {
00834 UndoTransact info;
00835 MIL << "*** undo ***" << endl;
00836 invokeOnEach ( _pool.begin(), _pool.end(),
00837 resfilter::ByTransact( ),
00838 functor::functorRef<bool,PoolItem>(info) );
00839
00840 _ignoreConflicts.clear();
00841
00842 _ignoreRequires.clear();
00843
00844 _ignoreObsoletes.clear();
00845
00846 _ignoreArchitecture.clear();
00847
00848 _ignoreInstalledItem.clear();
00849
00850 _ignoreArchitectureItem.clear();
00851
00852
00853 return;
00854 }
00855
00856
00857
00858
00859 struct CollectTransact : public resfilter::PoolItemFilterFunctor
00860 {
00861 Resolver & resolver;
00862
00863 CollectTransact (Resolver & r)
00864 : resolver (r)
00865 { }
00866
00867 bool operator()( PoolItem_Ref item )
00868 {
00869 ResStatus status = item.status();
00870 _XDEBUG( "CollectTransact(" << item << ")" );
00871 bool by_solver = (status.isBySolver() || status.isByApplLow());
00872
00873 if (by_solver) {
00874 item.status().resetTransact( ResStatus::APPL_LOW );
00875 return true;
00876 }
00877
00878 if (status.isToBeInstalled()) {
00879 resolver.addPoolItemToInstall(item);
00880 }
00881 if (status.isToBeUninstalled()) {
00882 resolver.addPoolItemToRemove(item);
00883 }
00884 if (status.isIncomplete()) {
00885 PoolItem_Ref reinstall = Helper::findReinstallItem (resolver.pool(), item);
00886 if (reinstall) {
00887 MIL << "Reinstall " << reinstall << " for incomplete " << item << endl;
00888 resolver.addPoolItemToInstall(reinstall);
00889 }
00890 else {
00891 WAR << "Can't find " << item << " for re-installation" << endl;
00892 }
00893 }
00894 return true;
00895 }
00896 };
00897
00898
00899 static void
00900 show_pool( ResPool pool )
00901 {
00902 int count = 1;
00903 static bool full_pool_shown = false;
00904
00905 MIL << "---------------------------------------" << endl;
00906 for (ResPool::const_iterator it = pool.begin(); it != pool.end(); ++it, ++count) {
00907
00908 if (!full_pool_shown
00909 || it->status().transacts()
00910 || !it->status().isUndetermined())
00911 {
00912 MIL << count << ": " << *it << endl;
00913 }
00914
00915 }
00916 MIL << "---------------------------------------" << endl;
00917 full_pool_shown = true;
00918 }
00919
00920
00921
00922
00923
00924
00925
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936 bool
00937 Resolver::resolvePool ()
00938 {
00939
00940 CollectTransact info (*this);
00941
00942
00943 reset();
00944
00945 #if 1
00946
00947 MIL << "Resolver::resolvePool()" << endl;
00948 MIL << "Pool before resolve" << endl;
00949 show_pool( _pool );
00950
00951 #endif
00952 invokeOnEach ( _pool.begin(), _pool.end(),
00953 resfilter::ByTransact( ),
00954 functor::functorRef<bool,PoolItem>(info) );
00955
00956 bool have_solution = resolveDependencies ();
00957
00958 if (have_solution) {
00959 MIL << "Have solution, copying back to pool" << endl;
00960 ResolverContext_Ptr solution = bestContext();
00961 solution->foreachMarked (solution_to_pool, NULL);
00962 #if 1
00963 MIL << "Pool after resolve" << endl;
00964 show_pool( _pool );
00965 #endif
00966 }
00967 else {
00968 MIL << "!!! Have NO solution !!!" << endl;
00969 }
00970 return have_solution;
00971 }
00972
00973
00974
00975 static bool
00976 transactItems( PoolItem_Ref installed, PoolItem_Ref uninstalled, bool install, bool soft )
00977 {
00978 if (install) {
00979 if (uninstalled
00980 && !uninstalled.status().isLocked())
00981 {
00982 if (soft)
00983 uninstalled.status().setSoftTransact( true, ResStatus::APPL_LOW );
00984 else
00985 uninstalled.status().setTransact( true, ResStatus::APPL_LOW );
00986 }
00987 if (installed
00988 && !installed.status().isLocked())
00989 {
00990 installed.status().resetTransact( ResStatus::APPL_LOW );
00991 }
00992 } else {
00993
00994 if (uninstalled
00995 && !uninstalled.status().isLocked())
00996 {
00997 uninstalled.status().resetTransact( ResStatus::APPL_LOW );
00998 }
00999 if (installed
01000 && !installed.status().isLocked())
01001 {
01002 if (soft)
01003 installed.status().setSoftTransact( true, ResStatus::APPL_LOW );
01004 else
01005 installed.status().setTransact( true, ResStatus::APPL_LOW );
01006 }
01007 }
01008 if (!uninstalled
01009 && !installed)
01010 {
01011 return false;
01012 }
01013 return true;
01014 }
01015
01016
01017
01018
01019 typedef struct { PoolItem_Ref installed; PoolItem_Ref uninstalled; } IandU;
01020 typedef map<string, IandU> IandUMap;
01021
01022 struct FindIandU
01023 {
01024 IandUMap iandu;
01025
01026 FindIandU ()
01027 { }
01028
01029 bool operator()( const CapAndItem & cai )
01030 {
01031 PoolItem item( cai.item );
01032 if ( item.status().staysInstalled() ) {
01033 iandu[item->name()].installed = item;
01034 }
01035 else if ( item.status().staysUninstalled() ) {
01036 IandUMap::iterator it = iandu.find( item->name() );
01037
01038 if (it != iandu.end()
01039 && it->second.uninstalled)
01040 {
01041 int cmp = it->second.uninstalled->arch().compare( item->arch() );
01042 if (cmp < 0) {
01043 it->second.uninstalled = item;
01044 }
01045 else if (cmp == 0) {
01046 if (it->second.uninstalled->edition().compare( item->edition() ) < 0) {
01047 it->second.uninstalled = item;
01048 }
01049 }
01050 }
01051 else {
01052 iandu[item->name()].uninstalled = item;
01053 }
01054 }
01055 return true;
01056 }
01057 };
01058
01059
01060
01061
01062
01063
01064
01065
01066
01067 static bool
01068 transactCaps( const ResPool & pool, const CapSet & caps, bool install, bool soft )
01069 {
01070 bool result = true;
01071
01072
01073
01074 for (CapSet::const_iterator cit = caps.begin(); cit != caps.end(); ++cit) {
01075
01076 FindIandU callback;
01077 Dep dep( Dep::PROVIDES );
01078 invokeOnEach( pool.byCapabilityIndexBegin( cit->index(), dep ),
01079 pool.byCapabilityIndexEnd( cit->index(), dep ),
01080 resfilter::ByCapMatch( *cit ) ,
01081 functor::functorRef<bool,CapAndItem>(callback) );
01082
01083 for (IandUMap::const_iterator it = callback.iandu.begin(); it != callback.iandu.end(); ++it) {
01084 if (!transactItems( it->second.installed, it->second.uninstalled, install, soft )) {
01085 result = false;
01086 }
01087 }
01088
01089 }
01090 return result;
01091 }
01092
01093
01094 struct TransactSupplements : public resfilter::PoolItemFilterFunctor
01095 {
01096 const Resolvable::Kind &_kind;
01097 bool valid;
01098
01099 TransactSupplements( const Resolvable::Kind & kind )
01100 : _kind( kind )
01101 , valid( false )
01102 { }
01103
01104 bool operator()( PoolItem_Ref item )
01105 {
01106
01107 if (item->kind() == _kind
01108 && (item.status().staysInstalled()
01109 || item.status().isToBeInstalled()))
01110 {
01111 valid = true;
01112 return false;
01113 }
01114 return true;
01115 }
01116 };
01117
01118
01119
01120
01121
01122 struct TransactLanguage : public resfilter::PoolItemFilterFunctor
01123 {
01124 Resolver & _resolver;
01125 ResObject::constPtr _langObj;
01126 bool _install;
01127
01128 TransactLanguage( Resolver & r, ResObject::constPtr langObj, bool install )
01129 : _resolver( r )
01130 , _langObj( langObj )
01131 , _install( install )
01132 { }
01133
01134
01135
01136
01137 bool operator()( const CapAndItem & cai )
01138 {
01139
01140
01141 PoolItem_Ref item( cai.item );
01142
01143 CapSet supplements( item->dep( Dep::SUPPLEMENTS ) );
01144 if (!supplements.empty()) {
01145
01146 bool valid = false;
01147 for (CapSet::const_iterator it = supplements.begin(); it != supplements.end(); ++it) {
01148
01149 TransactSupplements callback( it->refers() );
01150 invokeOnEach( _resolver.pool().byNameBegin( it->index() ),
01151 _resolver.pool().byNameEnd( it->index() ),
01152 functor::functorRef<bool,PoolItem>( callback ) );
01153 if (callback.valid) {
01154 valid = true;
01155 break;
01156 }
01157 }
01158 if (!valid) {
01159
01160 return true;
01161 }
01162 }
01163
01164 if (_install) {
01165 if (item.status().staysUninstalled()) {
01166 transactItems( PoolItem_Ref(), item, _install, true );
01167 }
01168 }
01169 else {
01170 if (item.status().staysInstalled()) {
01171 transactItems( item, PoolItem_Ref(), _install, true );
01172 }
01173 }
01174 return true;
01175 }
01176 };
01177
01178
01179
01180
01181
01182
01183
01184
01185 bool
01186 Resolver::transactResObject( ResObject::constPtr robj, bool install)
01187 {
01188 if (robj == NULL) {
01189 ERR << "NULL ResObject" << endl;
01190 }
01191 DBG << "transactResObject(" << *robj << ", " << (install?"install":"remove") << ")" << endl;
01192
01193 if (robj->kind() == ResTraits<Language>::kind) {
01194 TransactLanguage callback( *this, robj, install );
01195 Dep dep( Dep::FRESHENS );
01196 invokeOnEach( pool().byCapabilityIndexBegin( robj->name(), dep ),
01197 pool().byCapabilityIndexEnd( robj->name(), dep ),
01198 functor::functorRef<bool,CapAndItem>( callback ) );
01199
01200 }
01201 transactCaps( _pool, robj->dep( Dep::RECOMMENDS ), install, true );
01202 return transactCaps( _pool, robj->dep( Dep::REQUIRES ), install, false );
01203 }
01204
01205
01206
01207
01208
01209
01210
01211 struct TransactKind : public resfilter::PoolItemFilterFunctor
01212 {
01213 Resolver & _resolver;
01214 bool install;
01215 bool result;
01216
01217 TransactKind( Resolver & r )
01218 : _resolver( r )
01219 , result( true )
01220 { }
01221
01222 bool operator()( PoolItem_Ref item )
01223 {
01224 result = _resolver.transactResObject( item.resolvable(), install );
01225 return true;
01226 }
01227 };
01228
01229
01230 bool
01231 Resolver::transactResKind( Resolvable::Kind kind )
01232 {
01233 TransactKind callback (*this);
01234
01235 DBG << "transactResKind(" << kind << ")" << endl;
01236
01237
01238 callback.install = false;
01239 invokeOnEach( pool().byKindBegin( kind ),
01240 pool().byKindEnd( kind ),
01241 functor::chain( resfilter::ByTransact(), resfilter::ByInstalled ()),
01242 functor::functorRef<bool,PoolItem>( callback ) );
01243
01244
01245 callback.install = true;
01246 invokeOnEach( pool().byKindBegin( kind ),
01247 pool().byKindEnd( kind ),
01248 functor::chain( resfilter::ByTransact(), resfilter::ByUninstalled ()),
01249 functor::functorRef<bool,PoolItem>( callback ) );
01250
01251 return callback.result;
01252 }
01253
01254
01255 struct TransactReset : public resfilter::PoolItemFilterFunctor
01256 {
01257 ResStatus::TransactByValue _causer;
01258 TransactReset( ResStatus::TransactByValue causer )
01259 : _causer( causer )
01260 { }
01261
01262 bool operator()( PoolItem_Ref item )
01263 {
01264 item.status().resetTransact( _causer );
01265 return true;
01266 }
01267 };
01268
01269
01270 void
01271 Resolver::transactReset( ResStatus::TransactByValue causer )
01272 {
01273 TransactReset info( causer );
01274 MIL << "transactReset(" << causer << ")" << endl;
01275 invokeOnEach ( _pool.begin(), _pool.end(),
01276 resfilter::ByTransact( ),
01277 functor::functorRef<bool,PoolItem>(info) );
01278 return;
01279 }
01280
01282 };
01285 };
01288 };
01290