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