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