Enabled Pool to handle automatic soft-locks,
[platform/upstream/libzypp.git] / zypp / pool / PoolImpl.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/pool/PoolImpl.h
10  *
11 */
12 #ifndef ZYPP_POOL_POOLIMPL_H
13 #define ZYPP_POOL_POOLIMPL_H
14
15 #include <iosfwd>
16
17 #include "zypp/base/Easy.h"
18 #include "zypp/base/LogTools.h"
19 #include "zypp/base/SerialNumber.h"
20 #include "zypp/base/Deprecated.h"
21
22 #include "zypp/pool/PoolTraits.h"
23 #include "zypp/ResPoolProxy.h"
24
25 #include "zypp/sat/Pool.h"
26
27 using std::endl;
28
29 ///////////////////////////////////////////////////////////////////
30 namespace zypp
31 { /////////////////////////////////////////////////////////////////
32   ///////////////////////////////////////////////////////////////////
33   namespace pool
34   { /////////////////////////////////////////////////////////////////
35
36     ///////////////////////////////////////////////////////////////////
37     //
38     //  CLASS NAME : PoolImpl
39     //
40     /** */
41     class PoolImpl
42     {
43       friend std::ostream & operator<<( std::ostream & str, const PoolImpl & obj );
44
45       public:
46         /** */
47         typedef PoolTraits::ItemContainerT              ContainerT;
48         typedef PoolTraits::size_type                   size_type;
49         typedef PoolTraits::const_iterator              const_iterator;
50         typedef PoolTraits::Id2ItemT                    Id2ItemT;
51
52         typedef PoolTraits::repository_iterator         repository_iterator;
53
54         typedef sat::detail::SolvableIdType             SolvableIdType;
55
56       public:
57         /** Default ctor */
58         PoolImpl();
59         /** Dtor */
60         ~PoolImpl();
61
62       public:
63         /** convenience. */
64         const sat::Pool satpool() const
65         { return sat::Pool::instance(); }
66
67         /** Housekeeping data serial number. */
68         const SerialNumber & serial() const
69         { return satpool().serial(); }
70
71         ///////////////////////////////////////////////////////////////////
72         //
73         ///////////////////////////////////////////////////////////////////
74       public:
75         /**  */
76         bool empty() const
77         { return satpool().solvablesEmpty(); }
78
79         /**  */
80         size_type size() const
81         { return satpool().solvablesSize(); }
82
83         const_iterator begin() const
84         { return make_filter_begin( pool::ByPoolItem(), store() ); }
85
86         const_iterator end() const
87         { return make_filter_end( pool::ByPoolItem(), store() ); }
88
89       public:
90         /** Return the corresponding \ref PoolItem.
91          * Pool and sat pool should be in sync. Returns an empty
92          * \ref PoolItem if there is no corresponding \ref PoolItem.
93          * \see \ref PoolItem::satSolvable.
94          */
95         PoolItem find( const sat::Solvable & slv_r ) const
96         {
97           const ContainerT & mystore( store() );
98           return( slv_r.id() < mystore.size() ? mystore[slv_r.id()] : PoolItem() );
99         }
100
101         ///////////////////////////////////////////////////////////////////
102         //
103         ///////////////////////////////////////////////////////////////////
104       public:
105         /** \name Save and restore state. */
106         //@{
107         void SaveState( const ResObject::Kind & kind_r );
108
109         void RestoreState( const ResObject::Kind & kind_r );
110         //@}
111
112         ///////////////////////////////////////////////////////////////////
113         //
114         ///////////////////////////////////////////////////////////////////
115       public:
116         ResPoolProxy proxy( ResPool self ) const
117         {
118           checkSerial();
119           if ( !_poolProxy )
120           {
121             _poolProxy.reset( new ResPoolProxy( self, *this ) );
122           }
123           return *_poolProxy;
124         }
125
126       public:
127         /** Forward list of Repositories that contribute ResObjects from \ref sat::Pool */
128         size_type knownRepositoriesSize() const
129         { checkSerial(); return satpool().reposSize(); }
130
131         repository_iterator knownRepositoriesBegin() const
132         { checkSerial(); return satpool().reposBegin(); }
133
134         repository_iterator knownRepositoriesEnd() const
135         { checkSerial(); return satpool().reposEnd(); }
136
137         ///////////////////////////////////////////////////////////////////
138         //
139         ///////////////////////////////////////////////////////////////////
140       public:
141         bool hardLockAppliesTo( sat::Solvable solv_r ) const
142         {
143           return false;
144         }
145
146       public:
147         typedef PoolTraits::AutoSoftLocks          AutoSoftLocks;
148         typedef PoolTraits::autoSoftLocks_iterator autoSoftLocks_iterator;
149
150         const AutoSoftLocks & autoSoftLocks() const
151         { return _autoSoftLocks; }
152
153         bool autoSoftLockAppliesTo( sat::Solvable solv_r ) const
154         { return( _autoSoftLocks.find( solv_r.ident() ) != _autoSoftLocks.end() ); }
155
156         void setAutoSoftLocks( const AutoSoftLocks & newLocks_r )
157         {
158           MIL << "Apply " << newLocks_r.size() << " AutoSoftLocks: " << newLocks_r << endl;
159           _autoSoftLocks = newLocks_r;
160           // now adjust the pool status
161           for_( it, begin(), end() )
162           {
163             if ( ! it->status().isKept() )
164               continue;
165
166             if ( newLocks_r.find( it->satSolvable().ident() ) != newLocks_r.end() )
167               it->status().setSoftLock( ResStatus::USER );
168             else
169               it->status().resetTransact( ResStatus::USER );
170           }
171         }
172
173         void getActiveSoftLocks( AutoSoftLocks & activeLocks_r )
174         {
175           activeLocks_r = _autoSoftLocks; // currentsoft-locks
176           AutoSoftLocks todel;            // + names to be deleted
177           AutoSoftLocks toins;            // - names to be installed
178
179           for_( it, begin(), end() )
180           {
181             ResStatus & status( it->status() );
182             if ( ! status.isByUser() )
183               continue;
184
185             switch ( status.getTransactValue() )
186             {
187               case ResStatus::KEEP_STATE:
188                 activeLocks_r.insert( it->satSolvable().ident() );
189                 break;
190               case ResStatus::LOCKED:
191                 //  NOOP
192                 break;
193               case ResStatus::TRANSACT:
194                 (status.isInstalled() ? todel : toins).insert( it->satSolvable().ident() );
195                 break;
196             }
197           }
198           for_( it, todel.begin(), todel.end() )
199           {
200             activeLocks_r.insert( *it );
201           }
202           for_( it, toins.begin(), toins.end() )
203           {
204             activeLocks_r.erase( *it );
205           }
206         }
207
208       public:
209         const ContainerT & store() const
210         {
211           checkSerial();
212           if ( _storeDirty )
213           {
214             sat::Pool pool( satpool() );
215
216             if ( pool.capacity() != _store.capacity() )
217             {
218               _store.resize( pool.capacity() );
219             }
220
221             if ( pool.capacity() )
222             {
223               for ( sat::detail::SolvableIdType i = pool.capacity()-1; i != 0; --i )
224               {
225                 sat::Solvable s( i );
226                 PoolItem & pi( _store[i] );
227                 if ( ! s &&  pi )
228                 {
229                   // the PoolItem got invalidated (e.g unloaded repo)
230                   pi = PoolItem();
231                 }
232                 else if ( s && ! pi )
233                 {
234                   // new PoolItem to add
235                   pi = PoolItem::makePoolItem( s ); // the only way to create a new one!
236                   // and a few checks...
237                   if ( hardLockAppliesTo( s ) )
238                   {
239                     pi.status().setLock( true, ResStatus::USER );
240                   }
241                   else if ( autoSoftLockAppliesTo( s ) )
242                   {
243                     pi.status().setSoftLock( ResStatus::USER );
244                   }
245                 }
246               }
247             }
248             _storeDirty = false;
249           }
250           return _store;
251         }
252
253         const Id2ItemT & id2item () const
254         {
255           checkSerial();
256           if ( _id2itemDirty )
257           {
258             store();
259             _id2item = Id2ItemT( size() );
260             for_( it, begin(), end() )
261             {
262               const sat::Solvable &s = (*it)->satSolvable();
263               sat::detail::IdType id = s.ident().id();
264               if ( s.isKind( ResKind::srcpackage ) )
265                 id = -id;
266               _id2item.insert( std::make_pair( id, *it ) );
267             }
268             //INT << _id2item << endl;
269             _id2itemDirty = false;
270           }
271           return _id2item;
272         }
273
274         ///////////////////////////////////////////////////////////////////
275         //
276         ///////////////////////////////////////////////////////////////////
277       private:
278         void checkSerial() const
279         {
280           if ( _watcher.remember( serial() ) )
281             invalidate();
282           satpool().prepare(); // always ajust dependencies.
283         }
284
285         void invalidate() const
286         {
287           _storeDirty = true;
288           _id2itemDirty = true;
289           _id2item.clear();
290           _poolProxy.reset();
291         }
292
293       private:
294         /** Watch sat pools serial number. */
295         SerialNumberWatcher                   _watcher;
296         mutable ContainerT                    _store;
297         mutable DefaultIntegral<bool,true>    _storeDirty;
298         mutable Id2ItemT                      _id2item;
299         mutable DefaultIntegral<bool,true>    _id2itemDirty;
300
301       private:
302         mutable shared_ptr<ResPoolProxy>      _poolProxy;
303
304       private:
305         /** Set of solvable idents that should be soft locked per default. */
306         AutoSoftLocks                         _autoSoftLocks;
307     };
308     ///////////////////////////////////////////////////////////////////
309
310     /////////////////////////////////////////////////////////////////
311   } // namespace pool
312   ///////////////////////////////////////////////////////////////////
313   /////////////////////////////////////////////////////////////////
314 } // namespace zypp
315 ///////////////////////////////////////////////////////////////////
316 #endif // ZYPP_POOL_POOLIMPL_H