QueueItemEstablish.cc

Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
00002 /* QueueItemEstablish.cc
00003  *
00004  * Copyright (C) 2000-2002 Ximian, Inc.
00005  * Copyright (C) 2005 SUSE Linux Products GmbH
00006  *
00007  * This program is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU General Public License,
00009  * version 2, as published by the Free Software Foundation.
00010  *
00011  * This program is distributed in the hope that it will be useful, but
00012  * WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
00019  * 02111-1307, USA.
00020  */
00021 
00022 #include "zypp/solver/detail/Types.h"
00023 
00024 #include "zypp/solver/detail/QueueItemEstablish.h"
00025 #include "zypp/solver/detail/QueueItemInstall.h"
00026 #include "zypp/solver/detail/QueueItemRequire.h"
00027 #include "zypp/solver/detail/QueueItemConflict.h"
00028 #include "zypp/solver/detail/QueueItemUninstall.h"
00029 #include "zypp/solver/detail/QueueItem.h"
00030 #include "zypp/solver/detail/Helper.h"
00031 #include "zypp/solver/detail/ResolverContext.h"
00032 #include "zypp/solver/detail/ResolverInfoConflictsWith.h"
00033 #include "zypp/solver/detail/ResolverInfoNeededBy.h"
00034 #include "zypp/solver/detail/ResolverInfoMisc.h"
00035 
00036 #include "zypp/CapSet.h"
00037 #include "zypp/base/Logger.h"
00038 #include "zypp/base/String.h"
00039 #include "zypp/base/Gettext.h"
00040 
00042 namespace zypp
00043 { 
00044 
00045   namespace solver
00046   { 
00047 
00048     namespace detail
00049     { 
00050 
00051 using namespace std;
00052 
00053 IMPL_PTR_TYPE(QueueItemEstablish);
00054 
00055 //---------------------------------------------------------------------------
00056 
00057 std::ostream &
00058 QueueItemEstablish::dumpOn( std::ostream & os ) const
00059 {
00060     os <<"[Establish: ";
00061     os << _item;
00062     if (_explicitly_requested) os << ", Explicit !";
00063     os << "]";
00064     return os;
00065 }
00066 
00067 //---------------------------------------------------------------------------
00068 
00069 QueueItemEstablish::QueueItemEstablish (const ResPool & pool, PoolItem_Ref item, bool soft)
00070     : QueueItem (QUEUE_ITEM_TYPE_ESTABLISH, pool)
00071     , _item(item)
00072     , _soft(soft)
00073     , _channel_priority (0)
00074     , _other_penalty (0)
00075     , _explicitly_requested (false)
00076 {
00077     _XDEBUG("QueueItemEstablish::QueueItemEstablish (" << item << ")");
00078 
00079 }
00080 
00081 
00082 QueueItemEstablish::~QueueItemEstablish()
00083 {
00084 }
00085 
00086 //---------------------------------------------------------------------------
00087 
00088 bool
00089 QueueItemEstablish::isSatisfied (ResolverContext_Ptr context) const
00090 {
00091     return context->isPresent (_item);
00092 }
00093 
00094 
00095 //---------------------------------------------------------------------------
00096 
00097 
00098 bool
00099 QueueItemEstablish::process (const QueueItemList & mainQueue, ResolverContext_Ptr context, QueueItemList & qil)
00100 {
00101     _XDEBUG("QueueItemEstablish::process(" << *this << ")");
00102 
00103     ResStatus status = context->getStatus(_item);
00104     
00105     if (_item.status().isLocked()
00106         || status.isLocked()) {
00107         _XDEBUG("Item " << _item << " is locked. --> NO establish");
00108         return true;
00109     }
00110     if ( ! _item->arch().compatibleWith( context->architecture() ) ) {
00111         context->unneeded (_item, _other_penalty);
00112         _XDEBUG( _item << " has incompatible architecture, unneeded" );
00113         return true;
00114     }
00115 
00116     _item.status().setUndetermined();           // reset any previous establish state
00117 
00118     CapSet freshens = _item->dep(Dep::FRESHENS);
00119 
00120     _XDEBUG("simple establish of " << _item << " with " << freshens.size() << " freshens");
00121 
00122     ResolverInfo_Ptr misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_ESTABLISHING, _item, RESOLVER_INFO_PRIORITY_VERBOSE);
00123     context->addInfo (misc_info);
00124     logInfo (context);
00125 
00126     /* Loop through all freshen dependencies. If one is satisfied, queue the _item for installation.  */
00127 
00128     CapSet::const_iterator iter;
00129     for (iter = freshens.begin(); iter != freshens.end(); iter++) {
00130         const Capability cap = *iter;
00131         bool dummy1, dummy2;
00132         if (context->requirementIsMet (cap, _item, Dep::FRESHENS, &dummy1, &dummy2, true)) { //true =installInfoFlag
00133             _XDEBUG("this freshens " << cap);
00134             break;
00135         }
00136     }
00137 
00138     // if we have freshens but none of the freshen deps were met, mark the _item as unneeded
00139     // else we look at its supplements as an additional condition
00140     // (freshens AND supplements must be true. true means either empty or at least one match)
00141     //
00142     // else we look at its requires to set it to satisfied or incomplete
00143 
00144     if (freshens.size() > 0                             // have freshens !
00145         && iter == freshens.end())                      // but none matched
00146     {
00147         _XDEBUG(_item << " freshens nothing -> unneeded");
00148         if (_item->kind() != ResTraits<Package>::kind)
00149             context->unneeded (_item, _other_penalty);
00150     }
00151     else {                                                      // installed or no freshens or triggered freshens
00152 
00153         CapSet supplements = _item->dep(Dep::SUPPLEMENTS);
00154         if (supplements.size() != 0) {                                  // if we have supplements, they must _also_ trigger
00155             CapSet::const_iterator iter;
00156             for (iter = supplements.begin(); iter != supplements.end(); iter++) {
00157                 const Capability cap = *iter;
00158                 bool dummy1, dummy2;                
00159                 if (context->requirementIsMet (cap, _item, Dep::SUPPLEMENTS, &dummy1, &dummy2, true)) { //true =installInfoFlag
00160                     _XDEBUG("this supplements " << cap);
00161                     break;
00162                 }
00163             }
00164             if (iter == supplements.end()) {
00165                 _XDEBUG(_item << " none of the supplements match -> unneeded");
00166                 if (_item->kind() != ResTraits<Package>::kind)
00167                     context->unneeded (_item, _other_penalty);
00168                 return true;
00169             }
00170 
00171             PoolItem_Ref installed = Helper::findInstalledItem( pool(), _item );
00172             if (!installed                                                              // not installed
00173                 && Helper::isBestUninstalledItem( pool(), _item ))                      // and no better available -> install
00174             {
00175                 // not yet installed, have supplements, and at least one triggers -> install
00176                 _DEBUG("Uninstalled " << _item << " supplements " << *iter << " -> install");
00177                 QueueItemInstall_Ptr install_item = new QueueItemInstall( pool(), _item, true );
00178                 qil.push_front( install_item );
00179                 return true;
00180             }
00181         }
00182 
00183         // the conditions (freshens, supplements) are true (either empty or at least one match)
00184         // for a package, these are sufficient to trigger its installation. (packages only get
00185         //  'established' if they have freshens or supplements).
00186         //  While this is fine for e.g. fonts etc. its problematic for kernel driver packages.
00187         //  We must not install kernel driver packages which (via their dependencies) will install
00188         //  additional kernels. So for kernel driver packages, checking their requires is indeed
00189         //  the right thing. (see #178721)
00190 
00191         // So the current code checks all requirements and only triggers an install if
00192         //  - all requirements are already fulfilled
00193         //  - the package is not already installed (so we do only fresh installs, no upgrades here)
00194 
00195         // for other kind of resolvables, we now look at their requirements and set their
00196         //  'state modifier' accordingly.
00197 
00198 
00199         CapSet requires = _item->dep(Dep::REQUIRES);                    // check requirements
00200         Capability missing;
00201         bool all_unneeded = true;                                       // check if all are met because of unneeded
00202         for (iter = requires.begin(); iter != requires.end(); iter++) {
00203             missing = *iter;
00204             bool unneeded;
00205             if (!context->requirementIsMet (missing, _item, Dep::REQUIRES, &unneeded)) {
00206                 all_unneeded = false;
00207                 break;
00208             }
00209             if (!unneeded) all_unneeded = false;
00210         }
00211         if (iter == requires.end()) {                                   // all are met
00212             if (all_unneeded
00213                 && _item->kind() == ResTraits<Patch>::kind)             // unneeded is transitive only for patches (#171590)
00214             {
00215                 _XDEBUG("all requirements of " << _item << " unneeded -> unneeded");
00216                 context->unneeded( _item, _other_penalty );
00217             }
00218             else if (_item->kind() == ResTraits<Package>::kind)         // install package if not installed yet.
00219             {
00220                 PoolItem_Ref installed = Helper::findInstalledItem( pool(), _item );
00221                 if (!installed                                                          // not installed
00222                     && Helper::isBestUninstalledItem( pool(), _item ))                  // and no better available -> install
00223                 {
00224                     // freshens and at least one triggers -> install
00225                     _DEBUG("Uninstalled " << _item << " freshens -> install");
00226                     QueueItemInstall_Ptr install_item = new QueueItemInstall( pool(), _item, true );
00227                     qil.push_front( install_item );
00228                     return true;
00229                 }
00230             }
00231             else
00232             {
00233                 _XDEBUG("all requirements of " << _item << " met -> satisfied");
00234                 context->satisfy( _item, _other_penalty );
00235             }
00236         }
00237         else {                                                          // some requirements are unfulfilled
00238             // If the item stays installed, blame the user
00239             if ((_item->kind() == ResTraits<Patch>::kind        // bug 198379, set incomplete for all patches, installed or uninstalled
00240                  || _item->kind() == ResTraits<Atom>::kind)     // Bug 190272,  - same for atoms
00241                 || status.staysInstalled())
00242             {
00243                 _XDEBUG("Atom/Patch/Installed/Establishing " << _item << " has unfulfilled requirement " << *iter << " -> incomplete");
00244                 context->incomplete( _item, _other_penalty );
00245 
00246                 // if something installed goes 'incomplete' outside of the establishing call, its always an error
00247                 if ( status.staysInstalled()
00248                      &&!context->establishing()) {
00249 
00250                     // last check if the item will be deleted.
00251                     // (check the queue, if there is a delete request)
00252                     QueueItemList::const_iterator iterQueue;
00253                     for (iterQueue = mainQueue.begin(); iterQueue != mainQueue.end(); iterQueue++) {
00254                         QueueItem_Ptr qitem = *iterQueue;
00255                         if (qitem->isUninstall()) {
00256                             QueueItemUninstall_Ptr uninstall = dynamic_pointer_cast<QueueItemUninstall>(qitem);
00257                             if (uninstall->deletedItem() == _item) {
00258                                 _DEBUG(_item << " will be uninstalled later. So, we do not have to inform the user.");
00259                                 break;
00260                             }
00261                         }
00262                     }
00263 
00264                     if (iterQueue == mainQueue.end()) {
00265                         ResolverInfo_Ptr misc_info = new ResolverInfoMisc (RESOLVER_INFO_TYPE_INCOMPLETES, _item, RESOLVER_INFO_PRIORITY_VERBOSE);
00266                         context->addError (misc_info);
00267                     }
00268                 }
00269             }
00270             else {
00271                 _XDEBUG("Transacted " << _item << " has unfulfilled requirement " << *iter << " -> leave");
00272                 // do nothing, because its either toBeInstalled or toBeUninstalled
00273             }
00274         }
00275     }
00276 
00277     return true;
00278 }
00279 
00280 
00281 QueueItem_Ptr
00282 QueueItemEstablish::copy (void) const
00283 {
00284     QueueItemEstablish_Ptr new_install = new QueueItemEstablish (pool(), _item, _soft);
00285     new_install->QueueItem::copy(this);
00286 
00287     new_install->_channel_priority = _channel_priority;
00288     new_install->_other_penalty = _other_penalty;
00289     new_install->_explicitly_requested = _explicitly_requested;
00290 
00291     return new_install;
00292 }
00293 
00294 
00295 int
00296 QueueItemEstablish::cmp (QueueItem_constPtr item) const
00297 {
00298     int cmp = this->compare (item);
00299     if (cmp != 0)
00300         return cmp;
00301     QueueItemEstablish_constPtr establish = dynamic_pointer_cast<const QueueItemEstablish>(item);
00302     return compareByNVR(_item.resolvable(), establish->_item.resolvable());
00303 }
00304 
00306     };// namespace detail
00309   };// namespace solver
00312 };// namespace zypp

Generated on Tue Sep 25 19:23:07 2007 for libzypp by  doxygen 1.5.3