00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <values.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 #include "zypp/base/String.h"
00030
00031 #include "zypp/base/Algorithm.h"
00032 #include "zypp/ResPool.h"
00033 #include "zypp/ResFilters.h"
00034 #include "zypp/CapFilters.h"
00035 #include "zypp/Package.h"
00036 #include "zypp/Resolvable.h"
00037
00038 #include "zypp/solver/detail/Types.h"
00039 #include "zypp/solver/detail/Helper.h"
00040 #include "zypp/solver/detail/ResolverContext.h"
00041 #include "zypp/solver/detail/ResolverInfoMisc.h"
00042 #include "zypp/solver/detail/ResolverInfoConflictsWith.h"
00043
00045 namespace zypp
00046 {
00047
00048 namespace solver
00049 {
00050
00051 namespace detail
00052 {
00053
00054 using namespace std;
00055
00056 IMPL_PTR_TYPE(ResolverContext);
00057
00058
00059
00060 class compare_items {
00061 public:
00062 int operator() (PoolItem_Ref p1,
00063 PoolItem_Ref p2) const
00064 { return compareByN(p1.resolvable(),p2.resolvable()) < 0 ; }
00065 };
00066
00067
00068
00069
00070 ostream&
00071 operator<<( ostream& os, const ResolverContext & context)
00072 {
00073 if (context._parent != NULL) {
00074 os << "Parent @" << context._parent << endl;
00075 os << *(context._parent);
00076 }
00077 os << "ResolverContext with " << context._context.size() << " entries" << endl;
00078 for (ResolverContext::Context::const_iterator iter = context._context.begin(); iter != context._context.end(); ++iter) {
00079 os << iter->first << " : " << iter->second << endl;
00080 }
00081 return os;
00082 }
00083
00084
00085
00086 ResolverContext::ResolverContext (const ResPool & pool, const Arch & arch, ResolverContext_Ptr parent)
00087 : _parent (parent)
00088 , _pool (pool)
00089 , _download_size (0)
00090 , _install_size (0)
00091 , _total_priority (0)
00092 , _min_priority (0)
00093 , _max_priority (0)
00094 , _other_penalties (0)
00095 , _verifying (false)
00096 , _establishing (false)
00097 , _invalid (false)
00098 , _askUser(false)
00099 , _architecture(arch)
00100 , _forceResolve(false)
00101 , _upgradeMode(false)
00102 , _tryAllPossibilities(false)
00103 , _scippedPossibilities(false)
00104
00105 {
00106 _XDEBUG( "ResolverContext[" << this << "]::ResolverContext(" << parent << ")" );
00107 if (parent != NULL) {
00108 _pool = parent->_pool;
00109 _download_size = parent->_download_size;
00110 _install_size = parent->_install_size;
00111 _total_priority = parent->_total_priority;
00112 _max_priority = parent->_max_priority;
00113 _min_priority = parent->_min_priority;
00114 _other_penalties = parent->_other_penalties;
00115 _verifying = parent->_verifying;
00116 _establishing = parent->_establishing;
00117 _ignoreConflicts = parent->_ignoreConflicts;
00118 _ignoreRequires = parent->_ignoreRequires;
00119 _ignoreObsoletes = parent->_ignoreObsoletes;
00120 _ignoreInstalledItem = parent->_ignoreInstalledItem;
00121 _ignoreArchitectureItem = parent->_ignoreArchitectureItem;
00122 _forceResolve = parent->_forceResolve;
00123 _upgradeMode = parent->_upgradeMode;
00124 _tryAllPossibilities = parent->_tryAllPossibilities;
00125 _scippedPossibilities = parent->_scippedPossibilities;
00126
00127 } else {
00128 _min_priority = MAXINT;
00129 }
00130 }
00131
00132
00133 ResolverContext::~ResolverContext()
00134 {
00135 }
00136
00137
00138
00139
00140 ResStatus
00141 ResolverContext::getStatus (PoolItem_Ref item)
00142 {
00143
00144
00145 if (item == _last_checked_item) return _last_checked_status;
00146
00147 _last_checked_item = item;
00148
00149 Context::const_iterator it;
00150 ResolverContext_constPtr context = this;
00151
00152 while (context) {
00153
00154 it = context->_context.find(item);
00155 if (it != context->_context.end()) {
00156
00157 _last_checked_status = it->second;
00158 return it->second;
00159 }
00160 context = context->_parent;
00161 }
00162
00163 ResStatus status( item.status() );
00164 status.resetTransact( ResStatus::USER );
00165 #if 0
00166 if (item.status().isInstalled())
00167 status = ResStatus::installed;
00168 else
00169 status = ResStatus::uninstalled;
00170 #endif
00171 _last_checked_status = status;
00172
00173
00174 return _last_checked_status;
00175 }
00176
00177
00178
00179
00180
00181 void
00182 ResolverContext::setStatus (PoolItem_Ref item, const ResStatus & status)
00183 {
00184 if (_invalid) return;
00185
00186 _XDEBUG( "[" << this << "]setStatus(" << item << ", " << status << ")" );
00187 ResStatus old_status = getStatus (item);
00188
00189 if (old_status != status) {
00190 _XDEBUG( "MARK" );
00191 _context[item] = status;
00192 }
00193
00194 _last_checked_item = item;
00195 _last_checked_status = status;
00196
00197 return;
00198 }
00199
00200
00201
00202
00203 bool
00204 ResolverContext::install (PoolItem_Ref item, bool is_soft, int other_penalty)
00205 {
00206 ResStatus status, new_status;
00207 std::string msg;
00208
00209 status = getStatus(item);
00210 _XDEBUG( "ResolverContext[" << this << "]::install(<" << status << "> " << item << ")" );
00211
00212 if (status.isToBeUninstalled()
00213 && !status.isToBeUninstalledDueToUnlink()) {
00214 ResolverInfo_Ptr misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_INSTALL_TO_BE_UNINSTALLED, item, RESOLVER_INFO_PRIORITY_VERBOSE);
00215 addError (misc_info);
00216 return false;
00217 }
00218
00219 if (status.isImpossible()) {
00220 ResolverInfo_Ptr misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_UNINSTALLABLE, item, RESOLVER_INFO_PRIORITY_VERBOSE);
00221
00222 if (is_soft) {
00223 addInfo (misc_info);
00224 } else {
00225 addError (misc_info);
00226 }
00227 return false;
00228 }
00229
00230 if (status.isUnneeded()
00231 && ( item->kind() == ResTraits<Patch>::kind
00232 || item->kind() == ResTraits<Atom>::kind)) {
00233 ResolverInfo_Ptr misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_INSTALL_UNNEEDED, item, RESOLVER_INFO_PRIORITY_VERBOSE);
00234 addInfo (misc_info);
00235 return false;
00236 }
00237
00238 if (status.isToBeInstalled()) {
00239 return true;
00240 }
00241
00242 if (isParallelInstall( item )) {
00243 ResolverInfoMisc_Ptr misc_info = new ResolverInfoMisc( RESOLVER_INFO_TYPE_INSTALL_PARALLEL, item, RESOLVER_INFO_PRIORITY_VERBOSE );
00244 misc_info->setOtherPoolItem( getParallelInstall( item ) );
00245 addError( misc_info );
00246 return false;
00247 }
00248
00249 if (is_soft)
00250 setStatus (item, ResStatus::toBeInstalledSoft);
00251 else if (status.isToBeUninstalledDueToUnlink())
00252 setStatus (item, ResStatus(true));
00253 else
00254 setStatus (item, ResStatus::toBeInstalled);
00255
00256 if (status.wasUninstalled()) {
00257 Resolvable::constPtr res = item.resolvable();
00258 Package::constPtr pkg = asKind<Package>(res);
00259 if (pkg) {
00260
00261 _download_size += pkg->archivesize();
00262 _install_size += pkg->size();
00263
00264 }
00265
00266 int priority;
00267 #if 0
00268 if (item->local())
00269 priority = 0;
00270 else {
00271 #endif
00272 priority = getSourcePriority (item->source());
00273
00274
00275 if (priority < _min_priority) _min_priority = priority;
00276 if (priority > _max_priority) _max_priority = priority;
00277
00278 _other_penalties += other_penalty;
00279
00280 }
00281
00282 return true;
00283 }
00284
00285
00286
00287
00288 bool
00289 ResolverContext::upgrade (PoolItem_Ref item, PoolItem_Ref old_item, bool is_soft, int other_penalty)
00290 {
00291 ResStatus status;
00292
00293 _XDEBUG( "ResolverContext[" << this << "]::upgrade(" << item << " upgrades " << old_item << ")" );
00294
00295 status = getStatus(item);
00296
00297 if (status.isToBeUninstalled()
00298 || status.isImpossible())
00299 return false;
00300
00301 if (status.isToBeInstalled())
00302 return true;
00303
00304 if (isParallelInstall( item )) {
00305 ResolverInfoMisc_Ptr misc_info = new ResolverInfoMisc( RESOLVER_INFO_TYPE_INSTALL_PARALLEL, item, RESOLVER_INFO_PRIORITY_VERBOSE );
00306 misc_info->setOtherPoolItem( getParallelInstall( item ) );
00307 addError( misc_info );
00308 return false;
00309 }
00310
00311 ResStatus::TransactByValue by = ResStatus::SOLVER;
00312 if (item.status().isToBeInstalled()
00313 && item.status().getTransactByValue() > ResStatus::SOLVER) {
00314
00315
00316
00317 by = item.status().getTransactByValue();
00318 }
00319
00320 if (is_soft) {
00321 ResStatus newStatus = ResStatus::toBeInstalledSoft;
00322 setStatus (item, newStatus);
00323 }
00324 else {
00325 ResStatus newStatus;
00326 newStatus.setToBeInstalled (by);
00327 setStatus (item, newStatus);
00328 }
00329
00330 Resolvable::constPtr res = old_item.resolvable();
00331 Package::constPtr pkg = asKind<Package>(res);
00332 if (pkg) {
00333
00334 _install_size -= pkg->size();
00335 }
00336
00337 if (status == ResStatus::uninstalled) {
00338 res = item.resolvable();
00339 pkg = asKind<Package>(res);
00340 if (pkg) {
00341
00342 _download_size += pkg->archivesize();
00343 _install_size += pkg->size();
00344
00345 }
00346
00347 int priority;
00348 #if 0
00349 if (item->local())
00350 priority = 0;
00351 else {
00352 #endif
00353 priority = getSourcePriority (item->source());
00354
00355
00356 if (priority < _min_priority) _min_priority = priority;
00357 if (priority > _max_priority) _max_priority = priority;
00358
00359 _other_penalties += other_penalty;
00360 }
00361 return true;
00362 }
00363
00364
00365
00366
00367 bool
00368 ResolverContext::uninstall (PoolItem_Ref item, bool part_of_upgrade, bool due_to_obsolete, bool due_to_unlink)
00369 {
00370 ResStatus status, new_status;
00371 std::string msg;
00372
00373 status = getStatus(item);
00374
00375 _XDEBUG( "ResolverContext[" << this << "]::uninstall("
00376 << item << " " << (part_of_upgrade ? "part_of_upgrade" : "") << " "
00377 << (due_to_obsolete ? "due_to_obsolete": "") << " "
00378 << (due_to_unlink ? "due_to_unlink" : "") << ")" << "context-status:" << status);
00379
00380 assert (! (due_to_obsolete && due_to_unlink));
00381
00382 if ( ( (forceResolve()
00383 || upgradeMode())
00384 && (status.isToBeInstalledNotSoft()
00385 || item.status().isToBeInstalledNotSoft()))
00386
00387 || ( (!forceResolve()
00388 && !upgradeMode())
00389 && ((status.staysInstalled() || status.isToBeInstalledNotSoft())
00390 && (item.status().staysInstalled() || item.status().isToBeInstalledNotSoft())
00391 || status.isToBeInstalledNotSoft())
00392
00393 && !part_of_upgrade
00394 && !due_to_obsolete
00395 && !due_to_unlink)) {
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411 bool found = false;
00412
00413 ResolverInfoList addList;
00414 for (ResolverInfoList::const_iterator iter = _log.begin(); iter != _log.end(); iter++) {
00415 ResolverInfo_Ptr info = *iter;
00416
00417 if (info->type() == RESOLVER_INFO_TYPE_CONFLICT_CANT_INSTALL
00418 || info->type() == RESOLVER_INFO_TYPE_CONFLICTS_WITH) {
00419
00420
00421
00422 PoolItem_Ref other_item = PoolItem_Ref();
00423 if (info->type() == RESOLVER_INFO_TYPE_CONFLICT_CANT_INSTALL) {
00424 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(info);
00425 other_item = misc_info->other();
00426 } else {
00427 ResolverInfoConflictsWith_constPtr conflicts_with = dynamic_pointer_cast<const ResolverInfoConflictsWith>(info);
00428 if (conflicts_with->items().size() == 1) {
00429
00430 other_item = *(conflicts_with->items().begin());
00431 }
00432 }
00433
00434 bool other_found = false;
00435
00436 if (other_item != PoolItem_Ref()) {
00437
00438 for (ResolverInfoList::const_iterator iter_other = addList.begin();
00439 iter_other != addList.end(); iter_other++) {
00440
00441 if ((*iter_other)->type() == RESOLVER_INFO_TYPE_CONFLICT_CANT_INSTALL) {
00442 ResolverInfoMisc_constPtr misc_info = dynamic_pointer_cast<const ResolverInfoMisc>(*iter_other);
00443 if ( (other_item == misc_info->other()
00444 && item == misc_info->affected())
00445 || (other_item == misc_info->affected()
00446 && item == misc_info->other()))
00447 other_found = true;
00448 }
00449 else if ((*iter_other)->type() == RESOLVER_INFO_TYPE_CONFLICTS_WITH) {
00450 ResolverInfoConflictsWith_constPtr conflicts_with = dynamic_pointer_cast<const ResolverInfoConflictsWith>(*iter_other);
00451 if (conflicts_with->items().size() == 1) {
00452
00453 if ( (other_item == *(conflicts_with->items().begin())
00454 && item == conflicts_with->affected())
00455 || (other_item == conflicts_with->affected()
00456 && item == *(conflicts_with->items().begin())))
00457 other_found = true;
00458 }
00459 }
00460 }
00461 }
00462
00463 if ( !other_found
00464 && (info->affected() == item
00465 || other_item == item)) {
00466
00467 found = true;
00468 addList.push_back (info);
00469 }
00470 } else if ( (info->type() == RESOLVER_INFO_TYPE_NO_PROVIDER
00471 || info->type() == RESOLVER_INFO_TYPE_NO_OTHER_PROVIDER
00472 || info->type() == RESOLVER_INFO_TYPE_CANT_SATISFY)
00473 && info->affected() == item)
00474 {
00475
00476 found = true;
00477
00478 if (!info->error())
00479 addList.push_back (info);
00480 } else if (info->type() == RESOLVER_INFO_TYPE_CONFLICTS_WITH
00481 && info->affected() == item) {
00482
00483 found = true;
00484
00485 if (!info->error())
00486 addList.push_back (info);
00487 }
00488 }
00489 if (!found) {
00490
00491 ResolverInfo_Ptr misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_REJECT_INSTALL, item, RESOLVER_INFO_PRIORITY_VERBOSE);
00492 addError (misc_info, true);
00493 } else {
00494
00495 for (ResolverInfoList::const_iterator iter = addList.begin(); iter != addList.end(); iter++) {
00496 ResolverInfo_Ptr info = *iter;
00497 addError (info, true);
00498 }
00499 }
00500
00501
00502 }
00503
00504 if (status.isToBeUninstalled()
00505 && !status.isToBeUninstalledDueToUnlink())
00506 {
00507 return true;
00508 }
00509
00510 if (status.wasUninstalled()
00511 || status.isImpossible()
00512 || status.isToBeUninstalledDueToUnlink())
00513 {
00514 ResolverInfo_Ptr misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_UNINSTALLABLE, item, RESOLVER_INFO_PRIORITY_VERBOSE);
00515 addInfo (misc_info);
00516 }
00517
00518 if (due_to_obsolete) {
00519 setStatus (item, ResStatus::toBeUninstalledDueToObsolete);
00520 }
00521 else if (due_to_unlink) {
00522 setStatus (item, ResStatus::toBeUninstalledDueToUnlink);
00523 }
00524 else if (status.wasUninstalled()) {
00525 setStatus (item, ResStatus::impossible);
00526 }
00527 else if (part_of_upgrade) {
00528 setStatus (item, ResStatus::toBeUninstalledDueToUpgrade);
00529 }
00530 else {
00531 setStatus (item, ResStatus::toBeUninstalled);
00532 }
00533
00534 if (status.wasInstalled()) {
00535 Resolvable::constPtr res = item.resolvable();
00536 Package::constPtr pkg = asKind<Package>(res);
00537 if (pkg) {
00538 _install_size -= pkg->size();
00539 }
00540 }
00541
00542 return true;
00543 }
00544
00545
00546
00547
00548 bool
00549 ResolverContext::unneeded (PoolItem_Ref item, int other_penalty)
00550 {
00551 ResStatus status;
00552
00553 _XDEBUG( "ResolverContext[" << this << "]::unneeded(" << item << ")" );
00554
00555 status = getStatus(item);
00556
00557 if (status.wasInstalled()) {
00558 if (item->kind() != ResTraits<Patch>::kind
00559 && item->kind() != ResTraits<Atom>::kind
00560 && item->kind() != ResTraits<Script>::kind
00561 && item->kind() != ResTraits<Message>::kind) {
00562 setStatus (item, ResStatus::satisfied);
00563 } else {
00564
00565
00566
00567 setStatus (item, ResStatus::unneeded);
00568 }
00569 }
00570 else if (status.wasUninstalled()) {
00571 setStatus (item, ResStatus::unneeded);
00572 }
00573 return true;
00574 }
00575
00576
00577
00578
00579 bool
00580 ResolverContext::satisfy (PoolItem_Ref item, int other_penalty)
00581 {
00582 ResStatus status;
00583
00584 status = getStatus(item);
00585
00586 _XDEBUG( "ResolverContext[" << this << "]::satisfy(" << item << ":" << status << ")" );
00587
00588 if (status.wasInstalled()) {
00589 setStatus (item, ResStatus::complete);
00590 }
00591 else if (status.wasUninstalled()) {
00592 setStatus (item, ResStatus::satisfied);
00593 }
00594
00595 return true;
00596 }
00597
00598
00599
00600
00601 bool
00602 ResolverContext::incomplete (PoolItem_Ref item, int other_penalty)
00603 {
00604 ResStatus status = getStatus (item);
00605
00606 _XDEBUG( "ResolverContext[" << this << "]::incomplete(" << item << "):" << status );
00607
00608 if (_establishing) {
00609 if (status.wasInstalled()) {
00610 setStatus (item, ResStatus::incomplete);
00611 }
00612 else {
00613 setStatus (item, ResStatus::needed);
00614 }
00615
00616 return true;
00617 }
00618
00619
00620
00621 if (status.staysInstalled()) {
00622 ResolverInfo_Ptr misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_INCOMPLETES, item, RESOLVER_INFO_PRIORITY_VERBOSE);
00623 addError (misc_info);
00624 return false;
00625 }
00626
00627 return true;
00628 }
00629
00630
00631
00632
00633
00634
00635 bool
00636 ResolverContext::isPresent (PoolItem_Ref item, bool *unneeded, bool *installed)
00637 {
00638 ResStatus status = getStatus(item);
00639
00640 bool res = ((status.staysInstalled() && !status.isIncomplete())
00641 || (status.isToBeInstalled() && !status.isNeeded())
00642 || status.isUnneeded()
00643 || status.isSatisfied()
00644 );
00645
00646 if (unneeded) *unneeded = status.isUnneeded();
00647 if (installed) *installed = status.staysInstalled() || status.isToBeInstalled();
00648
00649 _XDEBUG("ResolverContext::itemIsPresent(<" << status << ">" << item << ") " << (res?"Y":"N"));
00650
00651 return res;
00652 }
00653
00654
00655
00656
00657
00658 bool
00659 ResolverContext::isAbsent (PoolItem_Ref item)
00660 {
00661 ResStatus status = getStatus(item);
00662
00663
00664
00665 bool res = (status.staysUninstalled()
00666 || status.isToBeUninstalled()
00667 || status.isImpossible());
00668
00669 _XDEBUG("ResolverContext::itemIsAbsent(<" << status << ">" << item << ") " << (res?"Y":"N"));
00670
00671 return res;
00672 }
00673
00674
00675
00676
00677
00678 void
00679 ResolverContext::foreachMarked (MarkedPoolItemFn fn, void *data) const
00680 {
00681 ResolverContext_constPtr context = this;
00682 while (context) {
00683 for (Context::const_iterator iter = context->_context.begin(); iter != context->_context.end(); ++iter) {
00684 fn (iter->first, iter->second, data);
00685 }
00686 context = context->_parent;
00687 }
00688 }
00689
00690
00691
00692
00693
00694 typedef struct {
00695 PoolItemList *rl;
00696 int status;
00697 } MarkedResolvableInfo;
00698
00699
00700 static void
00701 marked_item_collector (PoolItem_Ref item, const ResStatus & status, void *data)
00702 {
00703 MarkedResolvableInfo *info = (MarkedResolvableInfo *)data;
00704 if (info->status == 0
00705 || (info->status > 0 && status.isToBeInstalled())
00706 || (info->status < 0 && status.isToBeUninstalled()))
00707 {
00708 info->rl->push_back (item);
00709 }
00710 }
00711
00712
00713 PoolItemList
00714 ResolverContext::getMarked (int which)
00715 {
00716 if ( _last_getMarked_which == which
00717 && _last_getMarked.size() > 0 )
00718 return _last_getMarked;
00719
00720 MarkedResolvableInfo info = { &_last_getMarked, which };
00721
00722 foreachMarked (marked_item_collector, &info);
00723
00724 _last_getMarked.sort(compare_items());
00725 _last_getMarked_which = which;
00726
00727 return _last_getMarked;
00728 }
00729
00730
00731
00732
00733 typedef struct {
00734 ResPool pool;
00735 MarkedPoolItemFn fn;
00736 PoolItemList *rl;
00737 int count;
00738 } InstallInfo;
00739
00740 static void
00741 install_item_cb (PoolItem_Ref item, const ResStatus & status, void *data)
00742 {
00743 InstallInfo *info = (InstallInfo *)data;
00744
00745 if (status.isToBeInstalled()
00746 && !item.status().isInstalled()
00747 && !Helper::findInstalledItem( info->pool, item))
00748 {
00749 if (info->fn) info->fn (item, status, info->rl);
00750 ++info->count;
00751 }
00752 }
00753
00754
00755 int
00756 ResolverContext::foreachInstall (MarkedPoolItemFn fn, void *data) const
00757 {
00758 PoolItemList *rl = (PoolItemList *)data;
00759 InstallInfo info = { _pool, fn, rl, 0 };
00760
00761 foreachMarked (install_item_cb, (void *)&info);
00762
00763 return info.count;
00764 }
00765
00766
00767 static void
00768 context_item_collector (PoolItem_Ref item, const ResStatus & status, void *data)
00769 {
00770 PoolItemList *rl = (PoolItemList *)data;
00771 if (status.isToBeInstalled()
00772 || status.isToBeUninstalled())
00773 {
00774 rl->push_front (item);
00775 }
00776 }
00777
00778
00779 PoolItemList
00780 ResolverContext::getInstalls (void) const
00781 {
00782 PoolItemList rl;
00783
00784 foreachInstall (context_item_collector, (void *)&rl);
00785
00786 return rl;
00787 }
00788
00789
00790
00791
00792
00793 typedef struct {
00794 ResPool pool;
00795 MarkedPoolItemFn fn;
00796 PoolItemList *rl;
00797 int count;
00798 } SatisfyInfo;
00799
00800 static void
00801 satisfy_item_cb (PoolItem_Ref item, const ResStatus & status, void *data)
00802 {
00803 SatisfyInfo *info = (SatisfyInfo *)data;
00804 if (status.isSatisfied()
00805 && ! status.staysInstalled ()
00806 && !Helper::findInstalledItem (info->pool, item))
00807 {
00808 if (info->fn) info->fn (item, status, info->rl);
00809 ++info->count;
00810 }
00811 }
00812
00813
00814 int
00815 ResolverContext::foreachSatisfy (MarkedPoolItemFn fn, void *data) const
00816 {
00817 PoolItemList *rl = (PoolItemList *)data;
00818 SatisfyInfo info = { _pool, fn, rl, 0 };
00819
00820 foreachMarked (satisfy_item_cb, (void *)&info);
00821
00822 return info.count;
00823 }
00824
00825
00826 static void
00827 context_item_collector_satisfy (PoolItem_Ref item, const ResStatus & status, void *data)
00828 {
00829 PoolItemList *rl = (PoolItemList *)data;
00830 if (status.isSatisfied ())
00831 {
00832 rl->push_front (item);
00833 }
00834 }
00835
00836
00837 PoolItemList
00838 ResolverContext::getSatisfies (void) const
00839 {
00840 PoolItemList rl;
00841
00842 foreachSatisfy (context_item_collector_satisfy, (void *)&rl);
00843
00844 return rl;
00845 }
00846
00847
00848
00849
00850
00851 typedef struct {
00852 ResPool pool;
00853 MarkedPoolItemFn fn;
00854 PoolItemList *rl;
00855 int count;
00856 } IncompleteInfo;
00857
00858 static void
00859 incomplete_item_cb (PoolItem_Ref item, const ResStatus & status, void *data)
00860 {
00861 IncompleteInfo *info = (IncompleteInfo *)data;
00862
00863 if (status.isIncomplete ()) {
00864 if (info->fn) info->fn (item, status, info->rl);
00865 ++info->count;
00866 }
00867 }
00868
00869
00870 int
00871 ResolverContext::foreachIncomplete (MarkedPoolItemFn fn, void *data) const
00872 {
00873 PoolItemList *rl = (PoolItemList *)data;
00874 IncompleteInfo info = { _pool, fn, rl, 0 };
00875
00876 foreachMarked (incomplete_item_cb, (void *)&info);
00877
00878 return info.count;
00879 }
00880
00881
00882 static void
00883 context_item_collector_incomplete (PoolItem_Ref item, const ResStatus & status, void *data)
00884 {
00885 PoolItemList *rl = (PoolItemList *)data;
00886 if (status.isIncomplete ())
00887 {
00888 rl->push_front (item);
00889 }
00890 }
00891
00892
00893 PoolItemList
00894 ResolverContext::getIncompletes (void) const
00895 {
00896 PoolItemList rl;
00897
00898 foreachIncomplete (context_item_collector_incomplete, (void *)&rl);
00899
00900 return rl;
00901 }
00902
00903
00904
00905
00906
00907 typedef struct {
00908 ResPool pool;
00909 MarkedPoolItemPairFn fn;
00910 void *data;
00911 ResolverContext_Ptr context;
00912 int count;
00913 } UpgradeInfo;
00914
00915 static void
00916 upgrade_item_cb (PoolItem_Ref item, const ResStatus & status, void *data)
00917 {
00918 UpgradeInfo *info = (UpgradeInfo *)data;
00919
00920 PoolItem_Ref installed_item;
00921
00922 if (status.isToBeInstalled()
00923 && ! item.status().isInstalled ())
00924 {
00925
00926 installed_item = Helper::findInstalledItem( info->pool, item );
00927 if (installed_item) {
00928
00929
00930 ResStatus installed_status( info->context->getStatus( installed_item ) );
00931
00932
00933 if (!installed_status.transacts())
00934 return;
00935
00936 if (info->fn) {
00937 info->fn (item, status, installed_item, installed_status, info->data);
00938 }
00939 ++info->count;
00940 }
00941 }
00942 }
00943
00944
00945 int
00946 ResolverContext::foreachUpgrade (MarkedPoolItemPairFn fn, void *data)
00947 {
00948 UpgradeInfo info = { _pool, fn, data, this, 0 };
00949
00950 foreachMarked (upgrade_item_cb, (void *)&info);
00951
00952 return info.count;
00953 }
00954
00955
00956 static void
00957 pair_item_collector (PoolItem_Ref item, const ResStatus & status, PoolItem_Ref old_item, const ResStatus & old_status, void *data)
00958 {
00959 PoolItemList *rl = (PoolItemList *)data;
00960 rl->push_back (item);
00961 }
00962
00963
00964 PoolItemList
00965 ResolverContext::getUpgrades (void)
00966 {
00967 PoolItemList rl;
00968
00969 foreachUpgrade (pair_item_collector, (void *)&rl);
00970
00971 return rl;
00972 }
00973
00974
00975
00976
00977
00978 typedef std::map<std::string,PoolItem_Ref> UpgradeTable;
00979
00980 typedef struct {
00981 MarkedPoolItemFn fn;
00982 PoolItemList *rl;
00983 UpgradeTable upgrade_hash;
00984 int count;
00985 } UninstallInfo;
00986
00987 static void
00988 uninstall_item_cb (PoolItem_Ref item, const ResStatus & status, void *data)
00989 {
00990 UninstallInfo *info = (UninstallInfo *)data;
00991
00992 UpgradeTable::const_iterator pos = info->upgrade_hash.find(item->name());
00993
00994 if (status.isToBeUninstalled ()
00995 && pos == info->upgrade_hash.end())
00996 {
00997 if (info->fn)
00998 info->fn (item, status, info->rl);
00999 ++info->count;
01000 }
01001 }
01002
01003
01004 static void
01005 build_upgrade_hash_cb (PoolItem_Ref item_add, const ResStatus & add_status, PoolItem_Ref item_del, const ResStatus & del_status, void *data)
01006 {
01007 UpgradeTable *upgrade_hash = (UpgradeTable *)data;
01008 (*upgrade_hash)[item_del->name()] = item_del;
01009 }
01010
01011
01012 int
01013 ResolverContext::foreachUninstall (MarkedPoolItemFn fn, void *data)
01014 {
01015 UninstallInfo info;
01016
01017 info.fn = fn;
01018 info.rl = (PoolItemList *)data;
01019 info.count = 0;
01020
01021 foreachUpgrade (build_upgrade_hash_cb, (void *)&(info.upgrade_hash));
01022 foreachMarked (uninstall_item_cb, (void *)&info);
01023
01024 return info.count;
01025 }
01026
01027
01028 PoolItemList
01029 ResolverContext::getUninstalls (void)
01030 {
01031 PoolItemList rl;
01032
01033 foreachUninstall (context_item_collector, (void *)&rl);
01034
01035 return rl;
01036 }
01037
01038
01039
01040
01041
01042 typedef struct {
01043 ResPool pool;
01044 MarkedPoolItemFn fn;
01045 int count;
01046 void *data;
01047 } ImpossibleInfo;
01048
01049 static void
01050 impossible_item_cb (PoolItem_Ref item, const ResStatus & status, void *data)
01051 {
01052 ImpossibleInfo *info = (ImpossibleInfo *)data;
01053
01054 if (status.isImpossible ()) {
01055 if (info->fn) info->fn (item, status, info->data);
01056 ++info->count;
01057 }
01058 }
01059
01060
01061 int
01062 ResolverContext::foreachImpossible (MarkedPoolItemFn fn, void *data)
01063 {
01064 ImpossibleInfo info = { _pool, fn, 0, data };
01065
01066 foreachMarked (impossible_item_cb, (void *)&info);
01067
01068 return info.count;
01069 }
01070
01071
01072
01073
01074 static void
01075 install_count_cb (PoolItem_Ref item, const ResStatus & status, void *data)
01076 {
01077 int *count = (int *)data;
01078 if (!item.status().isInstalled ()) {
01079 ++*count;
01080 }
01081 }
01082
01083 int
01084 ResolverContext::installCount (void) const
01085 {
01086 int count = 0;
01087
01088 foreachInstall (install_count_cb, (void *)&count);
01089
01090 return count;
01091 }
01092
01093
01094 static void
01095 uninstall_count_cb (PoolItem_Ref item, const ResStatus & status, void *data)
01096 {
01097 int *count = (int *)data;
01098 if (item.status().isInstalled ()) {
01099 ++*count;
01100 }
01101 }
01102
01103
01104 int
01105 ResolverContext::uninstallCount (void)
01106 {
01107 int count = 0;
01108
01109 foreachUninstall (uninstall_count_cb, (void *)&count);
01110
01111 return count;
01112 }
01113
01114
01115 int
01116 ResolverContext::upgradeCount (void)
01117 {
01118 return foreachUpgrade ((MarkedPoolItemPairFn)NULL, (void *)NULL);
01119 }
01120
01121
01122 static void
01123 satisfy_count_cb (PoolItem_Ref item, const ResStatus & status, void *data)
01124 {
01125 int *count = (int *)data;
01126 if (!item.status().isInstalled ()) {
01127 ++*count;
01128 }
01129 }
01130
01131 int
01132 ResolverContext::satisfyCount (void) const
01133 {
01134 int count = 0;
01135
01136 foreachSatisfy (satisfy_count_cb, (void *)&count);
01137
01138 return count;
01139 }
01140
01141
01142 int
01143 ResolverContext::incompleteCount (void) const
01144 {
01145 return foreachIncomplete ((MarkedPoolItemFn)NULL, (void *)NULL);
01146 }
01147
01148
01149
01150
01151
01152
01153 void
01154 ResolverContext::addInfo (ResolverInfo_Ptr info, bool askUser)
01155 {
01156 _XDEBUG( "ResolverContext[" << this << "]::addInfo(" << *info << ")" );
01157 _log.push_back (info);
01158
01159
01160
01161 if (info->error ()
01162 && !askUser) {
01163
01164 if (! _invalid) {
01165 ResolverInfo_Ptr info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_INVALID_SOLUTION, PoolItem_Ref(), RESOLVER_INFO_PRIORITY_VERBOSE);
01166 info->flagAsError ();
01167 _log.push_back (info);
01168 }
01169
01170 _invalid = true;
01171 }
01172 if (askUser)
01173 _askUser = true;
01174 }
01175
01176
01177 void
01178 ResolverContext::addError (ResolverInfo_Ptr info, bool askUser)
01179 {
01180 bool is_error = true;
01181
01182 if (info->type() == RESOLVER_INFO_TYPE_UNINSTALL_LOCKED) {
01183 for (PoolItemList::const_iterator iter = _ignoreInstalledItem.begin(); iter != _ignoreInstalledItem.end(); iter++) {
01184 if (info->affected() == *iter) {
01185 DBG << "ignore keep installed: " << info->affected() << endl;
01186 is_error = false;
01187 break;
01188 }
01189 }
01190 }
01191
01192 if (is_error)
01193 info->flagAsError ();
01194
01195 WAR << "******** Error: " << *info << endl;
01196 addInfo (info, askUser);
01197 }
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208
01209
01210 static void
01211 mark_important_info (const ResolverInfoList & il)
01212 {
01213
01214 PoolItemSet error_set;
01215
01216 bool did_something;
01217 int pass_num = 1;
01218
01219
01220
01221 for (ResolverInfoList::const_iterator info_iter = il.begin(); info_iter != il.end(); ++info_iter) {
01222 ResolverInfo_Ptr info = (*info_iter);
01223 if (info != NULL
01224 && info->error ())
01225 {
01226 PoolItem_Ref item = info->affected();
01227 if (item) {
01228 error_set.insert (item);
01229 }
01230
01231
01232
01233 PoolItemList containerItems;
01234 ResolverInfoContainer_constPtr c = dynamic_pointer_cast<const ResolverInfoContainer>(*info_iter);
01235 if (c != NULL) containerItems = c->items();
01236
01237
01238
01239 for (PoolItemList::iterator res_iter = containerItems.begin(); res_iter != containerItems.end(); res_iter++) {
01240 PoolItem_Ref item = (*res_iter);
01241 if (item) {
01242 error_set.insert (item);
01243 }
01244 }
01245 }
01246 }
01247
01248
01249
01250 PoolItemSet important_set;
01251
01252 do {
01253 ++pass_num;
01254 assert (pass_num < 10000);
01255
01256 did_something = false;
01257
01258 for (ResolverInfoList::const_iterator info_iter = il.begin(); info_iter != il.end(); ++info_iter) {
01259
01260 ResolverInfo_Ptr info = (*info_iter);
01261
01262 if (info != NULL
01263 && !info->important ())
01264 {
01265 bool should_be_important = false;
01266
01267 for (PoolItemSet::const_iterator res_iter = error_set.begin(); res_iter != error_set.end() && ! should_be_important; ++res_iter) {
01268 ResolverInfoContainer_constPtr c = dynamic_pointer_cast<const ResolverInfoContainer>(*info_iter);
01269 if (c != NULL
01270 && c->mentions (*res_iter))
01271 {
01272 should_be_important = true;
01273 }
01274 }
01275
01276 for (PoolItemSet::const_iterator res_iter = important_set.begin(); res_iter != important_set.end() && ! should_be_important; ++res_iter) {
01277 if (info->isAbout (*res_iter)) {
01278 should_be_important = true;
01279 break;
01280 }
01281 }
01282
01283 if (should_be_important) {
01284 did_something = true;
01285 info->flagAsImportant ();
01286 PoolItemList items;
01287 ResolverInfoContainer_constPtr c = dynamic_pointer_cast<const ResolverInfoContainer>(*info_iter);
01288 if (c != NULL) items = c->items();
01289 for (PoolItemList::iterator res_iter = items.begin(); res_iter != items.end(); res_iter++) {
01290 important_set.insert (*res_iter);
01291 }
01292 }
01293 }
01294 }
01295
01296 } while (did_something);
01297
01298 }
01299
01300 void
01301 ResolverContext::foreachInfo (PoolItem_Ref item, int priority, ResolverInfoFn fn, void *data) const
01302 {
01303 ResolverInfoList info_list;
01304
01305 ResolverContext_constPtr context = this;
01306
01307 while (context != NULL) {
01308
01309 for (ResolverInfoList::const_iterator iter = context->_log.begin(); iter != context->_log.end(); ++iter) {
01310
01311 ResolverInfo_Ptr info = *iter;
01312
01313 if ((item == PoolItem_Ref()
01314 || info->affected() == item)
01315 && info->priority() >= priority)
01316 {
01317 info_list.push_back( info );
01318 }
01319 }
01320 context = context->_parent;
01321 }
01322 #if 1
01323
01324 for (ResolverInfoList::iterator iter = info_list.begin(); iter != info_list.end(); ++iter) {
01325
01326 ResolverInfo_Ptr info1 = (*iter);
01327 ResolverInfoList::iterator subiter = iter;
01328
01329 if (info1 != NULL) {
01330 for (subiter++; subiter != info_list.end();) {
01331 ResolverInfo_Ptr info2 = *subiter;
01332 ResolverInfoList::iterator next = subiter; ++next;
01333 if (info2 && info1->merge (info2)) {
01334 info_list.erase( subiter );
01335 }
01336 subiter = next;
01337 }
01338 }
01339 }
01340 #endif
01341 mark_important_info( info_list );
01342
01343
01344
01345 for (ResolverInfoList::iterator iter = info_list.begin(); iter != info_list.end(); ++iter) {
01346 if (*iter != NULL) {
01347 fn( *iter, data );
01348 }
01349 }
01350 }
01351
01352
01353
01354 static void
01355 get_info_foreach_cb (ResolverInfo_Ptr info, void *data)
01356 {
01357 ResolverInfoList *il = (ResolverInfoList *)data;
01358
01359 if (info->important ()) {
01360 il->push_back (info);
01361 }
01362 }
01363
01364
01365
01366 ResolverInfoList
01367 ResolverContext::getInfo (void) const
01368 {
01369 ResolverInfoList il;
01370 foreachInfo (PoolItem_Ref(), -1, get_info_foreach_cb, (void *)&il);
01371 return il;
01372 }
01373
01374
01375
01376
01377
01378 static void
01379 spew_item_cb (PoolItem_Ref item, const ResStatus & status, void *unused)
01380 {
01381 MIL << " " << item << " (" << status << ")" << endl;
01382 }
01383
01384
01385 void
01386 spew_item_pair_cb (PoolItem_Ref item1, const ResStatus & status1, PoolItem_Ref item2, const ResStatus & status2, void *unused)
01387 {
01388 MIL << " " << item2 << " (" << status2 << ") => (" << item1 << " (" << status2 << ")" << endl;
01389 }
01390
01391
01392 void
01393 ResolverContext::spew (void)
01394 {
01395 MIL << "TO INSTALL:" << endl;
01396 foreachInstall (spew_item_cb, NULL);
01397 MIL << endl;
01398
01399 MIL << "TO REMOVE:" << endl;
01400 foreachUninstall (spew_item_cb, NULL);
01401 MIL << endl;
01402
01403 MIL << "TO UPGRADE:" << endl;
01404 foreachUpgrade (spew_item_pair_cb, NULL);
01405 MIL << endl;
01406 }
01407
01408
01409 static void
01410 spew_info_cb (ResolverInfo_Ptr info, void *unused)
01411 {
01412 if (info == NULL) return;
01413
01414 if (info->error ()) MIL << "[ERROR] " << *info << endl;
01415 else if (info->important()) MIL << "[>>>>>] " << *info << endl;
01416 else MIL << *info << endl;
01417 }
01418
01419
01420 void
01421 ResolverContext::spewInfo (void) const
01422 {
01423 _XDEBUG( "ResolverContext[" << this << "]::spewInfo" );
01424 foreachInfo (PoolItem_Ref(), -1, spew_info_cb, NULL);
01425 }
01426
01427
01428
01429
01430 struct RequirementMet
01431 {
01432 ResolverContext_Ptr context;
01433 bool flag;
01434 bool unneeded;
01435 bool *installed;
01436
01437 RequirementMet (ResolverContext_Ptr ctx, bool *inst)
01438 : context (ctx)
01439 , flag (false)
01440 , unneeded( false )
01441 , installed( inst )
01442 { }
01443
01444
01445 bool operator()( const CapAndItem & cai )
01446 {
01447 Capability match( cai.cap );
01448 PoolItem provider( cai.item );
01449
01450
01451 bool my_unneeded = false;
01452 if (context->isPresent( provider, &my_unneeded, installed ))
01453 {
01454 unneeded = my_unneeded;
01455 flag = true;
01456 }
01457
01458
01459
01460
01461 if ( installed
01462 && !*installed )
01463 return true;
01464
01465 return ! flag;
01466 }
01467 };
01468
01469
01470 bool
01471 ResolverContext::requirementIsMet (const Capability & capability, bool *unneeded, bool *installed)
01472 {
01473 RequirementMet info (this, installed);
01474
01475
01476
01477 Dep dep( Dep::PROVIDES );
01478
01479
01480
01481 invokeOnEach( pool().byCapabilityIndexBegin( capability.index(), dep ),
01482 pool().byCapabilityIndexEnd( capability.index(), dep ),
01483 resfilter::ByCapMatch( capability ),
01484 functor::functorRef<bool,CapAndItem>(info) );
01485 _XDEBUG( "ResolverContext::requirementIsMet(" << capability << ") " << (info.flag?"Y":"N") );
01486 if (unneeded) *unneeded = info.unneeded;
01487
01488 return info.flag;
01489 }
01490
01491
01498 bool
01499 ResolverContext::requirementIsInstalledOrUnneeded (const ResObject::Kind & kind,
01500 const Capability & capability)
01501 {
01502 bool fulfilled = false;
01503
01504 if (kind != ResTraits<Package>::kind
01505 || kind != ResTraits<Script>::kind
01506 || kind != ResTraits<Message>::kind)
01507 {
01508 bool unneeded, installed;
01509 fulfilled = requirementIsMet (capability, &unneeded, &installed);
01510 if (!fulfilled
01511 || (!unneeded
01512 && !installed)) {
01513 fulfilled = false;
01514 _XDEBUG("Requirement is not unneeded and not installed.");
01515
01516
01517 }
01518 }else {
01519 fulfilled = requirementIsMet (capability);
01520 }
01521
01522 return fulfilled;
01523 }
01524
01525
01526
01527
01528
01529 struct RequirementPossible
01530 {
01531 ResolverContext_Ptr context;
01532 bool flag;
01533
01534 RequirementPossible( ResolverContext_Ptr ctx )
01535 : context (ctx)
01536 , flag (false)
01537 { }
01538
01539 bool operator()( const CapAndItem & cai )
01540 {
01541 PoolItem provider( cai.item );
01542 ResStatus status = context->getStatus( provider );
01543 if (! (status.isToBeUninstalled () || status.isImpossible())
01544 || status.isToBeUninstalledDueToUnlink())
01545 {
01546 flag = true;
01547 }
01548
01549
01550
01551 if (flag
01552 && !context->forceResolve()) {
01553 PoolItem installedItem = Helper::findInstalledByNameAndKind (context->pool(), provider->name(), provider->kind() );
01554 if (installedItem) {
01555 ResStatus statusInstalled = context->getStatus (installedItem);
01556 if (installedItem.status().isToBeUninstalled()
01557 && installedItem.status().isByUser()){
01558 DBG << provider << " would satify the requirement but it has been selected for removing by the user." << endl;
01559 flag = false;
01560 }
01561 }
01562 }
01563
01564 return ! flag;
01565 }
01566 };
01567
01568
01569 bool
01570 ResolverContext::requirementIsPossible (const Capability & capability)
01571 {
01572 RequirementPossible info( this );
01573
01574
01575
01576 Dep dep( Dep::PROVIDES );
01577
01578 invokeOnEach( pool().byCapabilityIndexBegin( capability.index(), dep ),
01579 pool().byCapabilityIndexEnd( capability.index(), dep ),
01580 resfilter::ByCapMatch( capability ),
01581 functor::functorRef<bool,CapAndItem>(info) );
01582 _XDEBUG("requirementIsPossible( " << capability << ") = " << (info.flag ? "Y" : "N"));
01583 return info.flag;
01584 }
01585
01586
01587 bool
01588 ResolverContext::itemIsPossible (PoolItem_Ref item)
01589 {
01590 CapSet requires = item->dep (Dep::REQUIRES);
01591 for (CapSet::iterator iter = requires.begin(); iter != requires.end(); iter++) {
01592 if (! requirementIsPossible (*iter)) {
01593 return false;
01594 }
01595 }
01596
01597 return true;
01598 }
01599
01600
01601
01602 typedef struct {
01603 PoolItem_Ref other;
01604 bool flag;
01605 PoolItem_Ref foundItem;
01606 } DupNameCheckInfo;
01607
01608 static void
01609 dup_name_check_cb (PoolItem_Ref item, const ResStatus & status, void *data)
01610 {
01611 DupNameCheckInfo *info = (DupNameCheckInfo *)data;
01612 if (! info->flag
01613 && status.isToBeInstalled ()
01614 && info->other->kind() == item->kind()
01615 && info->other->name() == item->name()
01616 #if 0
01617 && item->edition().compare(info->other->edition()) == 0
01618 && item->arch() == info->other->arch()
01619 #endif
01620 && item != info->other)
01621 {
01622 Package::constPtr p1 = asKind<Package>(item.resolvable());
01623 Package::constPtr p2 = asKind<Package>(info->other.resolvable());
01624 if (p1 && p2 && p1->installOnly() && p2->installOnly())
01625 return;
01626
01627 info->flag = true;
01628 info->foundItem = item;
01629 }
01630 }
01631
01632
01633 bool
01634 ResolverContext::isParallelInstall (PoolItem_Ref item) const
01635 {
01636 if (item->kind() == ResTraits<Atom>::kind) {
01637 return false;
01638 }
01639
01640 for (PoolItemList::const_iterator iter = _ignoreInstalledItem.begin();
01641 iter != _ignoreInstalledItem.end(); iter++) {
01642 if (item == *iter) {
01643 DBG << "ignore parallel install: " << item << endl;
01644 return false;
01645 }
01646 }
01647
01648 DupNameCheckInfo info;
01649
01650 info.other = item;
01651 info.flag = false;
01652 foreachMarked (dup_name_check_cb, (void *)&info);
01653 if (info.flag) {
01654 DBG << "isParallelInstall!!(" << item << ", " << info.foundItem << ")" << endl;
01655 }
01656 return info.flag;
01657 }
01658
01659
01660 PoolItem_Ref
01661 ResolverContext::getParallelInstall (PoolItem_Ref item) const
01662 {
01663 DupNameCheckInfo info;
01664
01665 info.other = item;
01666 info.flag = false;
01667 foreachMarked( dup_name_check_cb, (void *)&info );
01668 return info.foundItem;
01669 }
01670
01671
01672 int
01673 ResolverContext::getSourcePriority (Source_Ref source) const
01674 {
01675 if (source.subscribed())
01676 return source.priority();
01677 return source.priorityUnsubscribed();
01678 }
01679
01680
01681
01682 static int
01683 num_cmp (double a, double b)
01684 {
01685 return (b < a) - (a < b);
01686 }
01687
01688 static int
01689 rev_num_cmp (double a, double b)
01690 {
01691 return (a < b) - (b < a);
01692 }
01693
01694 static double
01695 churn_factor (ResolverContext_Ptr a)
01696 {
01697 return a->upgradeCount() + (2.0 * a->installCount ()) + (4.0 * a->uninstallCount ());
01698 }
01699
01700 void
01701 ResolverContext::collectCompareInfo (int & cmpVersion,
01702 int & cmpSource,
01703 ResolverContext_Ptr compareContext)
01704 {
01705 Source_Ref userSource;
01706
01707 bool differentUserSources = false;
01708 Source_Ref userSourceCompare;
01709
01710 bool differentUserCompareSources = false;
01711 SourceCounter thisMap;
01712 SourceCounter compareMap;
01713
01714 PoolItemList installList = getMarked(1);
01715 PoolItemList compareList = compareContext->getMarked(1);;
01716 PoolItemList::const_iterator itCompare = compareList.begin();
01717 _XDEBUG ("Starting comparing two solutions--------");
01718 for ( PoolItemList::const_iterator thisIt = installList.begin();
01719 thisIt != installList.end(); thisIt++ )
01720 {
01721
01722 ResStatus status = getStatus (*thisIt);
01723 if (status.isByUser()
01724 || thisIt->status().isByUser())
01725 {
01726 if (userSource == Source_Ref::noSource
01727 && !differentUserSources)
01728 {
01729 userSource = thisIt->resolvable()->source();
01730 }
01731 else if (userSource != thisIt->resolvable()->source())
01732 {
01733 differentUserSources = true;
01734 }
01735 }
01736
01737
01738 if (thisMap.find (thisIt->resolvable()->source()) == thisMap.end()) {
01739 thisMap[thisIt->resolvable()->source()] = 1;
01740 }
01741 else {
01742 thisMap[thisIt->resolvable()->source()] += 1;
01743 }
01744 _XDEBUG ("Count of left " << thisIt->resolvable()->source() << ": " << thisMap[thisIt->resolvable()->source()] << " : " << *(thisIt->resolvable()));
01745
01746
01747 while (itCompare != compareList.end() )
01748 {
01749 int cmp = compareByN ( thisIt->resolvable(), itCompare->resolvable());
01750 if ( cmp == 0) {
01751
01752
01753
01754
01755 cmpVersion += thisIt->resolvable()->edition().compare( itCompare->resolvable()->edition());
01756 _XDEBUG ("Version: " << *(thisIt->resolvable()) << "[" << thisIt->resolvable()->source() << "]" << endl
01757 << " <--> " << endl
01758 << "Version: " << *(itCompare->resolvable()) << "[" << itCompare->resolvable()->source() << "]"
01759 << " --> cmpVersion : " << cmpVersion);
01760
01761
01762 ResObject::constPtr sourceItem = itCompare->resolvable();
01763 ResStatus compStatus = compareContext->getStatus(*itCompare);
01764 if (compStatus.isByUser()
01765 || itCompare->status().isByUser())
01766 {
01767 if (userSourceCompare == Source_Ref::noSource
01768 && !differentUserCompareSources)
01769 userSourceCompare = sourceItem->source();
01770 else if (userSourceCompare != sourceItem->source())
01771 differentUserCompareSources = true;
01772 }
01773
01774 if (compareMap.find (sourceItem->source()) == compareMap.end())
01775 compareMap[sourceItem->source()] = 1;
01776 else
01777 compareMap[sourceItem->source()] += 1;
01778 _XDEBUG ("Count of right " << sourceItem->source() << ": " << compareMap[sourceItem->source()] << " : " << *(itCompare->resolvable()));
01779 itCompare++;
01780 } else if (cmp > 0 )
01781 itCompare++;
01782 else break;
01783 }
01784 }
01785
01786
01787 while (itCompare != compareList.end() )
01788 {
01789
01790 ResObject::constPtr sourceItem = itCompare->resolvable();
01791 ResStatus compStatus = compareContext->getStatus(*itCompare);
01792 if (compStatus.isByUser()
01793 || itCompare->status().isByUser())
01794 {
01795 if (userSourceCompare == Source_Ref::noSource
01796 && !differentUserCompareSources)
01797 userSourceCompare = sourceItem->source();
01798 else if (userSourceCompare != sourceItem->source())
01799 differentUserCompareSources = true;
01800 }
01801
01802
01803 if (compareMap.find (sourceItem->source()) == compareMap.end())
01804 compareMap[sourceItem->source()] = 1;
01805 else
01806 compareMap[sourceItem->source()] += 1;
01807 _XDEBUG ("Count of right" << sourceItem->source() << ": " << compareMap[sourceItem->source()] << " : "
01808 << *(itCompare->resolvable()));
01809 itCompare++;
01810 }
01811
01812
01813 cmpSource = 0;
01814 int cmpCompare = 0;
01815
01816 if (!differentUserSources)
01817 {
01818
01819
01820 cmpSource = thisMap[userSource];
01821 }
01822
01823 if (!differentUserCompareSources) {
01824
01825
01826 cmpCompare = compareMap[userSourceCompare];
01827 }
01828 _XDEBUG ("cmpSource = " << cmpSource << " ; cmpCompare = " << cmpCompare << " ; sizeof compareMap:" << compareMap.size());
01829 if (compareMap.size() == 1
01830 && thisMap.size() == 1
01831 && userSource == userSourceCompare) {
01832
01833
01834
01835 cmpSource = 0;
01836 } else {
01837
01838
01839
01840 cmpSource = cmpSource - cmpCompare;
01841 }
01842
01843 if (cmpSource == 0)
01844 {
01845
01846 cmpSource = compareMap.size() - thisMap.size();
01847 }
01848 _XDEBUG ("End comparing two solutions-------- Version compare: " << cmpVersion << " Source compare: "<< cmpSource);
01849 }
01850
01851 int
01852 ResolverContext::partialCompare (ResolverContext_Ptr context)
01853 {
01854 int cmp = 0;
01855 if (this != context) {
01856
01857
01858 int cmpVersion = 0;
01859 int cmpSource = 0;
01860
01861 collectCompareInfo (cmpVersion, cmpSource, context);
01862
01863
01864 cmp = cmpVersion;
01865 DBG << "Comparing versions returned :" << cmp << endl;
01866 if (cmp == 0) {
01867
01868
01869 cmp = num_cmp (_min_priority, context->_min_priority);
01870 DBG << "Comparing priority returned :" << cmp << endl;
01871 if (cmp == 0) {
01872
01873 cmp = rev_num_cmp (churn_factor (this), churn_factor (context));
01874 DBG << "Comparing churn_factor returned :" << cmp << endl;
01875 if (cmp == 0) {
01876
01877 cmp = cmpSource;
01878 DBG << "Comparing sources returned :" << cmp << endl;
01879 if (cmp == 0) {
01880
01881 cmp = rev_num_cmp (_other_penalties, context->_other_penalties);
01882 DBG << "Comparing other penalties returned :" << cmp << endl;
01883 }
01884 }
01885 }
01886 }
01887 }
01888
01889 return cmp;
01890 }
01891
01892 int
01893 ResolverContext::compare (ResolverContext_Ptr context)
01894 {
01895 int cmp;
01896
01897 if (this == context)
01898 return 0;
01899
01900 cmp = partialCompare (context);
01901 if (cmp)
01902 return cmp;
01903
01904
01905 cmp = rev_num_cmp (_download_size, context->_download_size);
01906 if (cmp)
01907 return cmp;
01908
01909
01910 cmp = rev_num_cmp (_install_size, context->_install_size);
01911 if (cmp)
01912 return cmp;
01913
01914 return 0;
01915 }
01916
01918 };
01921 };
01924 };
01926