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