358bf44be517218d4b0f50332583791b487f00f7
[platform/upstream/libzypp.git] / zypp / sat / Transaction.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/sat/Transaction.h
10  */
11 extern "C"
12 {
13   struct _Transaction;
14 }
15 #ifndef ZYPP_SAT_TRANSACTION_H
16 #define ZYPP_SAT_TRANSACTION_H
17
18 #include <iosfwd>
19
20 #include "zypp/base/PtrTypes.h"
21 #include "zypp/base/Flags.h"
22 #include "zypp/base/SafeBool.h"
23 #include "zypp/base/Iterator.h"
24 #include "zypp/base/DefaultIntegral.h"
25
26 #include "zypp/sat/SolvIterMixin.h"
27 #include "zypp/sat/Solvable.h"
28
29 #include "zypp/PoolItem.h"
30
31 ///////////////////////////////////////////////////////////////////
32 namespace zypp
33 { /////////////////////////////////////////////////////////////////
34   ///////////////////////////////////////////////////////////////////
35   namespace sat
36   { /////////////////////////////////////////////////////////////////
37
38     namespace detail
39     {
40       /** Needs to be outside \ref Transaction in order to be usable in SolvIterMixin. */
41       class Transaction_iterator;
42       /** Needs to be outside \ref Transaction in order to be usable in SolvIterMixin. */
43       class Transaction_const_iterator;
44     }
45
46     /** Satsolver transaction wrapper.
47      * \note Note that Transaction is derived from \ref sat::SolvIterMixin which
48      *       makes PoolItem and Selectable iterators automatically available.
49      * \note Changing the \ref ResPool content (loading/unloading repositories)
50      *       invalidates all outstanding transaction data. \see \ref valid.
51      * \note.The transaction may inlude steps of type \ref TRANSACTION_IGNORE which
52      *       do not cause/require any specific action. To skip those informal steps
53      *       when iterating, use the \ref actionBegin /\ref actionEnd methods.
54      */
55     class Transaction : public SolvIterMixin<Transaction, detail::Transaction_const_iterator>
56                       , protected base::SafeBool<Transaction>
57     {
58       friend std::ostream & operator<<( std::ostream & str, const Transaction & obj );
59       friend std::ostream & dumpOn( std::ostream & str, const Transaction & obj );
60       friend bool operator==( const Transaction & lhs, const Transaction & rhs );
61
62      public:
63        /** Represents a single step within a \ref Transaction. */
64        class Step;
65
66        /** Type of (rpm) action to perform in a \ref Step. */
67        enum StepType
68        {
69          TRANSACTION_IGNORE             = 0x00, /**< [ ] Nothing (includes implicit deletes due to obsoletes and non-package actions) */
70          TRANSACTION_ERASE              = 0x10, /**< [-] Delete item */
71          TRANSACTION_INSTALL            = 0x20, /**< [+] Install(update) item */
72          TRANSACTION_MULTIINSTALL       = 0x30  /**< [M] Install(multiversion) item (\see \ref ZConfig::multiversion) */
73        };
74
75        /** \ref Step action result. */
76        enum StepStage
77        {
78          STEP_TODO      = (1 << 0),     /**< [__] unprocessed */
79          STEP_DONE      = (1 << 1),     /**< [OK] success */
80          STEP_ERROR     = (1 << 2),     /**< [**] error */
81        };
82
83        ZYPP_DECLARE_FLAGS(StepStages,StepStage);
84
85      public:
86         /** Default ctor: empty transaction. */
87         Transaction();
88
89         /** Ctor cloning a sat transaction. */
90         Transaction( ::_Transaction & trans_r );
91
92         /** Dtor */
93         ~Transaction();
94
95       public:
96         /** Whether transaction actually contains data and also fits the current pools content. */
97         bool valid() const;
98
99         /**  Validate object in a boolean context: valid */
100         using base::SafeBool<Transaction>::operator bool_type;
101
102         /** Order transaction steps for commit.
103          * It's cheap to call it for an aleready ordered \ref Transaction.
104          * This invalidates outstanding iterators. Returns whether
105          * \ref Transaction is \ref valid.
106          */
107         bool order();
108
109         /** Whether the transaction contains any steps. */
110         bool empty() const;
111
112         /** Number of steps in transaction steps. */
113         size_t size() const;
114
115         typedef detail::Transaction_iterator iterator;
116         typedef detail::Transaction_const_iterator const_iterator;
117
118         /** Iterator to the first \ref TransactionStep */
119         const_iterator begin() const;
120         /** \overload */
121         iterator begin();
122
123         /** Iterator behind the last \ref TransactionStep */
124         const_iterator end() const;
125         /** \overload */
126         iterator end();
127
128         /** Return iterator pointing to \a solv_r or \ref end. */
129         const_iterator find( const sat::Solvable & solv_r ) const;
130         iterator find( const sat::Solvable & solv_r );
131         /** \overload */
132         const_iterator find( const ResObject::constPtr & resolvable_r ) const;
133         iterator find( const ResObject::constPtr & resolvable_r );
134         /** \overload */
135         const_iterator find( const PoolItem & pi_r ) const;
136         iterator find( const PoolItem & pi_r );
137
138       public:
139         /** \name Iterate action steps (omit TRANSACTION_IGNORE steps).
140          *
141          * All these methods allow to pass an optional OR'd combination of
142          * \ref StepStages as filter. Per default all steps are processed/counted.
143          *
144          * \code
145          *    Transaction trans;
146          *    for_( it, trans.actionBegin(~sat::Transaction::STEP_DONE), trans.actionEnd() )
147          *    {
148          *       ... // process all steps not DONE (ERROR and TODO)
149          *    }
150          * \endcode
151          */
152         //@{
153         struct FilterAction;
154         typedef filter_iterator<FilterAction,const_iterator> action_iterator;
155
156         /** Whether the [filtered] transaction contains any steps . */
157         bool actionEmpty( StepStages filter_r = StepStages() ) const;
158
159         /** Number of steps in [filtered] transaction steps. */
160         size_t actionSize( StepStages filter_r = StepStages() ) const;
161
162         /** Pointer to the 1st action step in [filtered] transaction. */
163         action_iterator actionBegin( StepStages filter_r = StepStages() ) const;
164
165         /** Pointer behind the last action step in transaction. */
166         action_iterator actionEnd() const;
167
168         //@}
169
170       private:
171         friend base::SafeBool<Transaction>::operator bool_type() const;
172         /**  Validate object in a boolean context. */
173         bool boolTest() const
174         { return valid(); }
175       public:
176         /** Implementation  */
177         class Impl;
178       private:
179         /** Pointer to implementation */
180         RW_pointer<Impl> _pimpl;
181     };
182
183     ZYPP_DECLARE_OPERATORS_FOR_FLAGS(Transaction::StepStages);
184
185     /** \relates Transaction Stream output */
186     std::ostream & operator<<( std::ostream & str, const Transaction & obj );
187
188     /** \relates Transaction Verbose stream output */
189     std::ostream & dumpOn( std::ostream & str, const Transaction & obj );
190
191     /** \relates Transaction */
192     bool operator==( const Transaction & lhs, const Transaction & rhs );
193
194     /** \relates Transaction */
195     inline bool operator!=( const Transaction & lhs, const Transaction & rhs )
196     { return !( lhs == rhs ); }
197
198
199     /** A single step within a \ref Transaction.
200      *
201      * \note After commit, when the @System repo (rpm database) is reread, all
202      * @System solvables within the transaction are invalidated (they got deleted).
203      * Thats why we internally store the NVRA, so you can access \ref ident
204      * (\see \ref sat::Solvable::ident), \ref edition, \ref arch of a deleted package,
205      * even if the \ref satSolvable itself is meanwhile invalid.
206      *
207      * \see \ref Transaction.
208      */
209     class Transaction::Step
210     {
211       friend std::ostream & operator<<( std::ostream & str, const Step & obj );
212
213       public:
214         Step();
215         Step( const RW_pointer<Impl> & pimpl_r, detail::IdType id_r )
216           : _solv( id_r )
217           , _pimpl( pimpl_r )
218         {}
219
220       public:
221         /** Type of action to perform in this step. */
222         StepType stepType() const;
223
224         /** Step action result. */
225         StepStage stepStage() const;
226
227         /** Set step action result. */
228         void stepStage( StepStage val_r );
229
230         /** Return the corresponding \ref Solvable.
231          * Returns \ref Solvable::noSolvable if the item is meanwhile deleted and
232          * was removed from the pool. \see Post mortem acccess to @System solvables.
233          */
234         Solvable satSolvable() const
235         { return _solv; }
236
237         /** \name Post mortem acccess to @System solvables
238          * \code
239          *   Transaction::Step step;
240          *   if ( step.satSolvable() )
241          *     std::cout << step.satSolvable() << endl;
242          *   else
243          *     std::cout << step.ident() << endl; // deleted @System solvable
244          * \endcode
245          */
246         //@{
247         /** \see \ref sat::Solvable::ident. */
248         IdString ident() const;
249
250         /** \see \ref sat::Solvable::edition. */
251         Edition edition() const;
252
253         /** \see \ref sat::Solvable::arch. */
254         Arch arch() const;
255         //@}
256
257         /** Implicit conversion to \ref Solvable */
258         operator const Solvable &() const { return _solv; }
259         /** \overload nonconst */
260         operator Solvable &() { return _solv; }
261
262       private:
263         Solvable _solv;
264         /** Pointer to implementation */
265         RW_pointer<Impl> _pimpl;
266     };
267
268     /** \relates Transaction::Step Stream output */
269     std::ostream & operator<<( std::ostream & str, const Transaction::Step & obj );
270
271     /** \relates Transaction::StepType Stream output */
272     std::ostream & operator<<( std::ostream & str, Transaction::StepType obj );
273
274     /** \relates Transaction::StepStage Stream output */
275     std::ostream & operator<<( std::ostream & str, Transaction::StepStage obj );
276
277    ///////////////////////////////////////////////////////////////////
278     namespace detail
279     { /////////////////////////////////////////////////////////////////
280
281       /** \ref Transaction iterator.
282        */
283       class Transaction_iterator : public boost::iterator_adaptor<
284       Transaction_iterator              // Derived
285       , const detail::IdType *          // Base
286       , Transaction::Step               // Value
287       , boost::forward_traversal_tag    // CategoryOrTraversal
288       , Transaction::Step               // Reference
289       >
290       {
291         public:
292           Transaction_iterator();
293           Transaction_iterator( const RW_pointer<Transaction::Impl> & pimpl_r, base_type id_r )
294           : Transaction_iterator::iterator_adaptor_( id_r )
295           , _pimpl( pimpl_r )
296           {}
297
298         private:
299           friend class boost::iterator_core_access;
300
301           reference dereference() const
302           { return Transaction::Step( _pimpl, *base() ); }
303
304         private:
305           friend class Transaction_const_iterator;
306           /** Pointer to implementation */
307           RW_pointer<Transaction::Impl> _pimpl;
308       };
309
310      /** \ref Transaction const_iterator.
311        */
312       class Transaction_const_iterator : public boost::iterator_adaptor<
313       Transaction_const_iterator        // Derived
314       , const detail::IdType *          // Base
315       , const Transaction::Step         // Value
316       , boost::forward_traversal_tag    // CategoryOrTraversal
317       , const Transaction::Step         // Reference
318       >
319       {
320         public:
321           Transaction_const_iterator();
322           Transaction_const_iterator( const Transaction_iterator & iter_r );
323           Transaction_const_iterator( const RW_pointer<Transaction::Impl> & pimpl_r, base_type id_r )
324           : Transaction_const_iterator::iterator_adaptor_( id_r )
325           , _pimpl( pimpl_r )
326           {}
327
328         private:
329           friend class boost::iterator_core_access;
330
331           reference dereference() const
332           { return Transaction::Step( _pimpl, *base() ); }
333
334         private:
335           /** Pointer to implementation */
336           RW_pointer<Transaction::Impl> _pimpl;
337       };
338
339        /////////////////////////////////////////////////////////////////
340     } // namespace detail
341     ///////////////////////////////////////////////////////////////////
342
343     inline Transaction::const_iterator Transaction::find( const ResObject::constPtr & resolvable_r ) const
344     { return( resolvable_r ? find( resolvable_r->satSolvable() ) : end() ); }
345
346     inline Transaction::iterator Transaction::find( const ResObject::constPtr & resolvable_r )
347     { return( resolvable_r ? find( resolvable_r->satSolvable() ) : end() ); }
348
349     inline Transaction::const_iterator Transaction::find( const PoolItem & pi_r ) const
350     { return find( pi_r.satSolvable() ); }
351
352     inline Transaction::iterator Transaction::find( const PoolItem & pi_r )
353     { return find( pi_r.satSolvable() ); }
354
355
356     struct  Transaction::FilterAction
357     {
358       FilterAction() {}
359       FilterAction( StepStages filter_r ) : _filter( filter_r ) {}
360
361       bool operator()( const Transaction::Step & step_r ) const
362       {
363         if ( step_r.stepType() == Transaction::TRANSACTION_IGNORE )
364           return false; // no action
365         return !_filter || _filter.testFlag( step_r.stepStage() );
366       }
367
368       StepStages _filter;
369     };
370
371     inline Transaction::action_iterator Transaction::actionBegin( StepStages filter_r ) const
372     { return make_filter_begin( FilterAction( filter_r ), *this ); }
373
374     inline Transaction::action_iterator Transaction::actionEnd() const
375     { return make_filter_end( FilterAction(), *this ); }
376
377     inline bool Transaction::actionEmpty( StepStages filter_r ) const
378     { return( actionBegin( filter_r ) == actionEnd() ); }
379
380     inline size_t Transaction::actionSize( StepStages filter_r ) const
381     {
382       size_t cnt = 0;
383       for_( it, actionBegin( filter_r ), actionEnd() )
384         ++cnt;
385       return cnt;
386     }
387
388      /////////////////////////////////////////////////////////////////
389   } // namespace sat
390   ///////////////////////////////////////////////////////////////////
391   /////////////////////////////////////////////////////////////////
392 } // namespace zypp
393 ///////////////////////////////////////////////////////////////////
394 #endif // ZYPP_SAT_TRANSACTION_H