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 { /////////////////////////////////////////////////////////////////
46 ///////////////////////////////////////////////////////////////////
48 { /////////////////////////////////////////////////////////////////
50 // MPL checks for satlib constants we redefine to avoid
51 // includes and defines.
52 BOOST_MPL_ASSERT_RELATION( noId, ==, STRID_NULL );
53 BOOST_MPL_ASSERT_RELATION( emptyId, ==, STRID_EMPTY );
55 BOOST_MPL_ASSERT_RELATION( noSolvableId, ==, ID_NULL );
56 BOOST_MPL_ASSERT_RELATION( systemSolvableId, ==, SYSTEMSOLVABLE );
58 BOOST_MPL_ASSERT_RELATION( solvablePrereqMarker, ==, SOLVABLE_PREREQMARKER );
59 BOOST_MPL_ASSERT_RELATION( solvableFileMarker, ==, SOLVABLE_FILEMARKER );
61 BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_AND, ==, REL_AND );
62 BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_OR, ==, REL_OR );
63 BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_WITH, ==, REL_WITH );
64 BOOST_MPL_ASSERT_RELATION( CapDetail::CAP_NAMESPACE, ==, REL_NAMESPACE );
66 /////////////////////////////////////////////////////////////////
68 static void logSat( struct _Pool *, void *data, int type, const char *logString )
70 if ((type & (SAT_FATAL|SAT_ERROR))) {
71 _ERR("satsolver") << logString;
73 _MIL("satsolver") << logString;
77 detail::IdType PoolImpl::nsCallback( struct _Pool *, void * data, detail::IdType lhs, detail::IdType rhs )
79 // lhs: the namespace identifier, e.g. NAMESPACE:MODALIAS
80 // rhs: the value, e.g. pci:v0000104Cd0000840[01]sv*sd*bc*sc*i*
81 // return: 0 if not supportded
82 // 1 if supported by the system
83 // -1 AFAIK it's also possible to return a list of solvables that support it, but don't know how.
85 static const detail::IdType RET_unsupported = 0;
86 static const detail::IdType RET_systemProperty = 1;
89 case NAMESPACE_LANGUAGE:
91 const std::tr1::unordered_set<IdString> & locale2Solver( reinterpret_cast<PoolImpl*>(data)->_locale2Solver );
92 return locale2Solver.find( IdString(rhs) ) != locale2Solver.end() ? RET_systemProperty : RET_unsupported;
96 case NAMESPACE_MODALIAS:
98 return target::Modalias::instance().query( IdString(rhs) ) ? RET_systemProperty : RET_unsupported;
102 case NAMESPACE_FILESYSTEM:
104 static const Pathname sysconfigStoragePath( "/etc/sysconfig/storage" );
105 static WatchFile sysconfigFile( sysconfigStoragePath, WatchFile::NO_INIT );
106 static std::set<std::string> requiredFilesystems;
107 if ( sysconfigFile.hasChanged() )
109 requiredFilesystems.clear();
110 str::split( base::sysconfig::read( sysconfigStoragePath )["USED_FS_LIST"],
111 std::inserter( requiredFilesystems, requiredFilesystems.end() ) );
113 return requiredFilesystems.find( IdString(rhs).asString() ) != requiredFilesystems.end() ? RET_systemProperty : RET_unsupported;
118 INT << "Unhandled " << Capability( lhs ) << " vs. " << Capability( rhs ) << endl;
119 return RET_unsupported;
122 ///////////////////////////////////////////////////////////////////
124 // METHOD NAME : PoolMember::myPool
125 // METHOD TYPE : PoolImpl
127 PoolImpl & PoolMember::myPool()
129 static PoolImpl _global;
133 ///////////////////////////////////////////////////////////////////
135 // METHOD NAME : PoolImpl::PoolImpl
136 // METHOD TYPE : Ctor
139 : _pool( ::pool_create() )
141 MIL << "Creating sat-pool." << endl;
144 ZYPP_THROW( Exception( _("Can not create sat-pool.") ) );
146 // initialialize logging
147 bool verbose = ( getenv("ZYPP_FULLLOG") || getenv("ZYPP_LIBSAT_FULLLOG") );
148 ::pool_setdebuglevel( _pool, verbose ? 5 : 1 );
149 ::pool_setdebugcallback( _pool, logSat, NULL );
151 // set namespace callback
152 _pool->nscallback = &nsCallback;
153 _pool->nscallbackdata = (void*)this;
156 ///////////////////////////////////////////////////////////////////
158 // METHOD NAME : PoolImpl::~PoolImpl
159 // METHOD TYPE : Dtor
161 PoolImpl::~PoolImpl()
163 ::pool_free( _pool );
166 ///////////////////////////////////////////////////////////////////
168 void PoolImpl::setDirty( const char * a1, const char * a2, const char * a3 )
172 if ( a3 ) MIL << a1 << " " << a2 << " " << a3 << endl;
173 else if ( a2 ) MIL << a1 << " " << a2 << endl;
174 else MIL << a1 << endl;
176 _serial.setDirty(); // pool content change
177 _availableLocalesPtr.reset(); // available locales may change
179 // invaldate dependency/namespace related indices:
183 void PoolImpl::depSetDirty( const char * a1, const char * a2, const char * a3 )
187 if ( a3 ) MIL << a1 << " " << a2 << " " << a3 << endl;
188 else if ( a2 ) MIL << a1 << " " << a2 << endl;
189 else MIL << a1 << endl;
191 ::pool_freewhatprovides( _pool );
194 void PoolImpl::prepare() const
196 if ( _watcher.remember( _serial ) )
198 // After repo/solvable add/remove:
199 // set pool architecture
200 ::pool_setarch( _pool, ZConfig::instance().systemArchitecture().asString().c_str() );
202 if ( ! _pool->whatprovides )
204 MIL << "pool_createwhatprovides..." << endl;
206 // NOTE: Thake care not to ctreate a nonexisting systemRepo
207 Repository sysrepo( sat::Pool::instance().reposFind( sat::Pool::instance().systemRepoName() ) );
210 ::pool_addfileprovides( _pool, sysrepo.get() );
212 ::pool_createwhatprovides( _pool );
214 if ( ! _pool->languages )
216 std::vector<std::string> fallbacklist;
217 for ( Locale l( ZConfig::instance().textLocale() ); l != Locale::noCode; l = l.fallback() )
219 fallbacklist.push_back( l.code() );
221 dumpRangeLine( MIL << "pool_set_languages: ", fallbacklist.begin(), fallbacklist.end() ) << endl;
223 std::vector<const char *> fallbacklist_cstr;
224 for_( it, fallbacklist.begin(), fallbacklist.end() )
226 fallbacklist_cstr.push_back( it->c_str() );
228 ::pool_set_languages( _pool, &fallbacklist_cstr.front(), fallbacklist_cstr.size() );
232 ///////////////////////////////////////////////////////////////////
234 int PoolImpl::_addSolv( ::_Repo * repo_r, FILE * file_r, bool isSystemRepo_r )
236 setDirty(__FUNCTION__, repo_r->name );
237 int ret = ::repo_add_solv( repo_r , file_r );
238 if ( ret == 0 && ! isSystemRepo_r )
240 // Filter out unwanted archs
241 std::set<detail::IdType> sysids;
243 Arch::CompatSet sysarchs( Arch::compatSet( ZConfig::instance().systemArchitecture() ) );
244 for_( it, sysarchs.begin(), sysarchs.end() )
245 sysids.insert( it->id() );
247 // unfortunately satsolver treats src/nosrc as architecture:
248 sysids.insert( ARCH_SRC );
249 sysids.insert( ARCH_NOSRC );
252 detail::IdType blockBegin = 0;
253 unsigned blockSize = 0;
254 for ( detail::IdType i = repo_r->start; i < repo_r->end; ++i )
256 ::_Solvable * s( _pool->solvables + i );
257 if ( s->repo == repo_r && sysids.find( s->arch ) == sysids.end() )
259 // Remember an unwanted arch entry:
264 else if ( blockSize )
266 // Free remembered entries
267 ::repo_free_solvable_block( repo_r, blockBegin, blockSize, /*reuseids*/false );
268 blockBegin = blockSize = 0;
273 // Free remembered entries
274 ::repo_free_solvable_block( repo_r, blockBegin, blockSize, /*reuseids*/false );
275 blockBegin = blockSize = 0;
281 ///////////////////////////////////////////////////////////////////
283 // need on demand and id based Locale
284 void _locale_hack( const LocaleSet & locales_r,
285 std::tr1::unordered_set<IdString> & locale2Solver )
287 std::tr1::unordered_set<IdString>( 2*locales_r.size() ).swap( locale2Solver ) ;
288 for_( it, locales_r.begin(),locales_r.end() )
290 for ( Locale l( *it ); l != Locale::noCode; l = l.fallback() )
291 locale2Solver.insert( IdString( l.code() ) );
293 MIL << "New Solver Locales: " << locale2Solver << endl;
296 void PoolImpl::setRequestedLocales( const LocaleSet & locales_r )
298 depSetDirty( "setRequestedLocales" );
299 _requestedLocales = locales_r;
300 MIL << "New RequestedLocales: " << locales_r << endl;
301 _locale_hack( _requestedLocales, _locale2Solver );
304 bool PoolImpl::addRequestedLocale( const Locale & locale_r )
306 if ( _requestedLocales.insert( locale_r ).second )
308 depSetDirty( "addRequestedLocale", locale_r.code().c_str() );
309 _locale_hack( _requestedLocales, _locale2Solver );
315 bool PoolImpl::eraseRequestedLocale( const Locale & locale_r )
317 if ( _requestedLocales.erase( locale_r ) )
319 depSetDirty( "addRequestedLocale", locale_r.code().c_str() );
320 _locale_hack( _requestedLocales, _locale2Solver );
326 static void _getLocaleDeps( Capability cap_r, std::tr1::unordered_set<sat::detail::IdType> & store_r )
328 // Collect locales from any 'namespace:language(lang)' dependency
329 CapDetail detail( cap_r );
330 if ( detail.kind() == CapDetail::EXPRESSION )
332 switch ( detail.capRel() )
334 case CapDetail::CAP_AND:
335 case CapDetail::CAP_OR:
337 _getLocaleDeps( detail.lhs(), store_r );
338 _getLocaleDeps( detail.rhs(), store_r );
341 case CapDetail::CAP_NAMESPACE:
342 if ( detail.lhs().id() == NAMESPACE_LANGUAGE )
344 store_r.insert( detail.rhs().id() );
348 case CapDetail::REL_NONE:
349 case CapDetail::CAP_WITH:
355 const LocaleSet & PoolImpl::getAvailableLocales() const
357 if ( !_availableLocalesPtr )
359 // Collect any 'namespace:language(ja)' dependencies
360 std::tr1::unordered_set<sat::detail::IdType> tmp;
361 Pool pool( Pool::instance() );
362 for_( it, pool.solvablesBegin(), pool.solvablesEnd() )
364 Capabilities cap( it->supplements() );
365 for_( cit, cap.begin(), cap.end() )
367 _getLocaleDeps( *cit, tmp );
370 #warning immediately build LocaleSet as soon as Loale is an Id based type
371 _availableLocalesPtr.reset( new LocaleSet(tmp.size()) );
372 for_( it, tmp.begin(), tmp.end() )
374 _availableLocalesPtr->insert( Locale( IdString(*it) ) );
377 return *_availableLocalesPtr;
380 /////////////////////////////////////////////////////////////////
381 } // namespace detail
382 ///////////////////////////////////////////////////////////////////
383 /////////////////////////////////////////////////////////////////
385 ///////////////////////////////////////////////////////////////////
386 /////////////////////////////////////////////////////////////////
388 ///////////////////////////////////////////////////////////////////