libzypp  17.36.3
Transaction.cc
Go to the documentation of this file.
1 /*---------------------------------------------------------------------\
2 | ____ _ __ __ ___ |
3 | |__ / \ / / . \ . \ |
4 | / / \ V /| _/ _/ |
5 | / /__ | | | | | | |
6 | /_____||_| |_| |_| |
7 | |
8 \---------------------------------------------------------------------*/
11 extern "C"
12 {
13 #include <solv/transaction.h>
14 #include <solv/solver.h>
15 }
16 #include <iostream>
17 #include <zypp/base/LogTools.h>
18 #include <zypp/base/SerialNumber.h>
19 #include <zypp-core/base/DefaultIntegral>
20 #include <zypp/base/NonCopyable.h>
21 #include <zypp/base/Hash.h>
22 
24 #include <zypp/sat/Transaction.h>
25 #include <zypp/sat/Solvable.h>
26 #include <zypp/sat/Queue.h>
27 #include <zypp/sat/Map.h>
28 #include <zypp/ResPool.h>
29 
30 using std::endl;
31 
33 namespace zypp
34 {
35  namespace sat
37  {
38 
39  constexpr Transaction::LoadFromPoolType Transaction::loadFromPool;
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 
58  struct PostMortem
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:
75  Impl()
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 ); }
188  iterator find(const RW_pointer<Transaction::Impl> & self_r, const sat::Solvable & solv_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
207  return isIn( _systemErase, solv_r.id() ) ? TRANSACTION_ERASE : TRANSACTION_IGNORE;
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 
219  StepStage stepStage( Solvable solv_r ) const
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:
297  static shared_ptr<Impl> nullimpl()
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 
321  : _pimpl( new Impl( loadFromPool ) )
322  {}
323 
325  {}
326 
327  bool Transaction::valid() const
328  { return _pimpl->valid(); }
329 
331  { return _pimpl->order(); }
332 
333  bool Transaction::empty() const
334  { return _pimpl->empty(); }
335 
336  size_t Transaction::size() const
337  { return _pimpl->size(); }
338 
340  { return _pimpl->begin( _pimpl ); }
341 
343  { return _pimpl->begin( _pimpl ); }
344 
346  { return _pimpl->end( _pimpl ); }
347 
349  { return _pimpl->end( _pimpl ); }
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 
363  void Transaction::autoInstalled( const StringQueue & queue_r )
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 
388  {}
389 
391  { return _pimpl->stepType( _solv ); }
392 
394  { return _pimpl->stepStage( _solv ); }
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, [-] );
425  OUTS( TRANSACTION_INSTALL, [+] );
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  }
445  namespace detail
446  {
447  //
449  // CLASS NAME : Transaction::const_iterator/iterator
450  //
452 
453  Transaction_const_iterator::Transaction_const_iterator()
454  : Transaction_const_iterator::iterator_adaptor_( 0 )
455  {}
456 
458  : Transaction_const_iterator::iterator_adaptor_( iter_r.base() )
459  , _pimpl( iter_r._pimpl )
460  {}
461 
463  : Transaction_iterator::iterator_adaptor_( 0 )
464  {}
465 
467  } // namespace detail
470  } // namespace sat
473 } // namespace zypp
int installedResult(Queue &result_r) const
Definition: Transaction.cc:192
#define MIL
Definition: Logger.h:100
Simple serial number watcher.
Definition: SerialNumber.h:122
A Solvable object within the sat Pool.
Definition: Solvable.h:53
IdType id() const
Expert backdoor.
Definition: Solvable.h:444
[M] Install(multiversion) item (
Definition: Transaction.h:67
Solvable satSolvable() const
Return the corresponding Solvable.
Definition: Transaction.h:243
const_iterator find(const sat::Solvable &solv_r) const
Return iterator pointing to solv_r or end.
Definition: Transaction.cc:351
iterator find(const RW_pointer< Transaction::Impl > &self_r, const sat::Solvable &solv_r)
Definition: Transaction.cc:188
std::unordered_map< detail::IdType, detail::IdType > map_type
Definition: Transaction.cc:56
Architecture.
Definition: Arch.h:36
bool operator==(const Map &lhs, const Map &rhs)
Definition: Map.cc:125
const MultiversionList & multiversionList() const
Definition: PoolImpl.cc:643
size_t size() const
Number of steps in transaction steps.
Definition: Transaction.cc:336
StepStage stepStage() const
Step action result.
Definition: Transaction.cc:393
std::ostream & operator<<(std::ostream &str, const FileConflicts &obj)
StepType stepType(Solvable solv_r) const
Definition: Transaction.cc:202
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition: Easy.h:27
String related utilities and Regular expression matching.
StepStage
Step action result.
Definition: Transaction.h:71
bool valid() const
Whether transaction actually contains data and also fits the current pools content.
Definition: Transaction.cc:327
Transaction()
Default ctor: empty transaction.
Definition: Transaction.cc:316
bool isKind(const ResKind &kind_r) const
Test whether a Solvable is of a certain ResKind.
Definition: Solvable.cc:303
sat::Solvable buddy() const
Return the buddy we share our status object with.
Definition: PoolItem.cc:215
const_iterator find(const RW_pointer< Transaction::Impl > &self_r, const sat::Solvable &solv_r) const
Definition: Transaction.cc:186
int IdType
Generic Id type.
Definition: PoolMember.h:104
Access to the sat-pools string space.
Definition: IdString.h:43
Libsolv transaction wrapper.
Definition: Transaction.h:51
Edition represents [epoch:]version[-release]
Definition: Edition.h:60
std::ostream & operator<<(std::ostream &str, const Transaction::Impl &obj)
Definition: Transaction.cc:305
const_iterator end() const
Iterator behind the last TransactionStep.
Definition: Transaction.cc:345
iterator begin(const RW_pointer< Transaction::Impl > &self_r)
Definition: Transaction.cc:178
const_iterator end(const RW_pointer< Transaction::Impl > &self_r) const
Definition: Transaction.cc:181
StepStage stepStage(detail::IdType sid_r) const
Definition: Transaction.cc:242
std::unordered_map< detail::IdType, PostMortem > pmmap_type
Definition: Transaction.cc:72
StringQueue autoInstalled() const
Return the ident strings of all packages that would be auto-installed after the transaction is run...
Definition: Transaction.cc:360
[ ] Nothing (includes implicit deletes due to obsoletes and non-package actions)
Definition: Transaction.h:64
void push(value_type val_r)
Push a value to the end off the Queue.
Definition: Queue.cc:103
void stepStage(detail::IdType sid_r, StepStage newval_r)
Definition: Transaction.cc:251
PostMortem(const sat::Solvable &solv_r)
Definition: Transaction.cc:62
value_type pop_front()
Pop and return the 1st Id from the queue or 0 if empty.
Definition: Queue.cc:115
Backlink to the associated PoolImpl.
Definition: PoolMember.h:88
RW_pointer< Impl > _pimpl
Pointer to implementation.
Definition: Transaction.h:186
mutable ::Transaction * _trans
Definition: Transaction.cc:284
friend std::ostream & operator<<(std::ostream &str, const Transaction &obj)
Definition: Transaction.cc:366
A single step within a Transaction.
Definition: Transaction.h:218
Package interface.
Definition: Package.h:33
SerialNumberWatcher _watcher
Definition: Transaction.cc:283
detail::IdType * _find(const sat::Solvable &solv_r) const
Definition: Transaction.cc:269
void autoInstalled(const StringQueue &queue_r)
Definition: Transaction.cc:198
Transaction implementation.
Definition: Transaction.cc:49
int installedResult(Queue &result_r) const
Return all packages that would be installed after the transaction is run.
Definition: Transaction.cc:357
bool order()
Order transaction steps for commit.
Definition: Transaction.cc:330
static PoolImpl & myPool()
Definition: PoolImpl.cc:184
std::ostream & dumpOn(std::ostream &str, const LocaleSupport &obj)
bool isIn(const set_type &set_r, detail::IdType sid_r) const
Definition: Transaction.cc:239
const_iterator begin(const RW_pointer< Transaction::Impl > &self_r) const
Definition: Transaction.cc:176
bool isSystem() const
Return whether this Solvable belongs to the system repo.
Definition: Solvable.cc:374
detail::Transaction_const_iterator const_iterator
Definition: Transaction.h:116
static constexpr LoadFromPoolType loadFromPool
Definition: Transaction.h:82
Libsolv Id queue wrapper.
Definition: Queue.h:35
StepType
Type of (rpm) action to perform in a Step.
Definition: Transaction.h:62
DefaultIntegral< bool, false > _ordered
Definition: Transaction.cc:285
const PostMortem & pmdata(Solvable solv_r) const
Definition: Transaction.cc:225
StringQueue autoInstalled() const
Definition: Transaction.cc:195
const_iterator begin() const
Iterator to the first TransactionStep.
Definition: Transaction.cc:339
StepType stepType() const
Type of action to perform in this step.
Definition: Transaction.cc:390
static shared_ptr< Impl > nullimpl()
Offer default Impl.
Definition: Transaction.cc:297
bool empty() const
Whether the transaction contains any steps.
Definition: Transaction.cc:333
int erase(const Pathname &path)
Erase whatever happens to be located at path (file or directory).
Definition: PathInfo.cc:1078
bool isClean(unsigned serial_r) const
Return whether serial_r is still unchanged.
Definition: SerialNumber.h:152
detail::IdType resolve(const Solvable &solv_r) const
Definition: Transaction.cc:233
Wrapper for const correct access via Smart pointer types.
Definition: PtrTypes.h:292
friend std::ostream & operator<<(std::ostream &str, const Impl &obj)
StepStage stepStage(Solvable solv_r) const
Definition: Transaction.cc:219
Combining sat::Solvable and ResStatus.
Definition: PoolItem.h:50
#define OUTS(E, S)
Impl(LoadFromPoolType)
Definition: Transaction.cc:84
Impl & operator=(const Impl &)=delete
iterator end(const RW_pointer< Transaction::Impl > &self_r)
Definition: Transaction.cc:183
Libsolv (bit)Map wrapper.
Definition: Map.h:33
Easy-to use interface to the ZYPP dependency resolver.
Definition: Application.cc:19
detail::Transaction_iterator iterator
Definition: Transaction.h:115
std::unordered_set< detail::IdType > set_type
Definition: Transaction.cc:55
void stepStage(Solvable solv_r, StepStage newval_r)
Definition: Transaction.cc:222
boost::noncopyable NonCopyable
Ensure derived classes cannot be copied.
Definition: NonCopyable.h:26
static ResPool instance()
Singleton ctor.
Definition: ResPool.cc:38