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"
20 #include "zypp/base/WatchFile.h"
21 #include "zypp/base/Sysconfig.h"
23 #include "zypp/ZConfig.h"
25 #include "zypp/sat/detail/PoolImpl.h"
26 #include "zypp/sat/Pool.h"
27 #include "zypp/Capability.h"
28 #include "zypp/Locale.h"
29 #include "zypp/PoolItem.h"
31 #include "zypp/target/modalias/Modalias.h"
35 #undef ZYPP_BASE_LOGGER_LOGGROUP
36 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::satpool"
38 // ///////////////////////////////////////////////////////////////////
40 { /////////////////////////////////////////////////////////////////
41 ///////////////////////////////////////////////////////////////////
43 { /////////////////////////////////////////////////////////////////
45 ///////////////////////////////////////////////////////////////////
47 { /////////////////////////////////////////////////////////////////
49 // MPL checks for satlib constants we redefine to avoid
50 // includes and defines.
51 BOOST_MPL_ASSERT_RELATION( noId, ==, STRID_NULL );
52 BOOST_MPL_ASSERT_RELATION( emptyId, ==, STRID_EMPTY );
54 BOOST_MPL_ASSERT_RELATION( noSolvableId, ==, ID_NULL );
55 BOOST_MPL_ASSERT_RELATION( systemSolvableId, ==, SYSTEMSOLVABLE );
57 BOOST_MPL_ASSERT_RELATION( solvablePrereqMarker, ==, SOLVABLE_PREREQMARKER );
58 BOOST_MPL_ASSERT_RELATION( solvableFileMarker, ==, SOLVABLE_FILEMARKER );
60 BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_AND, ==, REL_AND );
61 BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_OR, ==, REL_OR );
62 BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_WITH, ==, REL_WITH );
63 BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_NAMESPACE, ==, REL_NAMESPACE );
64 BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_ARCH, ==, REL_ARCH );
66 /////////////////////////////////////////////////////////////////
68 const std::string & PoolImpl::systemRepoAlias()
70 static const std::string _val( "@System" );
74 /////////////////////////////////////////////////////////////////
76 static void logSat( struct _Pool *, void *data, int type, const char *logString )
78 if ( type & (SAT_FATAL|SAT_ERROR) ) {
79 _ERR("satsolver") << logString;
80 } else if ( type & SAT_DEBUG_STATS ) {
81 _DBG("satsolver") << logString;
83 _MIL("satsolver") << logString;
87 detail::IdType PoolImpl::nsCallback( struct _Pool *, void * data, detail::IdType lhs, detail::IdType rhs )
89 // lhs: the namespace identifier, e.g. NAMESPACE:MODALIAS
90 // rhs: the value, e.g. pci:v0000104Cd0000840[01]sv*sd*bc*sc*i*
91 // return: 0 if not supportded
92 // 1 if supported by the system
93 // -1 AFAIK it's also possible to return a list of solvables that support it, but don't know how.
95 static const detail::IdType RET_unsupported = 0;
96 static const detail::IdType RET_systemProperty = 1;
99 case NAMESPACE_LANGUAGE:
101 static IdString en( "en" );
102 const std::tr1::unordered_set<IdString> & locale2Solver( reinterpret_cast<PoolImpl*>(data)->_locale2Solver );
103 if ( locale2Solver.empty() )
105 return rhs == en.id() ? RET_systemProperty : RET_unsupported;
107 return locale2Solver.find( IdString(rhs) ) != locale2Solver.end() ? RET_systemProperty : RET_unsupported;
111 case NAMESPACE_MODALIAS:
113 // modalias strings in capability may be hexencoded because rpm does not allow
114 // ',', ' ' or other special chars.
115 return target::Modalias::instance().query( str::hexdecode( IdString(rhs).c_str() ) )
121 case NAMESPACE_FILESYSTEM:
123 static const Pathname sysconfigStoragePath( "/etc/sysconfig/storage" );
124 static WatchFile sysconfigFile( sysconfigStoragePath, WatchFile::NO_INIT );
125 static std::set<std::string> requiredFilesystems;
126 if ( sysconfigFile.hasChanged() )
128 requiredFilesystems.clear();
129 str::split( base::sysconfig::read( sysconfigStoragePath )["USED_FS_LIST"],
130 std::inserter( requiredFilesystems, requiredFilesystems.end() ) );
132 return requiredFilesystems.find( IdString(rhs).asString() ) != requiredFilesystems.end() ? RET_systemProperty : RET_unsupported;
136 case NAMESPACE_PRODUCTBUDDY:
138 PoolItem pi( (Solvable(rhs)) );
139 return( pi ? pi.buddy().id() : noId );
145 WAR << "Unhandled " << Capability( lhs ) << " vs. " << Capability( rhs ) << endl;
146 return RET_unsupported;
149 ///////////////////////////////////////////////////////////////////
151 // METHOD NAME : PoolMember::myPool
152 // METHOD TYPE : PoolImpl
154 PoolImpl & PoolMember::myPool()
156 static PoolImpl _global;
160 ///////////////////////////////////////////////////////////////////
162 // METHOD NAME : PoolImpl::PoolImpl
163 // METHOD TYPE : Ctor
166 : _pool( ::pool_create() )
168 MIL << "Creating sat-pool." << endl;
171 ZYPP_THROW( Exception( _("Can not create sat-pool.") ) );
173 // initialialize logging
174 bool verbose = ( getenv("ZYPP_FULLLOG") || getenv("ZYPP_LIBSAT_FULLLOG") );
176 ::pool_setdebuglevel( _pool, 2 );
178 ::pool_setdebugmask(_pool, SAT_DEBUG_JOB);
180 ::pool_setdebugcallback( _pool, logSat, NULL );
182 // set namespace callback
183 _pool->nscallback = &nsCallback;
184 _pool->nscallbackdata = (void*)this;
187 ///////////////////////////////////////////////////////////////////
189 // METHOD NAME : PoolImpl::~PoolImpl
190 // METHOD TYPE : Dtor
192 PoolImpl::~PoolImpl()
194 ::pool_free( _pool );
197 ///////////////////////////////////////////////////////////////////
199 void PoolImpl::setDirty( const char * a1, const char * a2, const char * a3 )
203 if ( a3 ) MIL << a1 << " " << a2 << " " << a3 << endl;
204 else if ( a2 ) MIL << a1 << " " << a2 << endl;
205 else MIL << a1 << endl;
207 _serial.setDirty(); // pool content change
208 _availableLocalesPtr.reset(); // available locales may change
210 // invaldate dependency/namespace related indices:
214 void PoolImpl::depSetDirty( const char * a1, const char * a2, const char * a3 )
218 if ( a3 ) MIL << a1 << " " << a2 << " " << a3 << endl;
219 else if ( a2 ) MIL << a1 << " " << a2 << endl;
220 else MIL << a1 << endl;
222 ::pool_freewhatprovides( _pool );
225 void PoolImpl::prepare() const
227 if ( _watcher.remember( _serial ) )
229 // After repo/solvable add/remove:
230 // set pool architecture
231 ::pool_setarch( _pool, ZConfig::instance().systemArchitecture().asString().c_str() );
233 if ( ! _pool->whatprovides )
235 MIL << "pool_createwhatprovides..." << endl;
236 ::pool_addfileprovides( _pool );
237 ::pool_createwhatprovides( _pool );
239 if ( ! _pool->languages )
241 std::vector<std::string> fallbacklist;
242 for ( Locale l( ZConfig::instance().textLocale() ); l != Locale::noCode; l = l.fallback() )
244 fallbacklist.push_back( l.code() );
246 dumpRangeLine( MIL << "pool_set_languages: ", fallbacklist.begin(), fallbacklist.end() ) << endl;
248 std::vector<const char *> fallbacklist_cstr;
249 for_( it, fallbacklist.begin(), fallbacklist.end() )
251 fallbacklist_cstr.push_back( it->c_str() );
253 ::pool_set_languages( _pool, &fallbacklist_cstr.front(), fallbacklist_cstr.size() );
257 ///////////////////////////////////////////////////////////////////
259 ::_Repo * PoolImpl::_createRepo( const std::string & name_r )
261 setDirty(__FUNCTION__, name_r.c_str() );
262 ::_Repo * ret = ::repo_create( _pool, name_r.c_str() );
263 if ( ret && name_r == systemRepoAlias() )
264 ::pool_set_installed( _pool, ret );
268 void PoolImpl::_deleteRepo( ::_Repo * repo_r )
270 setDirty(__FUNCTION__, repo_r->name );
271 ::repo_free( repo_r, /*reuseids*/false );
272 eraseRepoInfo( repo_r );
275 int PoolImpl::_addSolv( ::_Repo * repo_r, FILE * file_r )
277 setDirty(__FUNCTION__, repo_r->name );
278 int ret = ::repo_add_solv( repo_r , file_r );
280 _postRepoAdd( repo_r );
284 int PoolImpl::_addHelix( ::_Repo * repo_r, FILE * file_r )
286 setDirty(__FUNCTION__, repo_r->name );
287 ::repo_add_helix( repo_r , file_r, 0 ); // unfortunately void
288 _postRepoAdd( repo_r );
292 void PoolImpl::_postRepoAdd( ::_Repo * repo_r )
294 if ( ! isSystemRepo( repo_r ) )
296 // Filter out unwanted archs
297 std::set<detail::IdType> sysids;
299 Arch::CompatSet sysarchs( Arch::compatSet( ZConfig::instance().systemArchitecture() ) );
300 for_( it, sysarchs.begin(), sysarchs.end() )
301 sysids.insert( it->id() );
303 // unfortunately satsolver treats src/nosrc as architecture:
304 sysids.insert( ARCH_SRC );
305 sysids.insert( ARCH_NOSRC );
308 detail::IdType blockBegin = 0;
309 unsigned blockSize = 0;
310 for ( detail::IdType i = repo_r->start; i < repo_r->end; ++i )
312 ::_Solvable * s( _pool->solvables + i );
313 if ( s->repo == repo_r && sysids.find( s->arch ) == sysids.end() )
315 // Remember an unwanted arch entry:
320 else if ( blockSize )
322 // Free remembered entries
323 ::repo_free_solvable_block( repo_r, blockBegin, blockSize, /*reuseids*/false );
324 blockBegin = blockSize = 0;
329 // Free remembered entries
330 ::repo_free_solvable_block( repo_r, blockBegin, blockSize, /*reuseids*/false );
331 blockBegin = blockSize = 0;
336 detail::SolvableIdType PoolImpl::_addSolvables( ::_Repo * repo_r, unsigned count_r )
338 setDirty(__FUNCTION__, repo_r->name );
339 return ::repo_add_solvable_block( repo_r, count_r );
342 ///////////////////////////////////////////////////////////////////
344 // need on demand and id based Locale
345 void _locale_hack( const LocaleSet & locales_r,
346 std::tr1::unordered_set<IdString> & locale2Solver )
348 std::tr1::unordered_set<IdString>( 2*locales_r.size() ).swap( locale2Solver );
349 for_( it, locales_r.begin(),locales_r.end() )
351 for ( Locale l( *it ); l != Locale::noCode; l = l.fallback() )
352 locale2Solver.insert( IdString( l.code() ) );
354 MIL << "New Solver Locales: " << locale2Solver << endl;
357 void PoolImpl::setRequestedLocales( const LocaleSet & locales_r )
359 depSetDirty( "setRequestedLocales" );
360 _requestedLocales = locales_r;
361 MIL << "New RequestedLocales: " << locales_r << endl;
362 _locale_hack( _requestedLocales, _locale2Solver );
365 bool PoolImpl::addRequestedLocale( const Locale & locale_r )
367 if ( _requestedLocales.insert( locale_r ).second )
369 depSetDirty( "addRequestedLocale", locale_r.code().c_str() );
370 _locale_hack( _requestedLocales, _locale2Solver );
376 bool PoolImpl::eraseRequestedLocale( const Locale & locale_r )
378 if ( _requestedLocales.erase( locale_r ) )
380 depSetDirty( "addRequestedLocale", locale_r.code().c_str() );
381 _locale_hack( _requestedLocales, _locale2Solver );
387 static void _getLocaleDeps( Capability cap_r, std::tr1::unordered_set<sat::detail::IdType> & store_r )
389 // Collect locales from any 'namespace:language(lang)' dependency
390 CapDetail detail( cap_r );
391 if ( detail.kind() == CapDetail::EXPRESSION )
393 switch ( detail.capRel() )
395 case CapDetail::CAP_AND:
396 case CapDetail::CAP_OR:
398 _getLocaleDeps( detail.lhs(), store_r );
399 _getLocaleDeps( detail.rhs(), store_r );
402 case CapDetail::CAP_NAMESPACE:
403 if ( detail.lhs().id() == NAMESPACE_LANGUAGE )
405 store_r.insert( detail.rhs().id() );
409 case CapDetail::REL_NONE:
410 case CapDetail::CAP_WITH:
411 case CapDetail::CAP_ARCH:
417 const LocaleSet & PoolImpl::getAvailableLocales() const
419 if ( !_availableLocalesPtr )
421 // Collect any 'namespace:language(ja)' dependencies
422 std::tr1::unordered_set<sat::detail::IdType> tmp;
423 Pool pool( Pool::instance() );
424 for_( it, pool.solvablesBegin(), pool.solvablesEnd() )
426 Capabilities cap( it->supplements() );
427 for_( cit, cap.begin(), cap.end() )
429 _getLocaleDeps( *cit, tmp );
432 #warning immediately build LocaleSet as soon as Loale is an Id based type
433 _availableLocalesPtr.reset( new LocaleSet(tmp.size()) );
434 for_( it, tmp.begin(), tmp.end() )
436 _availableLocalesPtr->insert( Locale( IdString(*it) ) );
439 return *_availableLocalesPtr;
442 /////////////////////////////////////////////////////////////////
443 } // namespace detail
444 ///////////////////////////////////////////////////////////////////
445 /////////////////////////////////////////////////////////////////
447 ///////////////////////////////////////////////////////////////////
448 /////////////////////////////////////////////////////////////////
450 ///////////////////////////////////////////////////////////////////