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"
30 #include "zypp/target/modalias/Modalias.h"
34 #undef ZYPP_BASE_LOGGER_LOGGROUP
35 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::satpool"
37 // ///////////////////////////////////////////////////////////////////
39 { /////////////////////////////////////////////////////////////////
40 ///////////////////////////////////////////////////////////////////
42 { /////////////////////////////////////////////////////////////////
44 ///////////////////////////////////////////////////////////////////
46 { /////////////////////////////////////////////////////////////////
48 // MPL checks for satlib constants we redefine to avoid
49 // includes and defines.
50 BOOST_MPL_ASSERT_RELATION( noId, ==, STRID_NULL );
51 BOOST_MPL_ASSERT_RELATION( emptyId, ==, STRID_EMPTY );
53 BOOST_MPL_ASSERT_RELATION( noSolvableId, ==, ID_NULL );
54 BOOST_MPL_ASSERT_RELATION( systemSolvableId, ==, SYSTEMSOLVABLE );
56 BOOST_MPL_ASSERT_RELATION( solvablePrereqMarker, ==, SOLVABLE_PREREQMARKER );
57 BOOST_MPL_ASSERT_RELATION( solvableFileMarker, ==, SOLVABLE_FILEMARKER );
59 BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_AND, ==, REL_AND );
60 BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_OR, ==, REL_OR );
61 BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_WITH, ==, REL_WITH );
62 BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_NAMESPACE, ==, REL_NAMESPACE );
63 BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_ARCH, ==, REL_ARCH );
65 /////////////////////////////////////////////////////////////////
67 static void logSat( struct _Pool *, void *data, int type, const char *logString )
69 if ((type & (SAT_FATAL|SAT_ERROR))) {
70 _ERR("satsolver") << logString;
72 _MIL("satsolver") << logString;
76 detail::IdType PoolImpl::nsCallback( struct _Pool *, void * data, detail::IdType lhs, detail::IdType rhs )
78 // lhs: the namespace identifier, e.g. NAMESPACE:MODALIAS
79 // rhs: the value, e.g. pci:v0000104Cd0000840[01]sv*sd*bc*sc*i*
80 // return: 0 if not supportded
81 // 1 if supported by the system
82 // -1 AFAIK it's also possible to return a list of solvables that support it, but don't know how.
84 static const detail::IdType RET_unsupported = 0;
85 static const detail::IdType RET_systemProperty = 1;
88 case NAMESPACE_LANGUAGE:
90 static IdString en( "en" );
91 const std::tr1::unordered_set<IdString> & locale2Solver( reinterpret_cast<PoolImpl*>(data)->_locale2Solver );
92 if ( locale2Solver.empty() )
94 return rhs == en.id() ? RET_systemProperty : RET_unsupported;
96 return locale2Solver.find( IdString(rhs) ) != locale2Solver.end() ? RET_systemProperty : RET_unsupported;
100 case NAMESPACE_MODALIAS:
102 return target::Modalias::instance().query( IdString(rhs) ) ? RET_systemProperty : RET_unsupported;
106 case NAMESPACE_FILESYSTEM:
108 static const Pathname sysconfigStoragePath( "/etc/sysconfig/storage" );
109 static WatchFile sysconfigFile( sysconfigStoragePath, WatchFile::NO_INIT );
110 static std::set<std::string> requiredFilesystems;
111 if ( sysconfigFile.hasChanged() )
113 requiredFilesystems.clear();
114 str::split( base::sysconfig::read( sysconfigStoragePath )["USED_FS_LIST"],
115 std::inserter( requiredFilesystems, requiredFilesystems.end() ) );
117 return requiredFilesystems.find( IdString(rhs).asString() ) != requiredFilesystems.end() ? RET_systemProperty : RET_unsupported;
122 INT << "Unhandled " << Capability( lhs ) << " vs. " << Capability( rhs ) << endl;
123 return RET_unsupported;
126 ///////////////////////////////////////////////////////////////////
128 // METHOD NAME : PoolMember::myPool
129 // METHOD TYPE : PoolImpl
131 PoolImpl & PoolMember::myPool()
133 static PoolImpl _global;
137 ///////////////////////////////////////////////////////////////////
139 // METHOD NAME : PoolImpl::PoolImpl
140 // METHOD TYPE : Ctor
143 : _pool( ::pool_create() )
145 MIL << "Creating sat-pool." << endl;
148 ZYPP_THROW( Exception( _("Can not create sat-pool.") ) );
150 // initialialize logging
151 bool verbose = ( getenv("ZYPP_FULLLOG") || getenv("ZYPP_LIBSAT_FULLLOG") );
152 ::pool_setdebuglevel( _pool, verbose ? 5 : 1 );
153 ::pool_setdebugcallback( _pool, logSat, NULL );
155 // set namespace callback
156 _pool->nscallback = &nsCallback;
157 _pool->nscallbackdata = (void*)this;
160 ///////////////////////////////////////////////////////////////////
162 // METHOD NAME : PoolImpl::~PoolImpl
163 // METHOD TYPE : Dtor
165 PoolImpl::~PoolImpl()
167 ::pool_free( _pool );
170 ///////////////////////////////////////////////////////////////////
172 void PoolImpl::setDirty( const char * a1, const char * a2, const char * a3 )
176 if ( a3 ) MIL << a1 << " " << a2 << " " << a3 << endl;
177 else if ( a2 ) MIL << a1 << " " << a2 << endl;
178 else MIL << a1 << endl;
180 _serial.setDirty(); // pool content change
181 _availableLocalesPtr.reset(); // available locales may change
183 // invaldate dependency/namespace related indices:
187 void PoolImpl::depSetDirty( const char * a1, const char * a2, const char * a3 )
191 if ( a3 ) MIL << a1 << " " << a2 << " " << a3 << endl;
192 else if ( a2 ) MIL << a1 << " " << a2 << endl;
193 else MIL << a1 << endl;
195 ::pool_freewhatprovides( _pool );
198 void PoolImpl::prepare() const
200 if ( _watcher.remember( _serial ) )
202 // After repo/solvable add/remove:
203 // set pool architecture
204 ::pool_setarch( _pool, ZConfig::instance().systemArchitecture().asString().c_str() );
206 if ( ! _pool->whatprovides )
208 MIL << "pool_createwhatprovides..." << endl;
210 // NOTE: Thake care not to ctreate a nonexisting systemRepo
211 Repository sysrepo( sat::Pool::instance().reposFind( sat::Pool::instance().systemRepoName() ) );
214 ::pool_addfileprovides( _pool, sysrepo.get() );
216 ::pool_createwhatprovides( _pool );
218 if ( ! _pool->languages )
220 std::vector<std::string> fallbacklist;
221 for ( Locale l( ZConfig::instance().textLocale() ); l != Locale::noCode; l = l.fallback() )
223 fallbacklist.push_back( l.code() );
225 dumpRangeLine( MIL << "pool_set_languages: ", fallbacklist.begin(), fallbacklist.end() ) << endl;
227 std::vector<const char *> fallbacklist_cstr;
228 for_( it, fallbacklist.begin(), fallbacklist.end() )
230 fallbacklist_cstr.push_back( it->c_str() );
232 ::pool_set_languages( _pool, &fallbacklist_cstr.front(), fallbacklist_cstr.size() );
236 ///////////////////////////////////////////////////////////////////
238 int PoolImpl::_addSolv( ::_Repo * repo_r, FILE * file_r, bool isSystemRepo_r )
240 setDirty(__FUNCTION__, repo_r->name );
241 int ret = ::repo_add_solv( repo_r , file_r );
242 if ( ret == 0 && ! isSystemRepo_r )
244 // Filter out unwanted archs
245 std::set<detail::IdType> sysids;
247 Arch::CompatSet sysarchs( Arch::compatSet( ZConfig::instance().systemArchitecture() ) );
248 for_( it, sysarchs.begin(), sysarchs.end() )
249 sysids.insert( it->id() );
251 // unfortunately satsolver treats src/nosrc as architecture:
252 sysids.insert( ARCH_SRC );
253 sysids.insert( ARCH_NOSRC );
256 detail::IdType blockBegin = 0;
257 unsigned blockSize = 0;
258 for ( detail::IdType i = repo_r->start; i < repo_r->end; ++i )
260 ::_Solvable * s( _pool->solvables + i );
261 if ( s->repo == repo_r && sysids.find( s->arch ) == sysids.end() )
263 // Remember an unwanted arch entry:
268 else if ( blockSize )
270 // Free remembered entries
271 ::repo_free_solvable_block( repo_r, blockBegin, blockSize, /*reuseids*/false );
272 blockBegin = blockSize = 0;
277 // Free remembered entries
278 ::repo_free_solvable_block( repo_r, blockBegin, blockSize, /*reuseids*/false );
279 blockBegin = blockSize = 0;
285 ///////////////////////////////////////////////////////////////////
287 // need on demand and id based Locale
288 void _locale_hack( const LocaleSet & locales_r,
289 std::tr1::unordered_set<IdString> & locale2Solver )
291 std::tr1::unordered_set<IdString>( 2*locales_r.size() ).swap( locale2Solver );
292 for_( it, locales_r.begin(),locales_r.end() )
294 for ( Locale l( *it ); l != Locale::noCode; l = l.fallback() )
295 locale2Solver.insert( IdString( l.code() ) );
297 MIL << "New Solver Locales: " << locale2Solver << endl;
300 void PoolImpl::setRequestedLocales( const LocaleSet & locales_r )
302 depSetDirty( "setRequestedLocales" );
303 _requestedLocales = locales_r;
304 MIL << "New RequestedLocales: " << locales_r << endl;
305 _locale_hack( _requestedLocales, _locale2Solver );
308 bool PoolImpl::addRequestedLocale( const Locale & locale_r )
310 if ( _requestedLocales.insert( locale_r ).second )
312 depSetDirty( "addRequestedLocale", locale_r.code().c_str() );
313 _locale_hack( _requestedLocales, _locale2Solver );
319 bool PoolImpl::eraseRequestedLocale( const Locale & locale_r )
321 if ( _requestedLocales.erase( locale_r ) )
323 depSetDirty( "addRequestedLocale", locale_r.code().c_str() );
324 _locale_hack( _requestedLocales, _locale2Solver );
330 static void _getLocaleDeps( Capability cap_r, std::tr1::unordered_set<sat::detail::IdType> & store_r )
332 // Collect locales from any 'namespace:language(lang)' dependency
333 CapDetail detail( cap_r );
334 if ( detail.kind() == CapDetail::EXPRESSION )
336 switch ( detail.capRel() )
338 case CapDetail::CAP_AND:
339 case CapDetail::CAP_OR:
341 _getLocaleDeps( detail.lhs(), store_r );
342 _getLocaleDeps( detail.rhs(), store_r );
345 case CapDetail::CAP_NAMESPACE:
346 if ( detail.lhs().id() == NAMESPACE_LANGUAGE )
348 store_r.insert( detail.rhs().id() );
352 case CapDetail::REL_NONE:
353 case CapDetail::CAP_WITH:
354 case CapDetail::CAP_ARCH:
360 const LocaleSet & PoolImpl::getAvailableLocales() const
362 if ( !_availableLocalesPtr )
364 // Collect any 'namespace:language(ja)' dependencies
365 std::tr1::unordered_set<sat::detail::IdType> tmp;
366 Pool pool( Pool::instance() );
367 for_( it, pool.solvablesBegin(), pool.solvablesEnd() )
369 Capabilities cap( it->supplements() );
370 for_( cit, cap.begin(), cap.end() )
372 _getLocaleDeps( *cit, tmp );
375 #warning immediately build LocaleSet as soon as Loale is an Id based type
376 _availableLocalesPtr.reset( new LocaleSet(tmp.size()) );
377 for_( it, tmp.begin(), tmp.end() )
379 _availableLocalesPtr->insert( Locale( IdString(*it) ) );
382 return *_availableLocalesPtr;
385 /////////////////////////////////////////////////////////////////
386 } // namespace detail
387 ///////////////////////////////////////////////////////////////////
388 /////////////////////////////////////////////////////////////////
390 ///////////////////////////////////////////////////////////////////
391 /////////////////////////////////////////////////////////////////
393 ///////////////////////////////////////////////////////////////////