1 /*---------------------------------------------------------------------\
3 | |__ / \ / / . \ . \ |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/sat/Transaction.cc
13 #include <satsolver/transaction.h>
16 #include "zypp/base/LogTools.h"
17 #include "zypp/base/SerialNumber.h"
18 #include "zypp/base/DefaultIntegral.h"
19 #include "zypp/base/NonCopyable.h"
20 #include "zypp/base/Tr1hash.h"
22 #include "zypp/sat/detail/PoolImpl.h"
23 #include "zypp/sat/Transaction.h"
24 #include "zypp/sat/Solvable.h"
25 #include "zypp/sat/Queue.h"
26 #include "zypp/PoolItem.h"
30 ///////////////////////////////////////////////////////////////////
32 { /////////////////////////////////////////////////////////////////
33 ///////////////////////////////////////////////////////////////////
35 { /////////////////////////////////////////////////////////////////
37 /** Transaction implementation.
38 * \todo check whether the pool serial number changed!
40 struct Transaction::Impl : protected detail::PoolMember
42 friend std::ostream & operator<<( std::ostream & str, const Impl & obj );
45 typedef std::tr1::unordered_set<detail::IdType> set_type;
46 typedef std::tr1::unordered_map<detail::IdType,detail::IdType> map_type;
50 { memset( &_trans, 0, sizeof(_trans) ); }
52 Impl( ::_Transaction & trans_r )
53 : _watcher( myPool().serial() )
55 ::transaction_init_clone( &_trans, &trans_r );
56 // NOTE: package/product buddies share the same ResStatus
57 // so we also link the buddies stepStages. This assumes
58 // only one buddy is acting during commit (package is installed,
59 // but no extra operation for the product).
60 for_( it, _trans.steps.elements, _trans.steps.elements + _trans.steps.count )
62 sat::Solvable solv( *it );
63 if ( ! solv.isKind<Package>() )
68 _linkMap[*it] = pi.buddy().id();
75 { ::transaction_free( &_trans ); }
79 { return _watcher.isClean( myPool().serial() ); }
86 ::transaction_order( &_trans, SOLVER_TRANSACTION_KEEP_ORDERDATA );
87 detail::IdType chosen = 0;
90 unsigned stopper = 10;
94 int ret = transaction_order_add_choices( &_trans, chosen, choices );
96 for_( it, choices.begin(), choices.end() )
104 if ( makeResObject( sat::Solvable(*it) )->mediaNr() > 1 )
109 MIL << ret << ": " << chosen << ": " << choices << endl;
121 ::transaction_order( &_trans, 0 );
128 { return( _trans.steps.count == 0 ); }
131 { return _trans.steps.count; }
133 const_iterator begin( const RW_pointer<Transaction::Impl> & self_r ) const
134 { return const_iterator( self_r, _trans.steps.elements ); }
135 iterator begin( const RW_pointer<Transaction::Impl> & self_r )
136 { return iterator( self_r, _trans.steps.elements ); }
138 const_iterator end( const RW_pointer<Transaction::Impl> & self_r ) const
139 { return const_iterator( self_r, _trans.steps.elements + _trans.steps.count ); }
140 iterator end( const RW_pointer<Transaction::Impl> & self_r )
141 { return iterator( self_r, _trans.steps.elements + _trans.steps.count ); }
143 const_iterator find(const RW_pointer<Transaction::Impl> & self_r, const sat::Solvable & solv_r ) const
144 { detail::IdType * it( _find( solv_r ) ); return it ? const_iterator( self_r, it ) : end( self_r ); }
145 iterator find(const RW_pointer<Transaction::Impl> & self_r, const sat::Solvable & solv_r )
146 { detail::IdType * it( _find( solv_r ) ); return it ? iterator( self_r, it ) : end( self_r ); }
149 detail::IdType * _find( const sat::Solvable & solv_r ) const
151 if ( solv_r && _trans.steps.elements )
153 for_( it, _trans.steps.elements, _trans.steps.elements + _trans.steps.count )
155 if ( *it == detail::IdType(solv_r.id()) )
163 StepType stepType( Solvable solv_r ) const
165 switch( ::transaction_type( &_trans, solv_r.id(), SOLVER_TRANSACTION_RPM_ONLY ) )
167 case SOLVER_TRANSACTION_ERASE: return TRANSACTION_ERASE; break;
168 case SOLVER_TRANSACTION_INSTALL: return TRANSACTION_INSTALL; break;
169 case SOLVER_TRANSACTION_MULTIINSTALL: return TRANSACTION_MULTIINSTALL; break;
171 return TRANSACTION_IGNORE;
174 StepStage stepStage( Solvable solv_r ) const
175 { return stepStage( resolve( solv_r ) ); }
177 void stepStage( Solvable solv_r, StepStage newval_r )
178 { stepStage( resolve( solv_r ), newval_r ); }
182 detail::IdType resolve( const Solvable & solv_r ) const
184 map_type::const_iterator res( _linkMap.find( solv_r.id() ) );
185 return( res == _linkMap.end() ? solv_r.id() : res->second );
188 bool isIn( const set_type & set_r, detail::IdType sid_r ) const
189 { return( set_r.find( sid_r ) != set_r.end() ); }
191 StepStage stepStage( detail::IdType sid_r ) const
193 if ( isIn( _doneSet, sid_r ) )
195 if ( isIn( _errSet, sid_r ) )
200 void stepStage( detail::IdType sid_r, StepStage newval_r )
202 StepStage stage( stepStage( sid_r ) );
203 if ( stage != newval_r )
206 if ( stage != STEP_TODO )
208 (stage == STEP_DONE ? _doneSet : _errSet).erase( sid_r );
210 if ( newval_r != STEP_TODO )
212 (newval_r == STEP_DONE ? _doneSet : _errSet).insert( sid_r );
217 SerialNumberWatcher _watcher;
218 mutable ::Transaction _trans;
219 DefaultIntegral<bool,false> _ordered;
226 /** Offer default Impl. */
227 static shared_ptr<Impl> nullimpl()
229 static shared_ptr<Impl> _nullimpl( new Impl );
234 /** \relates Transaction::Impl Stream output */
235 inline std::ostream & operator<<( std::ostream & str, const Transaction::Impl & obj )
237 return str << "Transaction: " << obj.size() << " (" << (obj.valid()?"valid":"INVALID") << ")";
240 ///////////////////////////////////////////////////////////////////
242 // CLASS NAME : Transaction
244 ///////////////////////////////////////////////////////////////////
246 Transaction::Transaction()
247 : _pimpl( Impl::nullimpl() )
250 Transaction::Transaction( ::_Transaction & trans_r )
251 : _pimpl( new Impl( trans_r ) )
254 Transaction::~Transaction()
257 bool Transaction::valid() const
258 { return _pimpl->valid(); }
260 bool Transaction::order()
261 { return _pimpl->order(); }
263 bool Transaction::empty() const
264 { return _pimpl->empty(); }
266 size_t Transaction::size() const
267 { return _pimpl->size(); }
269 Transaction::const_iterator Transaction::begin() const
270 { return _pimpl->begin( _pimpl ); }
272 Transaction::iterator Transaction::begin()
273 { return _pimpl->begin( _pimpl ); }
275 Transaction::const_iterator Transaction::end() const
276 { return _pimpl->end( _pimpl ); }
278 Transaction::iterator Transaction::end()
279 { return _pimpl->end( _pimpl ); }
281 Transaction::const_iterator Transaction::find( const sat::Solvable & solv_r ) const
282 { return _pimpl->find( _pimpl, solv_r ); }
284 Transaction::iterator Transaction::find( const sat::Solvable & solv_r )
285 { return _pimpl->find( _pimpl, solv_r ); }
287 std::ostream & operator<<( std::ostream & str, const Transaction & obj )
288 { return str << *obj._pimpl; }
290 std::ostream & dumpOn( std::ostream & str, const Transaction & obj )
292 for_( it, obj.begin(), obj.end() )
299 bool operator==( const Transaction & lhs, const Transaction & rhs )
300 { return lhs._pimpl == rhs._pimpl; }
302 ///////////////////////////////////////////////////////////////////
304 // CLASS NAME : Transaction::Step
306 ///////////////////////////////////////////////////////////////////
308 Transaction::Step::Step()
311 Transaction::StepType Transaction::Step::stepType() const
312 { return _pimpl->stepType( _solv ); }
314 Transaction::StepStage Transaction::Step::stepStage() const
315 { return _pimpl->stepStage( _solv ); }
317 void Transaction::Step::stepStage( StepStage val_r )
318 { _pimpl->stepStage( _solv, val_r ); }
320 std::ostream & operator<<( std::ostream & str, const Transaction::Step & obj )
321 { return str << obj.stepType() << obj.stepStage() << " " << PoolItem( obj.satSolvable() ); }
323 std::ostream & operator<<( std::ostream & str, Transaction::StepType obj )
327 #define OUTS(E,S) case Transaction::E: return str << #S; break
328 OUTS( TRANSACTION_IGNORE, [ ] );
329 OUTS( TRANSACTION_ERASE, [-] );
330 OUTS( TRANSACTION_INSTALL, [+] );
331 OUTS( TRANSACTION_MULTIINSTALL, [M] );
336 std::ostream & operator<<( std::ostream & str, Transaction::StepStage obj )
340 #define OUTS(E,S) case Transaction::E: return str << #S; break
341 OUTS( STEP_TODO, [__] );
342 OUTS( STEP_DONE, [OK] );
343 OUTS( STEP_ERROR, [**] );
347 ///////////////////////////////////////////////////////////////////
349 { /////////////////////////////////////////////////////////////////
350 ///////////////////////////////////////////////////////////////////
352 // CLASS NAME : Transaction::const_iterator/iterator
354 ///////////////////////////////////////////////////////////////////
356 Transaction_const_iterator::Transaction_const_iterator()
357 : Transaction_const_iterator::iterator_adaptor_( 0 )
360 Transaction_const_iterator::Transaction_const_iterator( const Transaction_iterator & iter_r )
361 : Transaction_const_iterator::iterator_adaptor_( iter_r.base() )
362 , _pimpl( iter_r._pimpl )
365 Transaction_iterator::Transaction_iterator()
366 : Transaction_iterator::iterator_adaptor_( 0 )
369 /////////////////////////////////////////////////////////////////
370 } // namespace detail
371 ///////////////////////////////////////////////////////////////////
372 /////////////////////////////////////////////////////////////////
374 ///////////////////////////////////////////////////////////////////
375 /////////////////////////////////////////////////////////////////
377 ///////////////////////////////////////////////////////////////////