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