Do not filter any installed solvables.
[platform/upstream/libzypp.git] / zypp / sat / detail / PoolImpl.cc
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/sat/detail/PoolImpl.cc
10  *
11 */
12 #include <iostream>
13 #include <boost/mpl/int.hpp>
14
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
21 #include "zypp/ZConfig.h"
22
23 #include "zypp/sat/detail/PoolImpl.h"
24 #include "zypp/sat/Pool.h"
25 #include "zypp/Capability.h"
26 #include "zypp/Locale.h"
27
28 using std::endl;
29
30 #undef  ZYPP_BASE_LOGGER_LOGGROUP
31 #define ZYPP_BASE_LOGGER_LOGGROUP "zypp::satpool"
32
33 // ///////////////////////////////////////////////////////////////////
34 namespace zypp
35 { /////////////////////////////////////////////////////////////////
36   ///////////////////////////////////////////////////////////////////
37   namespace sat
38   { /////////////////////////////////////////////////////////////////
39     ///////////////////////////////////////////////////////////////////
40     namespace detail
41     { /////////////////////////////////////////////////////////////////
42
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 );
47
48       BOOST_MPL_ASSERT_RELATION( solvablePrereqMarker, ==, SOLVABLE_PREREQMARKER );
49       BOOST_MPL_ASSERT_RELATION( solvableFileMarker,   ==, SOLVABLE_FILEMARKER );
50
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 );
55
56      /////////////////////////////////////////////////////////////////
57
58       static void logSat( struct _Pool *, void *data, int type, const char *logString )
59       {
60           if ((type & (SAT_FATAL|SAT_ERROR))) {
61               _ERR("satsolver") << logString;
62           } else {
63               _MIL("satsolver") << logString;
64           }
65       }
66
67       detail::IdType PoolImpl::nsCallback( struct _Pool *, void *data, detail::IdType lhs, detail::IdType rhs )
68       {
69         if ( lhs == NAMESPACE_LANGUAGE )
70         {
71           const std::tr1::unordered_set<IdString> & locale2Solver( reinterpret_cast<PoolImpl*>(data)->_locale2Solver );
72           return locale2Solver.find( IdString(rhs) ) == locale2Solver.end() ? -1 : 0;
73         }
74         DBG << Capability( lhs ) << " vs. " << Capability( rhs ) << endl;
75         return 0;
76       }
77
78       ///////////////////////////////////////////////////////////////////
79       //
80       //        METHOD NAME : PoolMember::myPool
81       //        METHOD TYPE : PoolImpl
82       //
83       PoolImpl & PoolMember::myPool()
84       {
85         static PoolImpl _global;
86         return _global;
87       }
88
89       ///////////////////////////////////////////////////////////////////
90       //
91       //        METHOD NAME : PoolImpl::PoolImpl
92       //        METHOD TYPE : Ctor
93       //
94       PoolImpl::PoolImpl()
95       : _pool( ::pool_create() )
96       {
97         MIL << "Creating sat-pool." << endl;
98         if ( ! _pool )
99         {
100           ZYPP_THROW( Exception( _("Can not create sat-pool.") ) );
101         }
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 );
106
107         // set namespace callback
108         _pool->nscallback = &nsCallback;
109         _pool->nscallbackdata = (void*)this;
110       }
111
112       ///////////////////////////////////////////////////////////////////
113       //
114       //        METHOD NAME : PoolImpl::~PoolImpl
115       //        METHOD TYPE : Dtor
116       //
117       PoolImpl::~PoolImpl()
118       {
119         ::pool_free( _pool );
120       }
121
122      ///////////////////////////////////////////////////////////////////
123
124       void PoolImpl::setDirty( const char * a1, const char * a2, const char * a3 )
125       {
126         if ( a1 )
127         {
128           if      ( a3 ) DBG << a1 << " " << a2 << " " << a3 << endl;
129           else if ( a2 ) DBG << a1 << " " << a2 << endl;
130           else           DBG << a1 << endl;
131         }
132         _serial.setDirty();           // pool content change
133         _availableLocalesPtr.reset(); // available locales may change
134
135         // invaldate dependency/namespace related indices:
136         depSetDirty();
137       }
138
139       void PoolImpl::depSetDirty( const char * a1, const char * a2, const char * a3 )
140       {
141         if ( a1 )
142         {
143           if      ( a3 ) DBG << a1 << " " << a2 << " " << a3 << endl;
144           else if ( a2 ) DBG << a1 << " " << a2 << endl;
145           else           DBG << a1 << endl;
146         }
147         ::pool_freewhatprovides( _pool );
148       }
149
150       void PoolImpl::prepare() const
151       {
152         if ( _watcher.remember( _serial ) )
153         {
154           // After repo/solvable add/remove:
155           // set pool architecture
156           ::pool_setarch( _pool,  ZConfig::instance().systemArchitecture().asString().c_str() );
157         }
158         if ( ! _pool->whatprovides )
159         {
160           DBG << "pool_createwhatprovides..." << endl;
161           ::pool_addfileprovides( _pool, sat::Pool::instance().systemRepo().get() );
162           ::pool_createwhatprovides( _pool );
163         }
164       }
165
166       ///////////////////////////////////////////////////////////////////
167
168       int PoolImpl::_addSolv( ::_Repo * repo_r, FILE * file_r, bool isSystemRepo_r )
169       {
170         setDirty(__FUNCTION__, repo_r->name );
171         int ret = ::repo_add_solv( repo_r , file_r  );
172         if ( ret == 0 && ! isSystemRepo_r )
173         {
174           // Filter out unwanted archs
175           std::set<detail::IdType> sysids;
176           {
177             Arch::CompatSet sysarchs( Arch::compatSet( ZConfig::instance().systemArchitecture() ) );
178             for_( it, sysarchs.begin(), sysarchs.end() )
179                sysids.insert( it->idStr().id() );
180
181             // unfortunately satsolver treats src/nosrc as architecture:
182             sysids.insert( ARCH_SRC );
183             sysids.insert( ARCH_NOSRC );
184           }
185
186           detail::IdType blockBegin = 0;
187           unsigned       blockSize  = 0;
188           for ( detail::IdType i = repo_r->start; i < repo_r->end; ++i )
189           {
190             ::_Solvable * s( _pool->solvables + i );
191             if ( s->repo == repo_r && sysids.find( s->arch ) == sysids.end() )
192             {
193               // Remember an unwanted arch entry:
194               if ( ! blockBegin )
195                 blockBegin = i;
196               ++blockSize;
197             }
198             else if ( blockSize )
199             {
200               // Free remembered entries
201               ::repo_free_solvable_block( repo_r, blockBegin, blockSize, /*reuseids*/false );
202               blockBegin = blockSize = 0;
203             }
204           }
205           if ( blockSize )
206           {
207             // Free remembered entries
208             ::repo_free_solvable_block( repo_r, blockBegin, blockSize, /*reuseids*/false );
209             blockBegin = blockSize = 0;
210           }
211         }
212         return ret;
213       }
214
215       ///////////////////////////////////////////////////////////////////
216
217       // need on demand and id based Locale
218       void _locale_hack( const LocaleSet & locales_r,
219                          std::tr1::unordered_set<IdString> & locale2Solver )
220       {
221         std::tr1::unordered_set<IdString>( 2*locales_r.size() ).swap( locale2Solver ) ;
222         for_( it, locales_r.begin(),locales_r.end() )
223         {
224           for ( Locale l( *it ); l != Locale::noCode; l = l.fallback() )
225             locale2Solver.insert( IdString( l.code() ) );
226         }
227         DBG << "New Solver Locales: " << locale2Solver << endl;
228       }
229
230       void PoolImpl::setRequestedLocales( const LocaleSet & locales_r )
231       {
232         depSetDirty( "setRequestedLocales" );
233         _requestedLocales = locales_r;
234         DBG << "New RequestedLocales: " << locales_r << endl;
235         _locale_hack( _requestedLocales, _locale2Solver );
236       }
237
238       bool PoolImpl::addRequestedLocale( const Locale & locale_r )
239       {
240         if ( _requestedLocales.insert( locale_r ).second )
241         {
242           depSetDirty( "addRequestedLocale", locale_r.code().c_str() );
243           _locale_hack( _requestedLocales, _locale2Solver );
244           return true;
245         }
246         return false;
247       }
248
249       bool PoolImpl::eraseRequestedLocale( const Locale & locale_r )
250       {
251         if ( _requestedLocales.erase( locale_r ) )
252         {
253           depSetDirty( "addRequestedLocale", locale_r.code().c_str() );
254           _locale_hack( _requestedLocales, _locale2Solver );
255           return true;
256         }
257         return false;
258       }
259
260       static void _getLocaleDeps( Capability cap_r, std::tr1::unordered_set<sat::detail::IdType> & store_r )
261       {
262         // Collect locales from any 'namespace:language(lang)' dependency
263         CapDetail detail( cap_r );
264         if ( detail.kind() == CapDetail::EXPRESSION )
265         {
266           switch ( detail.capRel() )
267           {
268             case CapDetail::CAP_AND:
269             case CapDetail::CAP_OR:
270               // expand
271               _getLocaleDeps( detail.lhs(), store_r );
272               _getLocaleDeps( detail.rhs(), store_r );
273               break;
274
275             case CapDetail::CAP_NAMESPACE:
276               if ( detail.lhs().id() == NAMESPACE_LANGUAGE )
277               {
278                 store_r.insert( detail.rhs().id() );
279               }
280               break;
281
282             case CapDetail::REL_NONE:
283             case CapDetail::CAP_WITH:
284               break; // unwanted
285           }
286         }
287       }
288
289       const LocaleSet & PoolImpl::getAvailableLocales() const
290       {
291         if ( !_availableLocalesPtr )
292         {
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() )
297           {
298             Capabilities cap( it->supplements() );
299             for_( cit, cap.begin(), cap.end() )
300             {
301               _getLocaleDeps( *cit, tmp );
302             }
303           }
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() )
307           {
308             _availableLocalesPtr->insert( Locale( IdString(*it) ) );
309           }
310         }
311         return *_availableLocalesPtr;
312       }
313
314       /////////////////////////////////////////////////////////////////
315     } // namespace detail
316     ///////////////////////////////////////////////////////////////////
317     /////////////////////////////////////////////////////////////////
318   } // namespace sat
319   ///////////////////////////////////////////////////////////////////
320   /////////////////////////////////////////////////////////////////
321 } // namespace zypp
322 ///////////////////////////////////////////////////////////////////