1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/sat/detail/PoolImpl.cc
13 #include <boost/mpl/int.hpp>
15 #include "zypp/base/Easy.h"
16 #include "zypp/base/LogTools.h"
17 #include "zypp/base/Gettext.h"
18 #include "zypp/base/Exception.h"
19 #include "zypp/base/Measure.h"
21 #include "zypp/ZConfig.h"
23 #include "zypp/sat/detail/PoolImpl.h"
24 #include "zypp/sat/Pool.h"
25 #include "zypp/Capability.h"
26 #include "zypp/Locale.h"
30 #undef ZYPP_BASE_LOGGER_LOGGROUP
31 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::satpool"
33 // ///////////////////////////////////////////////////////////////////
35 { /////////////////////////////////////////////////////////////////
36 ///////////////////////////////////////////////////////////////////
38 { /////////////////////////////////////////////////////////////////
39 ///////////////////////////////////////////////////////////////////
41 { /////////////////////////////////////////////////////////////////
43 // MPL checks for satlib constants we redefine to avoid
44 // includes and defines.
45 BOOST_MPL_ASSERT_RELATION( noId, ==, STRID_NULL );
46 BOOST_MPL_ASSERT_RELATION( emptyId, ==, STRID_EMPTY );
48 BOOST_MPL_ASSERT_RELATION( solvablePrereqMarker, ==, SOLVABLE_PREREQMARKER );
49 BOOST_MPL_ASSERT_RELATION( solvableFileMarker, ==, SOLVABLE_FILEMARKER );
51 BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_AND, ==, REL_AND );
52 BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_OR, ==, REL_OR );
53 BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_WITH, ==, REL_WITH );
54 BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_NAMESPACE, ==, REL_NAMESPACE );
56 /////////////////////////////////////////////////////////////////
58 static void logSat( struct _Pool *, void *data, int type, const char *logString )
60 if ((type & (SAT_FATAL|SAT_ERROR))) {
61 _ERR("satsolver") << logString;
63 _MIL("satsolver") << logString;
67 detail::IdType PoolImpl::nsCallback( struct _Pool *, void *data, detail::IdType lhs, detail::IdType rhs )
69 if ( lhs == NAMESPACE_LANGUAGE )
71 const std::tr1::unordered_set<IdString> & locale2Solver( reinterpret_cast<PoolImpl*>(data)->_locale2Solver );
72 return locale2Solver.find( IdString(rhs) ) == locale2Solver.end() ? -1 : 0;
74 DBG << Capability( lhs ) << " vs. " << Capability( rhs ) << endl;
78 ///////////////////////////////////////////////////////////////////
80 // METHOD NAME : PoolMember::myPool
81 // METHOD TYPE : PoolImpl
83 PoolImpl & PoolMember::myPool()
85 static PoolImpl _global;
89 ///////////////////////////////////////////////////////////////////
91 // METHOD NAME : PoolImpl::PoolImpl
95 : _pool( ::pool_create() )
97 MIL << "Creating sat-pool." << endl;
100 ZYPP_THROW( Exception( _("Can not create sat-pool.") ) );
102 // initialialize logging
103 bool verbose = ( getenv("ZYPP_FULLLOG") || getenv("ZYPP_LIBSAT_FULLLOG") );
104 ::pool_setdebuglevel( _pool, verbose ? 5 : 1 );
105 ::pool_setdebugcallback( _pool, logSat, NULL );
107 // set namespace callback
108 _pool->nscallback = &nsCallback;
109 _pool->nscallbackdata = (void*)this;
112 ///////////////////////////////////////////////////////////////////
114 // METHOD NAME : PoolImpl::~PoolImpl
115 // METHOD TYPE : Dtor
117 PoolImpl::~PoolImpl()
119 ::pool_free( _pool );
122 ///////////////////////////////////////////////////////////////////
124 void PoolImpl::setDirty( const char * a1, const char * a2, const char * a3 )
128 if ( a3 ) DBG << a1 << " " << a2 << " " << a3 << endl;
129 else if ( a2 ) DBG << a1 << " " << a2 << endl;
130 else DBG << a1 << endl;
132 _serial.setDirty(); // pool content change
133 _availableLocalesPtr.reset(); // available locales may change
135 // invaldate dependency/namespace related indices:
139 void PoolImpl::depSetDirty( const char * a1, const char * a2, const char * a3 )
143 if ( a3 ) DBG << a1 << " " << a2 << " " << a3 << endl;
144 else if ( a2 ) DBG << a1 << " " << a2 << endl;
145 else DBG << a1 << endl;
147 ::pool_freewhatprovides( _pool );
150 void PoolImpl::prepare() const
152 if ( _watcher.remember( _serial ) )
154 // After repo/solvable add/remove:
155 // set pool architecture
156 ::pool_setarch( _pool, ZConfig::instance().systemArchitecture().asString().c_str() );
158 if ( ! _pool->whatprovides )
160 DBG << "pool_createwhatprovides..." << endl;
161 ::pool_addfileprovides( _pool, sat::Pool::instance().systemRepo().get() );
162 ::pool_createwhatprovides( _pool );
166 ///////////////////////////////////////////////////////////////////
168 int PoolImpl::_addSolv( ::_Repo * repo_r, FILE * file_r, bool isSystemRepo_r )
170 setDirty(__FUNCTION__, repo_r->name );
171 int ret = ::repo_add_solv( repo_r , file_r );
172 if ( ret == 0 && ! isSystemRepo_r )
174 // Filter out unwanted archs
175 std::set<detail::IdType> sysids;
177 Arch::CompatSet sysarchs( Arch::compatSet( ZConfig::instance().systemArchitecture() ) );
178 for_( it, sysarchs.begin(), sysarchs.end() )
179 sysids.insert( it->idStr().id() );
181 // unfortunately satsolver treats src/nosrc as architecture:
182 sysids.insert( ARCH_SRC );
183 sysids.insert( ARCH_NOSRC );
186 detail::IdType blockBegin = 0;
187 unsigned blockSize = 0;
188 for ( detail::IdType i = repo_r->start; i < repo_r->end; ++i )
190 ::_Solvable * s( _pool->solvables + i );
191 if ( s->repo == repo_r && sysids.find( s->arch ) == sysids.end() )
193 // Remember an unwanted arch entry:
198 else if ( blockSize )
200 // Free remembered entries
201 ::repo_free_solvable_block( repo_r, blockBegin, blockSize, /*reuseids*/false );
202 blockBegin = blockSize = 0;
207 // Free remembered entries
208 ::repo_free_solvable_block( repo_r, blockBegin, blockSize, /*reuseids*/false );
209 blockBegin = blockSize = 0;
215 ///////////////////////////////////////////////////////////////////
217 // need on demand and id based Locale
218 void _locale_hack( const LocaleSet & locales_r,
219 std::tr1::unordered_set<IdString> & locale2Solver )
221 std::tr1::unordered_set<IdString>( 2*locales_r.size() ).swap( locale2Solver ) ;
222 for_( it, locales_r.begin(),locales_r.end() )
224 for ( Locale l( *it ); l != Locale::noCode; l = l.fallback() )
225 locale2Solver.insert( IdString( l.code() ) );
227 DBG << "New Solver Locales: " << locale2Solver << endl;
230 void PoolImpl::setRequestedLocales( const LocaleSet & locales_r )
232 depSetDirty( "setRequestedLocales" );
233 _requestedLocales = locales_r;
234 DBG << "New RequestedLocales: " << locales_r << endl;
235 _locale_hack( _requestedLocales, _locale2Solver );
238 bool PoolImpl::addRequestedLocale( const Locale & locale_r )
240 if ( _requestedLocales.insert( locale_r ).second )
242 depSetDirty( "addRequestedLocale", locale_r.code().c_str() );
243 _locale_hack( _requestedLocales, _locale2Solver );
249 bool PoolImpl::eraseRequestedLocale( const Locale & locale_r )
251 if ( _requestedLocales.erase( locale_r ) )
253 depSetDirty( "addRequestedLocale", locale_r.code().c_str() );
254 _locale_hack( _requestedLocales, _locale2Solver );
260 static void _getLocaleDeps( Capability cap_r, std::tr1::unordered_set<sat::detail::IdType> & store_r )
262 // Collect locales from any 'namespace:language(lang)' dependency
263 CapDetail detail( cap_r );
264 if ( detail.kind() == CapDetail::EXPRESSION )
266 switch ( detail.capRel() )
268 case CapDetail::CAP_AND:
269 case CapDetail::CAP_OR:
271 _getLocaleDeps( detail.lhs(), store_r );
272 _getLocaleDeps( detail.rhs(), store_r );
275 case CapDetail::CAP_NAMESPACE:
276 if ( detail.lhs().id() == NAMESPACE_LANGUAGE )
278 store_r.insert( detail.rhs().id() );
282 case CapDetail::REL_NONE:
283 case CapDetail::CAP_WITH:
289 const LocaleSet & PoolImpl::getAvailableLocales() const
291 if ( !_availableLocalesPtr )
293 // Collect any 'namespace:language(ja)' dependencies
294 std::tr1::unordered_set<sat::detail::IdType> tmp;
295 Pool pool( Pool::instance() );
296 for_( it, pool.solvablesBegin(), pool.solvablesEnd() )
298 Capabilities cap( it->supplements() );
299 for_( cit, cap.begin(), cap.end() )
301 _getLocaleDeps( *cit, tmp );
304 #warning immediately build LocaleSet as soon as Loale is an Id based type
305 _availableLocalesPtr.reset( new LocaleSet(tmp.size()) );
306 for_( it, tmp.begin(), tmp.end() )
308 _availableLocalesPtr->insert( Locale( IdString(*it) ) );
311 return *_availableLocalesPtr;
314 /////////////////////////////////////////////////////////////////
315 } // namespace detail
316 ///////////////////////////////////////////////////////////////////
317 /////////////////////////////////////////////////////////////////
319 ///////////////////////////////////////////////////////////////////
320 /////////////////////////////////////////////////////////////////
322 ///////////////////////////////////////////////////////////////////