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