libzypp  15.28.6
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"
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 
48  , private base::NonCopyable
49  {
50  friend std::ostream & operator<<( std::ostream & str, const Impl & obj );
51 
52  public:
53  typedef std::unordered_set<detail::IdType> set_type;
54  typedef std::unordered_map<detail::IdType,detail::IdType> map_type;
55 
56  struct PostMortem
57  {
59  {}
60  PostMortem( const sat::Solvable & solv_r )
61  : _ident( solv_r.ident() )
62  , _edition( solv_r.edition() )
63  , _arch( solv_r.arch() )
64  {}
65 
69  };
70  typedef std::unordered_map<detail::IdType,PostMortem> pmmap_type;
71 
72  public:
73  Impl()
74  : _trans( ::transaction_create( nullptr ) )
75  { memset( _trans, 0, sizeof(*_trans) ); }
76 
78  : _watcher( myPool().serial() )
79  , _trans( nullptr )
80  {
81  Queue decisionq;
82  for ( const PoolItem & pi : ResPool::instance() )
83  {
84  if ( ! pi.status().transacts() )
85  continue;
86  decisionq.push( pi.isSystem() ? -pi.id() : pi.id() );
87  }
88  Queue noobsq;
89  for ( const Solvable & solv : myPool().multiversionList() )
90  {
91  noobsq.push( SOLVER_NOOBSOLETES | SOLVER_SOLVABLE );
92  noobsq.push( solv.id() );
93  }
94  Map noobsmap;
95  ::solver_calculate_noobsmap( myPool().getPool(), noobsq, noobsmap );
96  _trans = ::transaction_create_decisionq( myPool().getPool(), decisionq, noobsmap );
97 
98  // NOTE: package/product buddies share the same ResStatus
99  // so we also link the buddies stepStages. This assumes
100  // only one buddy is acting during commit (package is installed,
101  // but no extra operation for the product).
102  for_( it, _trans->steps.elements, _trans->steps.elements + _trans->steps.count )
103  {
104  sat::Solvable solv( *it );
105  // buddy list:
106  if ( ! solv.isKind<Package>() )
107  {
108  PoolItem pi( solv );
109  if ( pi.buddy() )
110  {
111  _linkMap[*it] = pi.buddy().id();
112  }
113  }
114  if ( solv.isSystem() )
115  {
116  // to delete list:
117  if ( stepType( solv ) == TRANSACTION_ERASE )
118  {
119  _systemErase.insert( *it );
120  }
121  // post mortem data
122  _pmMap[*it] = solv;
123  }
124  }
125  }
126 
128  { ::transaction_free( _trans ); }
129 
130  public:
131  bool valid() const
132  { return _watcher.isClean( myPool().serial() ); }
133 
134  bool order()
135  {
136  if ( ! valid() )
137  return false;
138  if ( empty() )
139  return true;
140 #if 0
141  // This is hwo we could implement out own order method.
142  // As ::transaction already groups by MediaNr, we don't
143  // need it for ORDER_BY_MEDIANR.
144  ::transaction_order( _trans, SOLVER_TRANSACTION_KEEP_ORDERDATA );
145  detail::IdType chosen = 0;
146  Queue choices;
147 
148  while ( true )
149  {
150  int ret = transaction_order_add_choices( _trans, chosen, choices );
151  MIL << ret << ": " << chosen << ": " << choices << endl;
152  chosen = choices.pop_front(); // pick one out of choices
153  if ( ! chosen )
154  break;
155  }
156  return true;
157 #endif
158  if ( !_ordered )
159  {
160  ::transaction_order( _trans, 0 );
161  _ordered = true;
162  }
163  return true;
164  }
165 
166  bool empty() const
167  { return( _trans->steps.count == 0 ); }
168 
169  size_t size() const
170  { return _trans->steps.count; }
171 
173  { return const_iterator( self_r, _trans->steps.elements ); }
175  { return iterator( self_r, _trans->steps.elements ); }
176 
178  { return const_iterator( self_r, _trans->steps.elements + _trans->steps.count ); }
180  { return iterator( self_r, _trans->steps.elements + _trans->steps.count ); }
181 
182  const_iterator find(const RW_pointer<Transaction::Impl> & self_r, const sat::Solvable & solv_r ) const
183  { detail::IdType * it( _find( solv_r ) ); return it ? const_iterator( self_r, it ) : end( self_r ); }
184  iterator find(const RW_pointer<Transaction::Impl> & self_r, const sat::Solvable & solv_r )
185  { detail::IdType * it( _find( solv_r ) ); return it ? iterator( self_r, it ) : end( self_r ); }
186 
187  public:
188  int installedResult( Queue & result_r ) const
189  { return ::transaction_installedresult( _trans, result_r ); }
190 
192  { return _autoInstalled; }
193 
194  void autoInstalled( const StringQueue & queue_r )
195  { _autoInstalled = queue_r; }
196 
197  public:
198  StepType stepType( Solvable solv_r ) const
199  {
200  if ( ! solv_r )
201  {
202  // post mortem @System solvable
203  return isIn( _systemErase, solv_r.id() ) ? TRANSACTION_ERASE : TRANSACTION_IGNORE;
204  }
205 
206  switch( ::transaction_type( _trans, solv_r.id(), SOLVER_TRANSACTION_RPM_ONLY ) )
207  {
208  case SOLVER_TRANSACTION_ERASE: return TRANSACTION_ERASE; break;
209  case SOLVER_TRANSACTION_INSTALL: return TRANSACTION_INSTALL; break;
210  case SOLVER_TRANSACTION_MULTIINSTALL: return TRANSACTION_MULTIINSTALL; break;
211  }
212  return TRANSACTION_IGNORE;
213  }
214 
215  StepStage stepStage( Solvable solv_r ) const
216  { return stepStage( resolve( solv_r ) ); }
217 
218  void stepStage( Solvable solv_r, StepStage newval_r )
219  { stepStage( resolve( solv_r ), newval_r ); }
220 
221  const PostMortem & pmdata( Solvable solv_r ) const
222  {
223  static PostMortem _none;
224  pmmap_type::const_iterator it( _pmMap.find( solv_r.id() ) );
225  return( it == _pmMap.end() ? _none : it->second );
226  }
227 
228  private:
229  detail::IdType resolve( const Solvable & solv_r ) const
230  {
231  map_type::const_iterator res( _linkMap.find( solv_r.id() ) );
232  return( res == _linkMap.end() ? solv_r.id() : res->second );
233  }
234 
235  bool isIn( const set_type & set_r, detail::IdType sid_r ) const
236  { return( set_r.find( sid_r ) != set_r.end() ); }
237 
239  {
240  if ( isIn( _doneSet, sid_r ) )
241  return STEP_DONE;
242  if ( isIn( _errSet, sid_r ) )
243  return STEP_ERROR;
244  return STEP_TODO;
245  }
246 
247  void stepStage( detail::IdType sid_r, StepStage newval_r )
248  {
249  StepStage stage( stepStage( sid_r ) );
250  if ( stage != newval_r )
251  {
252  // reset old stage
253  if ( stage != STEP_TODO )
254  {
255  (stage == STEP_DONE ? _doneSet : _errSet).erase( sid_r );
256  }
257  if ( newval_r != STEP_TODO )
258  {
259  (newval_r == STEP_DONE ? _doneSet : _errSet).insert( sid_r );
260  }
261  }
262  }
263 
264  private:
265  detail::IdType * _find( const sat::Solvable & solv_r ) const
266  {
267  if ( solv_r && _trans->steps.elements )
268  {
269  for_( it, _trans->steps.elements, _trans->steps.elements + _trans->steps.count )
270  {
271  if ( *it == detail::IdType(solv_r.id()) )
272  return it;
273  }
274  }
275  return 0;
276  }
277 
278  private:
280  mutable ::Transaction * _trans;
282  //
285  map_type _linkMap; // buddy map to adopt buddies StepResult
286  set_type _systemErase; // @System packages to be eased (otherse are TRANSACTION_IGNORE)
287  pmmap_type _pmMap; // Post mortem data of deleted @System solvables
288 
289  StringQueue _autoInstalled; // ident strings of all packages that would be auto-installed after the transaction is run.
290 
291  public:
293  static shared_ptr<Impl> nullimpl()
294  {
295  static shared_ptr<Impl> _nullimpl( new Impl );
296  return _nullimpl;
297  }
298  };
299 
301  inline std::ostream & operator<<( std::ostream & str, const Transaction::Impl & obj )
302  {
303  return str << "Transaction: " << obj.size() << " (" << (obj.valid()?"valid":"INVALID") << ")";
304  }
305 
307  //
308  // CLASS NAME : Transaction
309  //
311 
313  : _pimpl( Impl::nullimpl() )
314  {}
315 
317  : _pimpl( new Impl( loadFromPool ) )
318  {}
319 
321  {}
322 
323  bool Transaction::valid() const
324  { return _pimpl->valid(); }
325 
327  { return _pimpl->order(); }
328 
329  bool Transaction::empty() const
330  { return _pimpl->empty(); }
331 
332  size_t Transaction::size() const
333  { return _pimpl->size(); }
334 
336  { return _pimpl->begin( _pimpl ); }
337 
339  { return _pimpl->begin( _pimpl ); }
340 
342  { return _pimpl->end( _pimpl ); }
343 
345  { return _pimpl->end( _pimpl ); }
346 
348  { return _pimpl->find( _pimpl, solv_r ); }
349 
351  { return _pimpl->find( _pimpl, solv_r ); }
352 
353  int Transaction::installedResult( Queue & result_r ) const
354  { return _pimpl->installedResult( result_r ); }
355 
357  { return _pimpl->autoInstalled(); }
358 
359  void Transaction::autoInstalled( const StringQueue & queue_r )
360  { _pimpl->autoInstalled( queue_r ); }
361 
362  std::ostream & operator<<( std::ostream & str, const Transaction & obj )
363  { return str << *obj._pimpl; }
364 
365  std::ostream & dumpOn( std::ostream & str, const Transaction & obj )
366  {
367  for_( it, obj.begin(), obj.end() )
368  {
369  str << *it << endl;
370  }
371  return str;
372  }
373 
374  bool operator==( const Transaction & lhs, const Transaction & rhs )
375  { return lhs._pimpl == rhs._pimpl; }
376 
378  //
379  // CLASS NAME : Transaction::Step
380  //
382 
384  {}
385 
387  { return _pimpl->stepType( _solv ); }
388 
390  { return _pimpl->stepStage( _solv ); }
391 
393  { _pimpl->stepStage( _solv, val_r ); }
394 
396  { return _solv ? _solv.ident() : _pimpl->pmdata(_solv )._ident; }
397 
399  { return _solv ? _solv.edition() : _pimpl->pmdata(_solv )._edition; }
400 
402  { return _solv ? _solv.arch() : _pimpl->pmdata(_solv )._arch; }
403 
404  std::ostream & operator<<( std::ostream & str, const Transaction::Step & obj )
405  {
406  str << obj.stepType() << obj.stepStage() << " ";
407  if ( obj.satSolvable() )
408  str << PoolItem( obj.satSolvable() );
409  else
410  str << '[' << obj.ident() << '-' << obj.edition() << '.' << obj.arch() << ']';
411  return str;
412  }
413 
414  std::ostream & operator<<( std::ostream & str, Transaction::StepType obj )
415  {
416  switch ( obj )
417  {
418  #define OUTS(E,S) case Transaction::E: return str << #S; break
419  OUTS( TRANSACTION_IGNORE, [ ] );
420  OUTS( TRANSACTION_ERASE, [-] );
421  OUTS( TRANSACTION_INSTALL, [+] );
423  #undef OUTS
424  }
425  return str << "[?]";
426  }
427 
428  std::ostream & operator<<( std::ostream & str, Transaction::StepStage obj )
429  {
430  switch ( obj )
431  {
432  #define OUTS(E,S) case Transaction::E: return str << #S; break
433  OUTS( STEP_TODO, [__] );
434  OUTS( STEP_DONE, [OK] );
435  OUTS( STEP_ERROR, [**] );
436  #undef OUTS
437  }
438  return str << "[??]";
439  }
441  namespace detail
442  {
443  //
445  // CLASS NAME : Transaction::const_iterator/iterator
446  //
448 
449  Transaction_const_iterator::Transaction_const_iterator()
450  : Transaction_const_iterator::iterator_adaptor_( 0 )
451  {}
452 
454  : Transaction_const_iterator::iterator_adaptor_( iter_r.base() )
455  , _pimpl( iter_r._pimpl )
456  {}
457 
459  : Transaction_iterator::iterator_adaptor_( 0 )
460  {}
461 
463  } // namespace detail
466  } // namespace sat
469 } // namespace zypp
StringQueue autoInstalled() const
Return the ident strings of all packages that would be auto-installed after the transaction is run...
Definition: Transaction.cc:356
#define MIL
Definition: Logger.h:64
Simple serial number watcher.
Definition: SerialNumber.h:122
int IdType
Generic Id type.
Definition: PoolMember.h:130
A Solvable object within the sat Pool.
Definition: Solvable.h:53
[M] Install(multiversion) item (
Definition: Transaction.h:67
bool isIn(const set_type &set_r, detail::IdType sid_r) const
Definition: Transaction.cc:235
iterator find(const RW_pointer< Transaction::Impl > &self_r, const sat::Solvable &solv_r)
Definition: Transaction.cc:184
Architecture.
Definition: Arch.h:36
std::unordered_map< detail::IdType, detail::IdType > map_type
Definition: Transaction.cc:54
bool operator==(const Map &lhs, const Map &rhs)
Definition: Map.cc:123
std::ostream & operator<<(std::ostream &str, const FileConflicts &obj)
StepStage stepStage(Solvable solv_r) const
Definition: Transaction.cc:215
detail::IdType resolve(const Solvable &solv_r) const
Definition: Transaction.cc:229
const_iterator find(const sat::Solvable &solv_r) const
Return iterator pointing to solv_r or end.
Definition: Transaction.cc:347
bool isSystem() const
Return whether this Solvable belongs to the system repo.
Definition: Solvable.cc:361
StepStage
Step action result.
Definition: Transaction.h:71
Transaction()
Default ctor: empty transaction.
Definition: Transaction.cc:312
Access to the sat-pools string space.
Definition: IdString.h:41
Libsolv transaction wrapper.
Definition: Transaction.h:51
#define for_(IT, BEG, END)
Convenient for-loops using iterator.
Definition: Easy.h:27
Edition represents [epoch:]version[-release]
Definition: Edition.h:60
std::ostream & operator<<(std::ostream &str, const Transaction::Impl &obj)
Definition: Transaction.cc:301
std::unordered_set< detail::IdType > set_type
Definition: Transaction.cc:53
iterator begin(const RW_pointer< Transaction::Impl > &self_r)
Definition: Transaction.cc:174
const MultiversionList & multiversionList() const
Definition: PoolImpl.cc:592
StepType stepType(Solvable solv_r) const
Definition: Transaction.cc:198
const_iterator begin() const
Iterator to the first TransactionStep.
Definition: Transaction.cc:335
int installedResult(Queue &result_r) const
Return all packages that would be installed after the transaction is run.
Definition: Transaction.cc:353
StepStage stepStage() const
Step action result.
Definition: Transaction.cc:389
[ ] 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:247
StepType stepType() const
Type of action to perform in this step.
Definition: Transaction.cc:386
boost::noncopyable NonCopyable
Ensure derived classes cannot be copied.
Definition: NonCopyable.h:26
PostMortem(const sat::Solvable &solv_r)
Definition: Transaction.cc:60
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:114
RW_pointer< Impl > _pimpl
Pointer to implementation.
Definition: Transaction.h:184
mutable::Transaction * _trans
Definition: Transaction.cc:280
const_iterator end(const RW_pointer< Transaction::Impl > &self_r) const
Definition: Transaction.cc:177
friend std::ostream & operator<<(std::ostream &str, const Transaction &obj)
Definition: Transaction.cc:362
A single step within a Transaction.
Definition: Transaction.h:216
Package interface.
Definition: Package.h:32
SerialNumberWatcher _watcher
Definition: Transaction.cc:279
const PostMortem & pmdata(Solvable solv_r) const
Definition: Transaction.cc:221
detail::Transaction_const_iterator const_iterator
Definition: Transaction.h:116
void autoInstalled(const StringQueue &queue_r)
Definition: Transaction.cc:194
Transaction implementation.
Definition: Transaction.cc:47
bool order()
Order transaction steps for commit.
Definition: Transaction.cc:326
#define nullptr
Definition: Easy.h:54
bool isClean(unsigned serial_r) const
Return whether serial_r is still unchanged.
Definition: SerialNumber.h:152
bool valid() const
Whether transaction actually contains data and also fits the current pools content.
Definition: Transaction.cc:323
static PoolImpl & myPool()
Definition: PoolImpl.cc:167
const_iterator begin(const RW_pointer< Transaction::Impl > &self_r) const
Definition: Transaction.cc:172
std::ostream & dumpOn(std::ostream &str, const LocaleSupport &obj)
Solvable satSolvable() const
Return the corresponding Solvable.
Definition: Transaction.h:241
Libsolv Id queue wrapper.
Definition: Queue.h:34
StepType
Type of (rpm) action to perform in a Step.
Definition: Transaction.h:62
DefaultIntegral< bool, false > _ordered
Definition: Transaction.cc:281
size_t size() const
Number of steps in transaction steps.
Definition: Transaction.cc:332
sat::Solvable buddy() const
Return the buddy we share our status object with.
Definition: PoolItem.cc:206
detail::IdType * _find(const sat::Solvable &solv_r) const
Definition: Transaction.cc:265
const_iterator find(const RW_pointer< Transaction::Impl > &self_r, const sat::Solvable &solv_r) const
Definition: Transaction.cc:182
bool empty() const
Whether the transaction contains any steps.
Definition: Transaction.cc:329
const_iterator end() const
Iterator behind the last TransactionStep.
Definition: Transaction.cc:341
static shared_ptr< Impl > nullimpl()
Offer default Impl.
Definition: Transaction.cc:293
int erase(const Pathname &path)
Erase whatever happens to be located at path (file or directory).
Definition: PathInfo.cc:1005
Wrapper for const correct access via Smart pointer types.
Definition: PtrTypes.h:285
friend std::ostream & operator<<(std::ostream &str, const Impl &obj)
Combining sat::Solvable and ResStatus.
Definition: PoolItem.h:50
IdType id() const
Expert backdoor.
Definition: Solvable.h:374
#define OUTS(E, S)
Impl(LoadFromPoolType)
Definition: Transaction.cc:77
StepStage stepStage(detail::IdType sid_r) const
Definition: Transaction.cc:238
std::unordered_map< detail::IdType, PostMortem > pmmap_type
Definition: Transaction.cc:70
StringQueue autoInstalled() const
Definition: Transaction.cc:191
bool isKind(const ResKind &kind_r) const
Test whether a Solvable is of a certain ResKind.
Definition: Solvable.cc:290
iterator end(const RW_pointer< Transaction::Impl > &self_r)
Definition: Transaction.cc:179
Libsolv (bit)Map wrapper.
Definition: Map.h:33
void stepStage(Solvable solv_r, StepStage newval_r)
Definition: Transaction.cc:218
detail::Transaction_iterator iterator
Definition: Transaction.h:115
static ResPool instance()
Singleton ctor.
Definition: ResPool.cc:33
int installedResult(Queue &result_r) const
Definition: Transaction.cc:188