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