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