libzypp 17.37.17
Transaction.cc
Go to the documentation of this file.
1/*---------------------------------------------------------------------\
2| ____ _ __ __ ___ |
3| |__ / \ / / . \ . \ |
4| / / \ V /| _/ _/ |
5| / /__ | | | | | | |
6| /_____||_| |_| |_| |
7| |
8\---------------------------------------------------------------------*/
11extern "C"
12{
13#include <solv/transaction.h>
14#include <solv/solver.h>
15}
16#include <iostream>
17#include <zypp/base/LogTools.h>
19#include <zypp-core/base/DefaultIntegral>
21#include <zypp/base/Hash.h>
22
25#include <zypp/sat/Solvable.h>
26#include <zypp/sat/Queue.h>
27#include <zypp/sat/Map.h>
28#include <zypp/ResPool.h>
29
30using std::endl;
31
33namespace zypp
34{
36 namespace sat
37 {
38
40
50 , private base::NonCopyable
51 {
52 friend std::ostream & operator<<( std::ostream & str, const Impl & obj );
53
54 public:
55 using set_type = std::unordered_set<detail::IdType>;
56 using map_type = std::unordered_map<detail::IdType, detail::IdType>;
57
59 {
61 {}
62 PostMortem( const sat::Solvable & solv_r )
63 : _ident( solv_r.ident() )
64 , _edition( solv_r.edition() )
65 , _arch( solv_r.arch() )
66 {}
67
71 };
72 using pmmap_type = std::unordered_map<detail::IdType, PostMortem>;
73
74 public:
76 : _trans( ::transaction_create( nullptr ) )
77 { memset( _trans, 0, sizeof(*_trans) ); }
78
79 Impl(const Impl &) = delete;
80 Impl(Impl &&) = delete;
81 Impl &operator=(const Impl &) = delete;
82 Impl &operator=(Impl &&) = delete;
83
84 Impl(LoadFromPoolType) : _watcher(myPool().serial()), _trans(nullptr) {
85 Queue decisionq;
86 for ( const PoolItem & pi : ResPool::instance() )
87 {
88 if ( ! pi.status().transacts() )
89 continue;
90 decisionq.push( pi.isSystem() ? -pi.id() : pi.id() );
91 }
92 Queue noobsq;
93 for ( const Solvable & solv : myPool().multiversionList() )
94 {
95 noobsq.push( SOLVER_NOOBSOLETES | SOLVER_SOLVABLE );
96 noobsq.push( solv.id() );
97 }
98 Map noobsmap;
99 ::solver_calculate_noobsmap( myPool().getPool(), noobsq, noobsmap );
100 _trans = ::transaction_create_decisionq( myPool().getPool(), decisionq, noobsmap );
101
102 // NOTE: package/product buddies share the same ResStatus
103 // so we also link the buddies stepStages. This assumes
104 // only one buddy is acting during commit (package is installed,
105 // but no extra operation for the product).
106 for_( it, _trans->steps.elements, _trans->steps.elements + _trans->steps.count )
107 {
108 sat::Solvable solv( *it );
109 // buddy list:
110 if ( ! solv.isKind<Package>() )
111 {
112 PoolItem pi( solv );
113 if ( pi.buddy() )
114 {
115 _linkMap[*it] = pi.buddy().id();
116 }
117 }
118 if ( solv.isSystem() )
119 {
120 // to delete list:
121 if ( stepType( solv ) == TRANSACTION_ERASE )
122 {
123 _systemErase.insert( *it );
124 }
125 // post mortem data
126 _pmMap[*it] = solv;
127 }
128 }
129 }
130
132 { ::transaction_free( _trans ); }
133
134 public:
135 bool valid() const
136 { return _watcher.isClean( myPool().serial() ); }
137
138 bool order()
139 {
140 if ( ! valid() )
141 return false;
142 if ( empty() )
143 return true;
144#if 0
145 // This is hwo we could implement out own order method.
146 // As ::transaction already groups by MediaNr, we don't
147 // need it for ORDER_BY_MEDIANR.
148 ::transaction_order( _trans, SOLVER_TRANSACTION_KEEP_ORDERDATA );
149 detail::IdType chosen = 0;
150 Queue choices;
151
152 while ( true )
153 {
154 int ret = transaction_order_add_choices( _trans, chosen, choices );
155 MIL << ret << ": " << chosen << ": " << choices << endl;
156 chosen = choices.pop_front(); // pick one out of choices
157 if ( ! chosen )
158 break;
159 }
160 return true;
161#endif
162 if ( !_ordered )
163 {
164 ::transaction_order( _trans, 0 );
165 _ordered = true;
166 }
167 return true;
168 }
169
170 bool empty() const
171 { return( _trans->steps.count == 0 ); }
172
173 size_t size() const
174 { return _trans->steps.count; }
175
177 { return const_iterator( self_r, _trans->steps.elements ); }
179 { return iterator( self_r, _trans->steps.elements ); }
180
182 { return const_iterator( self_r, _trans->steps.elements + _trans->steps.count ); }
184 { return iterator( self_r, _trans->steps.elements + _trans->steps.count ); }
185
186 const_iterator find(const RW_pointer<Transaction::Impl> & self_r, const sat::Solvable & solv_r ) const
187 { detail::IdType * it( _find( solv_r ) ); return it ? const_iterator( self_r, it ) : end( self_r ); }
189 { detail::IdType * it( _find( solv_r ) ); return it ? iterator( self_r, it ) : end( self_r ); }
190
191 public:
192 int installedResult( Queue & result_r ) const
193 { return ::transaction_installedresult( _trans, result_r ); }
194
196 { return _autoInstalled; }
197
198 void autoInstalled( const StringQueue & queue_r )
199 { _autoInstalled = queue_r; }
200
201 public:
202 StepType stepType( Solvable solv_r ) const
203 {
204 if ( ! solv_r )
205 {
206 // post mortem @System solvable
208 }
209
210 switch( ::transaction_type( _trans, solv_r.id(), SOLVER_TRANSACTION_RPM_ONLY ) )
211 {
212 case SOLVER_TRANSACTION_ERASE: return TRANSACTION_ERASE; break;
213 case SOLVER_TRANSACTION_INSTALL: return TRANSACTION_INSTALL; break;
214 case SOLVER_TRANSACTION_MULTIINSTALL: return TRANSACTION_MULTIINSTALL; break;
215 }
216 return TRANSACTION_IGNORE;
217 }
218
220 { return stepStage( resolve( solv_r ) ); }
221
222 void stepStage( Solvable solv_r, StepStage newval_r )
223 { stepStage( resolve( solv_r ), newval_r ); }
224
225 const PostMortem & pmdata( Solvable solv_r ) const
226 {
227 static PostMortem _none;
228 pmmap_type::const_iterator it( _pmMap.find( solv_r.id() ) );
229 return( it == _pmMap.end() ? _none : it->second );
230 }
231
232 private:
233 detail::IdType resolve( const Solvable & solv_r ) const
234 {
235 map_type::const_iterator res( _linkMap.find( solv_r.id() ) );
236 return( res == _linkMap.end() ? solv_r.id() : res->second );
237 }
238
239 bool isIn( const set_type & set_r, detail::IdType sid_r ) const
240 { return( set_r.find( sid_r ) != set_r.end() ); }
241
243 {
244 if ( isIn( _doneSet, sid_r ) )
245 return STEP_DONE;
246 if ( isIn( _errSet, sid_r ) )
247 return STEP_ERROR;
248 return STEP_TODO;
249 }
250
251 void stepStage( detail::IdType sid_r, StepStage newval_r )
252 {
253 StepStage stage( stepStage( sid_r ) );
254 if ( stage != newval_r )
255 {
256 // reset old stage
257 if ( stage != STEP_TODO )
258 {
259 (stage == STEP_DONE ? _doneSet : _errSet).erase( sid_r );
260 }
261 if ( newval_r != STEP_TODO )
262 {
263 (newval_r == STEP_DONE ? _doneSet : _errSet).insert( sid_r );
264 }
265 }
266 }
267
268 private:
269 detail::IdType * _find( const sat::Solvable & solv_r ) const
270 {
271 if ( solv_r && _trans->steps.elements )
272 {
273 for_( it, _trans->steps.elements, _trans->steps.elements + _trans->steps.count )
274 {
275 if ( *it == detail::IdType(solv_r.id()) )
276 return it;
277 }
278 }
279 return 0;
280 }
281
282 private:
284 mutable ::Transaction * _trans;
286 //
289 map_type _linkMap; // buddy map to adopt buddies StepResult
290 set_type _systemErase; // @System packages to be eased (otherse are TRANSACTION_IGNORE)
291 pmmap_type _pmMap; // Post mortem data of deleted @System solvables
292
293 StringQueue _autoInstalled; // ident strings of all packages that would be auto-installed after the transaction is run.
294
295 public:
298 {
299 static shared_ptr<Impl> _nullimpl( new Impl );
300 return _nullimpl;
301 }
302 };
303
305 inline std::ostream & operator<<( std::ostream & str, const Transaction::Impl & obj )
306 {
307 return str << "Transaction: " << obj.size() << " (" << (obj.valid()?"valid":"INVALID") << ")";
308 }
309
311 //
312 // CLASS NAME : Transaction
313 //
315
317 : _pimpl( Impl::nullimpl() )
318 {}
319
323
326
328 { return _pimpl->valid(); }
329
331 { return _pimpl->order(); }
332
334 { return _pimpl->empty(); }
335
336 size_t Transaction::size() const
337 { return _pimpl->size(); }
338
341
344
347
350
352 { return _pimpl->find( _pimpl, solv_r ); }
353
355 { return _pimpl->find( _pimpl, solv_r ); }
356
357 int Transaction::installedResult( Queue & result_r ) const
358 { return _pimpl->installedResult( result_r ); }
359
361 { return _pimpl->autoInstalled(); }
362
364 { _pimpl->autoInstalled( queue_r ); }
365
366 std::ostream & operator<<( std::ostream & str, const Transaction & obj )
367 { return str << *obj._pimpl; }
368
369 std::ostream & dumpOn( std::ostream & str, const Transaction & obj )
370 {
371 for_( it, obj.begin(), obj.end() )
372 {
373 str << *it << endl;
374 }
375 return str;
376 }
377
378 bool operator==( const Transaction & lhs, const Transaction & rhs )
379 { return lhs._pimpl == rhs._pimpl; }
380
382 //
383 // CLASS NAME : Transaction::Step
384 //
386
389
391 { return _pimpl->stepType( _solv ); }
392
395
397 { _pimpl->stepStage( _solv, val_r ); }
398
400 { return _solv ? _solv.ident() : _pimpl->pmdata(_solv )._ident; }
401
403 { return _solv ? _solv.edition() : _pimpl->pmdata(_solv )._edition; }
404
406 { return _solv ? _solv.arch() : _pimpl->pmdata(_solv )._arch; }
407
408 std::ostream & operator<<( std::ostream & str, const Transaction::Step & obj )
409 {
410 str << obj.stepType() << obj.stepStage() << " ";
411 if ( obj.satSolvable() )
412 str << PoolItem( obj.satSolvable() );
413 else
414 str << '[' << obj.ident() << '-' << obj.edition() << '.' << obj.arch() << ']';
415 return str;
416 }
417
418 std::ostream & operator<<( std::ostream & str, Transaction::StepType obj )
419 {
420 switch ( obj )
421 {
422 #define OUTS(E,S) case Transaction::E: return str << #S; break
423 OUTS( TRANSACTION_IGNORE, [ ] );
424 OUTS( TRANSACTION_ERASE, [-] );
427 #undef OUTS
428 }
429 return str << "[?]";
430 }
431
432 std::ostream & operator<<( std::ostream & str, Transaction::StepStage obj )
433 {
434 switch ( obj )
435 {
436 #define OUTS(E,S) case Transaction::E: return str << #S; break
437 OUTS( STEP_TODO, [__] );
438 OUTS( STEP_DONE, [OK] );
439 OUTS( STEP_ERROR, [**] );
440 #undef OUTS
441 }
442 return str << "[??]";
443 }
444
445 namespace detail
446 {
448 //
449 // CLASS NAME : Transaction::const_iterator/iterator
450 //
452
456
458 : Transaction_const_iterator::iterator_adaptor_( iter_r.base() )
459 , _pimpl( iter_r._pimpl )
460 {}
461
465
467 } // namespace detail
470 } // namespace sat
473} // namespace zypp
#define OUTS(V)
Architecture.
Definition Arch.h:37
Integral type with defined initial value when default constructed.
Edition represents [epoch:]version[-release]
Definition Edition.h:61
Access to the sat-pools string space.
Definition IdString.h:44
Package interface.
Definition Package.h:34
Combining sat::Solvable and ResStatus.
Definition PoolItem.h:51
sat::Solvable buddy() const
Return the buddy we share our status object with.
Definition PoolItem.cc:215
static ResPool instance()
Singleton ctor.
Definition ResPool.cc:38
Simple serial number watcher.
Libsolv (bit)Map wrapper.
Definition Map.h:34
Libsolv Id queue wrapper.
Definition Queue.h:36
value_type pop_front()
Pop and return the 1st Id from the queue or 0 if empty.
Definition Queue.cc:115
void push(value_type val_r)
Push a value to the end off the Queue.
Definition Queue.cc:103
A Solvable object within the sat Pool.
Definition Solvable.h:54
IdType id() const
Expert backdoor.
Definition Solvable.h:445
bool isSystem() const
Return whether this Solvable belongs to the system repo.
Definition Solvable.cc:374
bool isKind(const ResKind &kind_r) const
Test whether a Solvable is of a certain ResKind.
Definition Solvable.cc:303
A single step within a Transaction.
StepType stepType() const
Type of action to perform in this step.
StepStage stepStage() const
Step action result.
RW_pointer< Impl > _pimpl
Pointer to implementation.
Solvable satSolvable() const
Return the corresponding Solvable.
detail::Transaction_iterator iterator
const_iterator end() const
Iterator behind the last TransactionStep.
RW_pointer< Impl > _pimpl
Pointer to implementation.
int installedResult(Queue &result_r) const
Return all packages that would be installed after the transaction is run.
StringQueue autoInstalled() const
Return the ident strings of all packages that would be auto-installed after the transaction is run.
const_iterator begin() const
Iterator to the first TransactionStep.
detail::Transaction_const_iterator const_iterator
bool valid() const
Whether transaction actually contains data and also fits the current pools content.
Transaction()
Default ctor: empty transaction.
bool order()
Order transaction steps for commit.
friend std::ostream & operator<<(std::ostream &str, const Transaction &obj)
static constexpr LoadFromPoolType loadFromPool
Definition Transaction.h:82
const_iterator find(const sat::Solvable &solv_r) const
Return iterator pointing to solv_r or end.
StepType
Type of (rpm) action to perform in a Step.
Definition Transaction.h:63
@ TRANSACTION_MULTIINSTALL
[M] Install(multiversion) item (
Definition Transaction.h:67
@ TRANSACTION_INSTALL
[+] Install(update) item
Definition Transaction.h:66
@ TRANSACTION_IGNORE
[ ] Nothing (includes implicit deletes due to obsoletes and non-package actions)
Definition Transaction.h:64
@ TRANSACTION_ERASE
[-] Delete item
Definition Transaction.h:65
size_t size() const
Number of steps in transaction steps.
StepStage
Step action result.
Definition Transaction.h:72
@ STEP_DONE
[OK] success
Definition Transaction.h:74
@ STEP_TODO
[__] unprocessed
Definition Transaction.h:73
bool empty() const
Whether the transaction contains any steps.
RW_pointer< Transaction::Impl > _pimpl
Pointer to implementation.
String related utilities and Regular expression matching.
boost::noncopyable NonCopyable
Ensure derived classes cannot be copied.
Definition NonCopyable.h:26
int IdType
Generic Id type.
Definition PoolMember.h:104
Libsolv interface
std::ostream & operator<<(std::ostream &str, const FileConflicts &obj)
Queue StringQueue
Queue with String ids.
Definition Queue.h:28
std::ostream & dumpOn(std::ostream &str, const LocaleSupport &obj)
bool operator==(const Map &lhs, const Map &rhs)
Definition Map.cc:125
Easy-to use interface to the ZYPP dependency resolver.
Wrapper for const correct access via Smart pointer types.
Definition PtrTypes.h:293
PostMortem(const sat::Solvable &solv_r)
Transaction implementation.
void stepStage(Solvable solv_r, StepStage newval_r)
const_iterator find(const RW_pointer< Transaction::Impl > &self_r, const sat::Solvable &solv_r) const
std::unordered_map< detail::IdType, detail::IdType > map_type
void autoInstalled(const StringQueue &queue_r)
Impl & operator=(const Impl &)=delete
std::unordered_set< detail::IdType > set_type
int installedResult(Queue &result_r) const
iterator end(const RW_pointer< Transaction::Impl > &self_r)
SerialNumberWatcher _watcher
Impl(const Impl &)=delete
static shared_ptr< Impl > nullimpl()
Offer default Impl.
iterator find(const RW_pointer< Transaction::Impl > &self_r, const sat::Solvable &solv_r)
std::unordered_map< detail::IdType, PostMortem > pmmap_type
detail::IdType resolve(const Solvable &solv_r) const
friend std::ostream & operator<<(std::ostream &str, const Impl &obj)
DefaultIntegral< bool, false > _ordered
StepStage stepStage(Solvable solv_r) const
mutable::Transaction * _trans
bool isIn(const set_type &set_r, detail::IdType sid_r) const
detail::IdType * _find(const sat::Solvable &solv_r) const
const_iterator end(const RW_pointer< Transaction::Impl > &self_r) const
StepType stepType(Solvable solv_r) const
const PostMortem & pmdata(Solvable solv_r) const
iterator begin(const RW_pointer< Transaction::Impl > &self_r)
const_iterator begin(const RW_pointer< Transaction::Impl > &self_r) const
StringQueue autoInstalled() const
std::ostream & operator<<(std::ostream &str, const Transaction::Impl &obj)
Stream output.
Impl & operator=(Impl &&)=delete
StepStage stepStage(detail::IdType sid_r) const
void stepStage(detail::IdType sid_r, StepStage newval_r)
Backlink to the associated PoolImpl.
Definition PoolMember.h:89
static PoolImpl & myPool()
Definition PoolImpl.cc:185
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition Easy.h:27
#define MIL
Definition Logger.h:100