{ /////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
+ //
+ // CLASS NAME : WhatProvides::Impl
+ //
+ /** WhatProvides implementation date.
+ * Stores the offset into a O terminated Id array. Per default
+ * the satsolvers whatprovidesdata, otherwise private data.
+ *
+ * As the satsolvers whatprovidesdata might be realocated
+ * while iterating a result, the iterator takes an
+ * <tt>const IdType *const*</tt>. Thats why we explicitly
+ * provide _private and pass its adress to the iterator,
+ * even if private data are not reallocated.
+ */
+ class WhatProvides::Impl : protected detail::PoolMember
+ {
+ public:
+ Impl()
+ : _offset( 0 ), _private( 0 )
+ {}
+
+ Impl( unsigned offset_r )
+ : _offset( offset_r ), _private( 0 )
+ {}
+
+ Impl( const std::tr1::unordered_set<detail::IdType> & ids_r )
+ : _offset( 0 ), _private( 0 )
+ {
+ // use private data to store the result (incl. trailing NULL)
+ _pdata.reserve( ids_r.size()+1 );
+ _pdata.insert( _pdata.begin(), ids_r.begin(), ids_r.end() );
+ _pdata.push_back( detail::noId );
+
+ _private = &_pdata.front(); // ptr to 1st element
+ }
+
+ public:
+ unsigned _offset;
+ const detail::IdType * _private;
+
+ private:
+ std::vector<sat::detail::IdType> _pdata;
+ };
+ ///////////////////////////////////////////////////////////////////
+
+ ///////////////////////////////////////////////////////////////////
namespace
{ /////////////////////////////////////////////////////////////////
/** WhatProvides ctor helper collecting providers from Capabilies. */
template <class Iterator>
- shared_ptr<void> allocatedProviders( Iterator begin_r, Iterator end_r, const sat::detail::IdType *& first_r )
+ void collectProviders( Iterator begin_r, Iterator end_r, std::tr1::unordered_set<detail::IdType> & collect_r )
{
- // use a set to unify the collected results
- std::tr1::unordered_set<sat::detail::IdType> ids;
for_( it, begin_r, end_r )
{
WhatProvides providers( *it );
for_( prv, providers.begin(), providers.end() )
{
- ids.insert( prv->id() );
+ collect_r.insert( prv->id() );
}
}
-
- if ( ids.empty() )
- {
- return shared_ptr<void>();
- }
-
- // use allocated private data to store the result (incl. trailing NULL)
- std::vector<sat::detail::IdType> * pdata = new std::vector<sat::detail::IdType>( ids.size()+1, sat::detail::noId );
- pdata->insert( pdata->begin(), ids.begin(), ids.end() );
- first_r = &pdata->front();
- return shared_ptr<void>( pdata );
}
/////////////////////////////////////////////////////////////////
- } // namespace
+ } //namespace
///////////////////////////////////////////////////////////////////
- WhatProvides::WhatProvides( Capability cap_r )
- : _begin( myPool().whatProvides( cap_r ) )
+ WhatProvides::WhatProvides()
{}
+ WhatProvides::WhatProvides( Capability cap_r )
+ {
+ unsigned res( myPool().whatProvides( cap_r ) );
+ if ( myPool().whatProvidesData( res ) )
+ {
+ _pimpl.reset( new Impl( res ) );
+ }
+ // else: no Impl for empty result.
+ }
+
WhatProvides::WhatProvides( Capabilities caps_r )
- : _begin( 0 )
- , _private( allocatedProviders( caps_r.begin(), caps_r.end(), _begin ) )
- {}
+ {
+ std::tr1::unordered_set<detail::IdType> ids;
+ collectProviders( caps_r.begin(), caps_r.end(), ids );
+ if ( ! ids.empty() )
+ {
+ _pimpl.reset( new Impl( ids ) );
+ }
+ // else: no Impl for empty result.
+ }
WhatProvides::WhatProvides( const CapabilitySet & caps_r )
- : _begin( 0 )
- , _private( allocatedProviders( caps_r.begin(), caps_r.end(), _begin ) )
- {}
+ {
+ std::tr1::unordered_set<detail::IdType> ids;
+ collectProviders( caps_r.begin(), caps_r.end(), ids );
+ if ( ! ids.empty() )
+ {
+ _pimpl.reset( new Impl( ids ) );
+ }
+ // else: no Impl for empty result.
+ }
+
+ bool WhatProvides::empty() const
+ {
+ return _pimpl; // Ctor asserts no Impl for empty result.
+ }
WhatProvides::size_type WhatProvides::size() const
{
- if ( ! _begin )
+ if ( !_pimpl )
return 0;
- Capabilities::size_type ret = 0;
- for ( const sat::detail::IdType * end = _begin; *end; ++end )
- {
- ++ret;
- }
- return ret;
+ size_type count = 0;
+ for_( it, begin(), end() )
+ ++count;
+ return count;
+ }
+
+ WhatProvides::const_iterator WhatProvides::begin() const
+ {
+ if ( !_pimpl )
+ return const_iterator();
+
+ if ( _pimpl->_private )
+ return const_iterator( _pimpl->_private );
+
+ // for satsolvers index use one more indirection, as it might get relocated.
+ return const_iterator( &myPool().getPool()->whatprovidesdata, _pimpl->_offset );
}
/******************************************************************
public:
/** Default ctor */
- WhatProvides()
- : _begin( 0 )
- {}
+ WhatProvides();
/** Ctor from \ref Capability. */
explicit
public:
/** Whether the container is empty. */
- bool empty() const
- { return ! ( _begin && *_begin ); }
+ bool empty() const;
/** Number of solvables inside. */
size_type size() const;
const_iterator end() const;
private:
- const sat::detail::IdType * _begin;
- shared_ptr<void> _private;
+ struct Impl;
+ RW_pointer<Impl> _pimpl;
};
///////////////////////////////////////////////////////////////////
// CLASS NAME : WhatProvides::const_iterator
//
/** \ref WhatProvides iterator.
- * Iterate a NULL terminated sat::detail::IdType array.
+ * Iterate a NULL terminated sat::detail::IdType array. Ctor gets
+ * the adress of a pointer to the array, and offset into the array.
+ * This is needed in case the array gets reallocated.
*/
class WhatProvidesIterator : public boost::iterator_adaptor<
WhatProvidesIterator // Derived
{
public:
WhatProvidesIterator()
- : iterator_adaptor_( 0 )
+ : iterator_adaptor_( 0 ), _baseRef( 0 ), _offset( 0 )
+ {}
+
+ /** Ctor with pointer to 1st elemment of an array.
+ * Use otherwise unused base as pointer for _baseRef. */
+ explicit WhatProvidesIterator( const detail::IdType *const base_r, unsigned offset_r = 0 )
+ : iterator_adaptor_( base_r ), _baseRef( base_r ? &base_reference() : 0 ), _offset( offset_r )
{}
- explicit WhatProvidesIterator( const sat::detail::IdType * _idx )
- : iterator_adaptor_( _idx )
+ /** Ctor with pointer to pointer to 1st elemment of an array.
+ * Required for arrays that might be relocated whlite iterating (
+ */
+ explicit WhatProvidesIterator( const detail::IdType *const* baseRef_r, unsigned offset_r )
+ : iterator_adaptor_( 0 ), _baseRef( baseRef_r ), _offset( offset_r )
{}
private:
friend class boost::iterator_core_access;
reference dereference() const
- { return ( base() ) ? Solvable( *base() ) : Solvable::noSolvable; }
-
+ { return Solvable( getId() ); }
+#if 0
template <class OtherDerived, class OtherIterator, class V, class C, class R, class D>
bool equal( const boost::iterator_adaptor<OtherDerived, OtherIterator, V, C, R, D> & rhs ) const
- { // NULL pointer is eqal pointer to Id 0
- return ( base() == rhs.base() // includes both NULL...
- || ( !rhs.base() && !*base() )
- || ( !base() && !*rhs.base() ) );
+#endif
+ bool equal( const WhatProvidesIterator & rhs ) const
+ { // NULL pointer is eqal Id 0
+ return ( ! ( getId() || rhs.getId() ) // both @end
+ || ( _baseRef == rhs._baseRef && _offset == rhs._offset ) );
}
void increment()
- { ++base_reference(); }
+ { ++_offset; }
+
+ detail::IdType getId() const
+ { return _baseRef ? (*_baseRef)[_offset] : detail::noId; }
+
+ private:
+ const detail::IdType *const*const _baseRef;
+ unsigned _offset;
};
///////////////////////////////////////////////////////////////////
}
- inline WhatProvides::const_iterator WhatProvides::begin() const
- { return const_iterator( _begin ); }
-
inline WhatProvides::const_iterator WhatProvides::end() const
- { return const_iterator( 0 ); }
+ { return const_iterator(); }
/////////////////////////////////////////////////////////////////
} // namespace sat
#include "satsolver/poolvendor.h"
#include "satsolver/policy.h"
#include "satsolver/bitmap.h"
-#include "satsolver/queue.h"
+#include "satsolver/queue.h"
}
/////////////////////////////////////////////////////////////////////////
}
return os.str();
}
-
+
//---------------------------------------------------------------------------
std::ostream &
SATResolver::dumpOn( std::ostream & os ) const
{
- os << "<resolver>" << endl;
+ os << "<resolver>" << endl;
if (_solv) {
os << " fixsystem = " << _solv->fixsystem << endl;
os << " allowdowngrade = " << _solv->allowdowngrade << endl;
break;
}
}
- }
+ }
}
void
SATResolver::addPoolItemToRemove (PoolItem item)
{
- resetItemTransaction (item);
+ resetItemTransaction (item);
_items_to_remove.push_back (item);
_items_to_remove.unique ();
}
void
SATResolver::addPoolItemToLock (PoolItem item)
{
- resetItemTransaction (item);
+ resetItemTransaction (item);
_items_to_lock.push_back (item);
_items_to_lock.unique ();
}
void
SATResolver::addPoolItemToKeep (PoolItem item)
{
- resetItemTransaction (item);
+ resetItemTransaction (item);
_items_to_keep.push_back (item);
_items_to_keep.unique ();
}
static void
SATSolutionToPool (PoolItem item, const ResStatus & status, const ResStatus::TransactByValue causer)
{
- // resetting
+ // resetting
item.status().resetTransact (causer);
item.status().resetWeak ();
r = item.status().setToBeUninstalled (causer);
_XDEBUG("SATSolutionToPool(" << item << ", " << status << ") remove !" << r);
}
-
+
return;
}
//----------------------------------------------------------------------------
-// helper functions for distupgrade
+// helper functions for distupgrade
//----------------------------------------------------------------------------
bool SATResolver::doesObsoleteItem (PoolItem candidate, PoolItem installed) {
Solvable *sCandidate = _SATPool->solvables + candidate.satSolvable().id();
::_Repo *installedRepo = sat::Pool::instance().systemRepo().get();
-
- Id p, *pp, obsolete, *obsoleteIt;
-
+
+ Id p, pp, obsolete, *obsoleteIt;
+
if ((!installedRepo || sCandidate->repo != installedRepo) && sCandidate->obsoletes) {
obsoleteIt = sCandidate->repo->idarraydata + sCandidate->obsoletes;
while ((obsolete = *obsoleteIt++) != 0)
{
- for (pp = pool_whatprovides(_SATPool, obsolete) ; (p = *pp++) != 0; ) {
+ for (pp = pool_whatprovides(_SATPool, obsolete); (p = _SATPool->whatprovidesdata[pp++]) != 0; ) {
if (p > 0 && installed.satSolvable().id() == (sat::detail::SolvableIdType)p) {
MIL << candidate << " obsoletes " << installed << endl;
return true;
CollectNonePackages( Queue *queue )
:solvableQueue (queue)
{}
-
+
// collecting none packges
bool operator()( PoolItem item )
_solv->dosplitprovides = _dosplitprovides;
_solv->noupdateprovide = _noupdateprovide;
_solv->dontinstallrecommended = _onlyRequires;
- _solv->distupgrade = _distupgrade;
+ _solv->distupgrade = _distupgrade;
_solv->distupgrade_removeunsupported = _distupgrade_removeunsupported;
-
+
sat::Pool::instance().prepare();
// Solve !
} else {
SATSolutionToPool (poolItem, ResStatus::toBeUninstalled, ResStatus::SOLVER);
}
- _result_items_to_remove.push_back (poolItem);
+ _result_items_to_remove.push_back (poolItem);
} else {
ERR << "id " << i << " not found in ZYPP pool." << endl;
}
PoolItem poolItem = _pool.find (sat::Solvable(p));
if (poolItem) {
poolItem.status().setRecommended(true);
- _XDEBUG("SATSolutionToPool(" << poolItem << ") recommended !");
+ _XDEBUG("SATSolutionToPool(" << poolItem << ") recommended !");
} else {
ERR << "id " << p << " not found in ZYPP pool." << endl;
}
Map installedmap;
Queue flags, solvableQueue;
- queue_init(&flags);
+ queue_init(&flags);
queue_init(&solvableQueue);
CollectNonePackages collectNonePackages(&solvableQueue);
pool_trivial_installable(_solv->pool, _solv->installed, &installedmap, &solvableQueue, &flags);
for (int i = 0; i < solvableQueue.count; i++) {
PoolItem item = _pool.find (sat::Solvable(solvableQueue.elements[i]));
- item.status().setUndetermined();
-
+ item.status().setUndetermined();
+
if (flags.elements[i] == -1) {
item.status().setNonRelevant();
_XDEBUG("SATSolutionToPool(" << item << " ) nonRelevant !");
_XDEBUG("SATSolutionToPool(" << item << " ) satisfied !");
} else if (flags.elements[i] == 0) {
item.status().setBroken();
- _XDEBUG("SATSolutionToPool(" << item << " ) broken !");
+ _XDEBUG("SATSolutionToPool(" << item << " ) broken !");
}
}
ERR << "Solverrun finished with an ERROR" << endl;
return false;
}
-
+
map_free(&installedmap);
queue_free(&(solvableQueue));
- queue_free(&flags);
+ queue_free(&flags);
return true;
}
SATResolver::solverInit(const PoolItemList & weakItems)
{
SATCollectTransact info (*this);
-
+
MIL << "SATResolver::solverInit()" << endl;
if (_solv) {
invokeOnEach ( _pool.begin(), _pool.end(),
functor::functorRef<bool,PoolItem>(info) );
-
+
for (PoolItemList::const_iterator iter = weakItems.begin(); iter != weakItems.end(); iter++) {
Id id = (*iter)->satSolvable().id();
if (id == ID_NULL) {
}
MIL << "Weaken dependencies of " << *iter << endl;
queue_push( &(_jobQueue), SOLVER_WEAKEN_SOLVABLE_DEPS );
- queue_push( &(_jobQueue), id );
+ queue_push( &(_jobQueue), id );
}
// Add rules for parallel installable resolvables with different versions
// cleanup
solver_free(_solv);
_solv = NULL;
- queue_free( &(_jobQueue) );
+ queue_free( &(_jobQueue) );
}
const PoolItemList & weakItems)
{
MIL << "SATResolver::resolvePool()" << endl;
-
+
// initialize
solverInit(weakItems);
-
+
for (PoolItemList::const_iterator iter = _items_to_install.begin(); iter != _items_to_install.end(); iter++) {
Id id = (*iter)->satSolvable().id();
if (id == ID_NULL) {
// cleanup
if (ret)
solverEnd(); // remove solver only if no errors happend. Need it for solving problems
-
+
MIL << "SATResolver::resolvePool() done. Ret:" << ret << endl;
return ret;
}
const PoolItemList & weakItems)
{
MIL << "SATResolver::resolvQueue()" << endl;
-
+
// initialize
solverInit(weakItems);
for (SolverQueueItemList::const_iterator iter = requestQueue.begin(); iter != requestQueue.end(); iter++) {
(*iter)->addRule(_jobQueue);
}
-
+
// Add addition item status to the resolve-queue cause these can be set by problem resolutions
for (PoolItemList::const_iterator iter = _items_to_install.begin(); iter != _items_to_install.end(); iter++) {
Id id = (*iter)->satSolvable().id();
// set requirements for a running system
setSystemRequirements();
-
+
// set locks for the solver
setLocks();
// cleanup
if (ret)
solverEnd(); // remove solver only if no errors happend. Need it for solving problems
-
+
MIL << "SATResolver::resolveQueue() done. Ret:" << ret << endl;
return ret;
}
// set requirements for a running system
setSystemRequirements();
-
+
// set locks for the solver
void setLocks();
_solv->updatesystem = true;
_solv->dontinstallrecommended = true; // #FIXME dontinstallrecommended maybe set to false if it works correctly
-
+
sat::Pool::instance().prepare();
// Solve !
MIL << "Starting solving for update...." << endl;
- MIL << *this;
+ MIL << *this;
solver_solve( _solv, &(_jobQueue) );
MIL << "....Solver end" << endl;
, action (act)
{
}
-
+
bool operator()( PoolItem p)
{
problemSolution->addSingleAction (p, action);
sat::Solvable SATResolver::mapSolvable (const Id &id)
{
PoolItem item = _pool.find (sat::Solvable(id));
- return mapItem(item).satSolvable();
+ return mapItem(item).satSolvable();
}
string SATResolver::SATprobleminfoString(Id problem, string &detail, Id &ignoreId)
break;
case SOLVER_PROBLEM_JOB_NOTHING_PROVIDES_DEP:
ret = str::form (_("nothing provides requested %s"), dep2str(pool, dep));
- detail += _("Have you enabled all requested repositories?");
+ detail += _("Have you enabled all requested repositories?");
break;
case SOLVER_PROBLEM_NOT_INSTALLABLE:
s = mapSolvable (source);
case SOLVER_PROBLEM_SELF_CONFLICT:
s = mapSolvable (source);
ret = str::form (_("Solvable %s conflicts with %s provided by itself"), solvable2str(pool, s.get()), dep2str(pool, dep));
- break;
+ break;
case SOLVER_PROBLEM_DEP_PROVIDERS_NOT_INSTALLABLE:
ignoreId = source; // for setting weak dependencies
s = mapSolvable (source);
// find pair of an installed/uninstalled item with the same NVR
bool found = false;
for_( iter2, possibleProviders.begin(), possibleProviders.end() ) {
- PoolItem provider2 = ResPool::instance().find( *iter2 );
+ PoolItem provider2 = ResPool::instance().find( *iter2 );
if (compareByNVR (provider1.resolvable(),provider2.resolvable()) == 0
&& ( (provider1.status().isInstalled() && provider2.status().isUninstalled())
|| (provider2.status().isInstalled() && provider1.status().isUninstalled()) )) {
if (detail.size() > 0)
detail += _("\nuninstallable providers: ");
else
- detail = _("uninstallable providers: ");
+ detail = _("uninstallable providers: ");
for (ProviderList::const_iterator iter = providerlistUninstalled.begin(); iter != providerlistUninstalled.end(); iter++) {
if (iter == providerlistUninstalled.begin())
- detail += itemToString (*iter, false);
+ detail += itemToString (*iter, false);
else
- detail += "\n " + itemToString (mapItem(*iter), false);
+ detail += "\n " + itemToString (mapItem(*iter), false);
}
- }
+ }
break;
}
IdString ident( what );
SolverQueueItemInstall_Ptr install =
new SolverQueueItemInstall(_pool, ident.asString(), false );
- problemSolution->addSingleAction (install, REMOVE_SOLVE_QUEUE_ITEM);
-
+ problemSolution->addSingleAction (install, REMOVE_SOLVE_QUEUE_ITEM);
+
string description = str::form (_("do not install %s"), ident.c_str() );
MIL << description << endl;
problemSolution->addDescription (description);
case SOLVER_ERASE_SOLVABLE_NAME:
{
// As we do not know, if this request has come from resolvePool or
- // resolveQueue we will have to take care for both cases.
+ // resolveQueue we will have to take care for both cases.
IdString ident( what );
FindPackage info (problemSolution, KEEP);
invokeOnEach( _pool.byIdentBegin( ident ),
functor::chain (resfilter::ByInstalled (), // ByInstalled
resfilter::ByTransact ()), // will be deinstalled
functor::functorRef<bool,PoolItem> (info) );
-
+
SolverQueueItemDelete_Ptr del =
new SolverQueueItemDelete(_pool, ident.asString(), false );
- problemSolution->addSingleAction (del, REMOVE_SOLVE_QUEUE_ITEM);
-
+ problemSolution->addSingleAction (del, REMOVE_SOLVE_QUEUE_ITEM);
+
string description = str::form (_("keep %s"), ident.c_str());
MIL << description << endl;
problemSolution->addDescription (description);
description = str::form (_("do not ask to install a solvable providing %s"), dep2str(pool, what));
}
MIL << description << endl;
- problemSolution->addDescription (description);
+ problemSolution->addDescription (description);
}
break;
case SOLVER_ERASE_SOLVABLE_PROVIDES:
description = str::form (_("do not ask to delete all solvables providing %s"), dep2str(pool, what));
}
MIL << description << endl;
- problemSolution->addDescription (description);
+ problemSolution->addDescription (description);
}
break;
case SOLVER_INSTALL_SOLVABLE_UPDATE:
if (ignoreId > 0) {
// There is a possibility to ignore this error by setting weak dependencies
- PoolItem item = _pool.find (sat::Solvable(ignoreId));
- ProblemSolutionIgnore *problemSolution = new ProblemSolutionIgnore(resolverProblem, item);
+ PoolItem item = _pool.find (sat::Solvable(ignoreId));
+ ProblemSolutionIgnore *problemSolution = new ProblemSolutionIgnore(resolverProblem, item);
resolverProblem->addSolution (problemSolution,
false); // Solutions will be shown at the end
MIL << "Ignore some dependencies of " << item << endl;
- MIL << "------------------------------------" << endl;
- }
-
+ MIL << "------------------------------------" << endl;
+ }
+
// save problem
resolverProblems.push_back (resolverProblem);
}
queue_push( &(_jobQueue), SOLVER_ERASE_SOLVABLE | SOLVER_WEAK);
queue_push( &(_jobQueue), ident );
}
- }
+ }
}
void SATResolver::setSystemRequirements()
{
CapabilitySet system_requires = SystemCheck::instance().requiredSystemCap();
CapabilitySet system_conflicts = SystemCheck::instance().conflictSystemCap();
-
+
for (CapabilitySet::const_iterator iter = system_requires.begin(); iter != system_requires.end(); iter++) {
queue_push( &(_jobQueue), SOLVER_INSTALL_SOLVABLE_PROVIDES );
queue_push( &(_jobQueue), iter->id() );
MIL << "SYSTEM Conflicts " << *iter << endl;
}
}
-
+
///////////////////////////////////////////////////////////////////
};// namespace detail