ba340daa272b5812247224c0fa79fcfa4787fc32
[platform/upstream/libzypp.git] / zypp / ResStatus.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file       zypp/ResStatus.h
10  *
11 */
12 #ifndef ZYPP_RESSTATUS_H
13 #define ZYPP_RESSTATUS_H
14
15 #include <iosfwd>
16
17 #include "zypp/Bit.h"
18
19 ///////////////////////////////////////////////////////////////////
20 namespace zypp
21 { /////////////////////////////////////////////////////////////////
22
23   ///////////////////////////////////////////////////////////////////
24   //
25   //    CLASS NAME : ResStatus
26   //
27   /** Status bitfield.
28    *
29    * \li \c StateField Whether the resolvable is or uninstalled (available).
30    * \li \c TransactField Wheter to transact this resolvable
31    *        (delete if installed install if uninstalled).
32    *        In case the resolvable is locked, only USER may modify the
33    *        transact bit.
34    * \li \c TransactByField Who triggered the transaction. Transaction
35    *        bit may be reset by higer levels only.
36    * \li \c TransactDetailField Reason why the Resolvable transacts.
37    *        Splitted into \c InstallDetailValue and \c RemoveDetailValue
38    *        dependent on the kind of transaction.
39    * \li \c WeakField The solvable will be recommended/suggested by 
40    *        a to be installed/deleted solvable.
41    *
42   */
43   class ResStatus
44   {
45     friend std::ostream & operator<<( std::ostream & str, const ResStatus & obj );
46     friend bool operator==( const ResStatus & lhs, const ResStatus & rhs );
47
48   public:
49     /** \name BitField range definitions.
50      *
51      * \note Enlarge FieldType if more bit's needed. It's not yet
52      * checked by the compiler.
53      */
54     //@{
55     typedef uint16_t FieldType;
56     typedef bit::BitField<FieldType> BitFieldType;
57     // Bit Ranges within FieldType defined by 1st bit and size:
58     typedef bit::Range<FieldType,0,                          1> StateField;
59     typedef bit::Range<FieldType,StateField::end,            2> TransactField;
60     typedef bit::Range<FieldType,TransactField::end,         2> TransactByField;
61     typedef bit::Range<FieldType,TransactByField::end,       2> TransactDetailField;
62     typedef bit::Range<FieldType,TransactDetailField::end,   1> SolverStateField;
63     typedef bit::Range<FieldType,SolverStateField::end,      1> LicenceConfirmedField;
64     typedef bit::Range<FieldType,LicenceConfirmedField::end, 2> WeakField;      
65     // enlarge FieldType if more bit's needed. It's not yet
66     // checked by the compiler.
67     //@}
68   public:
69
70     /** \name Status values.
71      *
72      * Each enum corresponds to a BitField range.
73      * \note Take care that enumerator values actually fit into
74      * the corresponding field. It's not yet checked by the compiler.
75      */
76     //@{
77     enum StateValue
78       {
79         UNINSTALLED = bit::RangeValue<StateField,0>::value,
80         INSTALLED   = bit::RangeValue<StateField,1>::value
81       };
82     enum TransactValue
83       {
84         KEEP_STATE = bit::RangeValue<TransactField,0>::value,
85         LOCKED     = bit::RangeValue<TransactField,1>::value, // locked, must not transact
86         TRANSACT   = bit::RangeValue<TransactField,2>::value  // transact according to state
87       };
88     enum TransactByValue
89       {
90         SOLVER    = bit::RangeValue<TransactByField,0>::value,
91         APPL_LOW  = bit::RangeValue<TransactByField,1>::value,
92         APPL_HIGH = bit::RangeValue<TransactByField,2>::value,
93         USER      = bit::RangeValue<TransactByField,3>::value
94       };
95
96     enum DetailValue
97       {
98         /** Detail for no transact, i.e. reset any Install/RemoveDetailValue. */
99         NO_DETAIL = bit::RangeValue<TransactDetailField,0>::value,
100       };
101
102     enum InstallDetailValue
103       {
104         EXPLICIT_INSTALL = bit::RangeValue<TransactDetailField,0>::value,
105         SOFT_INSTALL     = bit::RangeValue<TransactDetailField,1>::value
106       };
107     enum RemoveDetailValue
108       {
109         EXPLICIT_REMOVE = bit::RangeValue<TransactDetailField,0>::value,
110         SOFT_REMOVE     = bit::RangeValue<TransactDetailField,1>::value,
111         DUE_TO_OBSOLETE = bit::RangeValue<TransactDetailField,2>::value,
112         DUE_TO_UPGRADE  = bit::RangeValue<TransactDetailField,3>::value
113       };
114     enum SolverStateValue
115       {
116         NORMAL     = bit::RangeValue<SolverStateField,0>::value, // default, notthing special
117         SEEN       = bit::RangeValue<SolverStateField,1>::value, // already seen during ResolverUpgrade
118       };
119
120     enum LicenceConfirmedValue
121       {
122         LICENCE_UNCONFIRMED = bit::RangeValue<LicenceConfirmedField,0>::value,
123         LICENCE_CONFIRMED   = bit::RangeValue<LicenceConfirmedField,1>::value
124       };
125       
126     enum WeakValue
127       {
128         NO_WEAK                 = bit::RangeValue<WeakField,0>::value,
129         SUGGESTED               = bit::RangeValue<WeakField,1>::value,
130         RECOMMENDED             = bit::RangeValue<WeakField,2>::value,
131         SUGGESTED_AND_RECOMMENDED = bit::RangeValue<WeakField,3>::value
132       };      
133     //@}
134
135   public:
136
137     /** Default ctor. */
138     ResStatus();
139
140     /** Ctor setting the initial . */
141     ResStatus( bool isInstalled_r );
142
143     /** Dtor. */
144     ~ResStatus();
145
146     /** Debug helper returning the bitfield.
147      * It's save to expose the bitfield, as it can't be used to
148      * recreate a ResStatus. So it is not possible to bypass
149      * transition rules.
150     */
151     BitFieldType bitfield() const
152     { return _bitfield; }
153
154   public:
155
156     bool isLicenceConfirmed() const
157     { return fieldValueIs<LicenceConfirmedField>( LICENCE_CONFIRMED ); }
158
159     void setLicenceConfirmed( bool toVal_r = true )
160     { fieldValueAssign<LicenceConfirmedField>( toVal_r ? LICENCE_CONFIRMED : LICENCE_UNCONFIRMED ); }
161
162   public:
163
164     bool isRecommended() const
165     { return fieldValueIs<WeakField>( RECOMMENDED ); }
166
167     bool isSuggested() const
168     { return fieldValueIs<WeakField>( SUGGESTED ); }
169
170     void setRecommended( bool toVal_r = true )
171     { if (isSuggested())
172         fieldValueAssign<WeakField>( toVal_r ? SUGGESTED_AND_RECOMMENDED : SUGGESTED );
173     else
174         fieldValueAssign<WeakField>( toVal_r ? RECOMMENDED : NO_WEAK );
175     }
176
177     void setSuggested( bool toVal_r = true ) 
178     { if (isRecommended())
179         fieldValueAssign<WeakField>( toVal_r ? SUGGESTED_AND_RECOMMENDED : RECOMMENDED );
180     else
181         fieldValueAssign<WeakField>( toVal_r ? SUGGESTED : NO_WEAK );
182     }
183
184   public:
185     // These two are IMMUTABLE!
186
187     bool isInstalled() const
188     { return fieldValueIs<StateField>( INSTALLED ); }
189
190     bool isUninstalled() const
191     { return fieldValueIs<StateField>( UNINSTALLED ); }
192
193   public:
194
195     bool staysInstalled() const
196     { return isInstalled() && !transacts(); }
197
198     bool wasInstalled() const { return staysInstalled(); }      //for old status
199
200     bool isToBeInstalled() const
201     { return isUninstalled() && transacts(); }
202
203     bool staysUninstalled() const
204     { return isUninstalled() && !transacts(); }
205
206     bool wasUninstalled() const { return staysUninstalled(); }  // for old status
207
208     bool isToBeUninstalled() const
209     { return isInstalled() && transacts(); }
210
211     bool isLocked() const
212     { return fieldValueIs<TransactField>( LOCKED ); }
213
214     bool isKept() const
215     { return fieldValueIs<TransactField>( KEEP_STATE ); }      
216
217     bool transacts() const
218     { return fieldValueIs<TransactField>( TRANSACT ); }
219
220     TransactValue getTransactValue() const
221     { return (TransactValue)_bitfield.value<TransactField>(); }
222
223     bool isBySolver() const
224     { return fieldValueIs<TransactByField>( SOLVER ); }
225
226     bool isByApplLow() const
227     { return fieldValueIs<TransactByField>( APPL_LOW ); }
228
229     bool isByApplHigh() const
230     { return fieldValueIs<TransactByField>( APPL_HIGH ); }
231
232     bool isByUser() const
233     { return fieldValueIs<TransactByField>( USER ); }
234
235     TransactByValue getTransactByValue() const
236     { return (TransactByValue)_bitfield.value<TransactByField>(); }
237
238       
239     bool isToBeUninstalledDueToObsolete () const
240     { return isToBeUninstalled() && fieldValueIs<TransactDetailField>( DUE_TO_OBSOLETE ); }
241
242     bool isToBeUninstalledDueToUpgrade() const
243     { return isToBeUninstalled() && fieldValueIs<TransactDetailField>( DUE_TO_UPGRADE ); }
244
245     bool isToBeInstalledSoft () const
246     { return isToBeInstalled() && fieldValueIs<TransactDetailField>( SOFT_INSTALL ); }
247
248     bool isToBeInstalledNotSoft () const
249     { return isToBeInstalled() && !fieldValueIs<TransactDetailField>( SOFT_INSTALL ); }
250
251     bool isToBeUninstalledSoft () const
252     { return isToBeUninstalled() && fieldValueIs<TransactDetailField>( SOFT_REMOVE ); }
253
254   public:
255
256     //------------------------------------------------------------------------
257     // get/set functions, returnig \c true if requested status change
258     // was successfull (i.e. leading to the desired transaction).
259     // If a lower level (e.g.SOLVER) wants to transact, but it's
260     // already set by a higher level, \c true should be returned.
261     // Removing a higher levels transaction bit should fail.
262     //
263     // The may functions checks only, if the action would return true
264     // if it is called.
265
266     /** Set TransactValue.
267      * Convenience to set TransactValue from enum.
268      */
269     bool setTransactValue( TransactValue newVal_r, TransactByValue causer_r )
270     {
271       switch ( newVal_r )
272         {
273         case KEEP_STATE:
274           return setTransact( false, causer_r );
275           break;
276         case LOCKED:
277           return setLock( true, causer_r );
278           break;
279         case TRANSACT:
280           return setTransact( true, causer_r );
281           break;
282         }
283       return false;
284     }
285
286     bool maySetTransactValue( TransactValue newVal_r, TransactByValue causer_r )
287     {
288         bit::BitField<FieldType> savBitfield = _bitfield;
289         bool ret = setTransactValue( newVal_r, causer_r );
290         _bitfield = savBitfield;
291         return ret;
292     }
293
294     /** Apply a lock (prevent transaction).
295      * Currently by USER only, but who knows... Set LOCKED
296      * from KEEP_STATE to be shure all transaction details
297      * were reset properly.
298     */
299     bool setLock( bool toLock_r, TransactByValue causer_r )
300     {
301       if ( toLock_r == isLocked() )
302         {
303           // we're already in the desired state, but in case of
304           // LOCKED, remember a superior causer.
305           if ( isLocked() && isLessThan<TransactByField>( causer_r ) )
306             fieldValueAssign<TransactByField>( causer_r );
307            return true;
308         }
309       // Here: Lock status is to be changed:
310       if ( causer_r != USER )
311         return false;
312       // Setting no transact removes an existing lock,
313       // or brings this into KEEP_STATE, and we apply the lock.
314       if ( ! setTransact( false, causer_r ) )
315         return false;
316       if ( toLock_r ) {
317           fieldValueAssign<TransactField>( LOCKED );
318           fieldValueAssign<TransactByField>( causer_r );
319       } else {
320           fieldValueAssign<TransactField>( KEEP_STATE );
321           fieldValueAssign<TransactByField>( SOLVER ); // reset to lowest causer
322                                                        // in order to distinguish from keep_state_by_user
323       }
324       return true;
325     }
326
327     bool maySetLock( bool to_r, TransactByValue causer_r )
328     {
329         bit::BitField<FieldType> savBitfield = _bitfield;
330         bool ret = setLock( to_r, causer_r );
331         _bitfield = savBitfield;
332         return ret;
333     }
334
335     /** Toggle between TRANSACT and KEEP_STATE.
336      * LOCKED state means KEEP_STATE. But in contrary to KEEP_STATE,
337      * LOCKED state is immutable for \a causer_r less than TransactByValue.
338      * KEEP_STATE may be canged by any \a causer_r.
339     */
340     bool setTransact( bool toTansact_r, TransactByValue causer_r )
341     {
342       if ( toTansact_r == transacts() )
343         {
344           // we're already in the desired state, but in case of
345           // TRANSACT, remember a superior causer.
346           if ( transacts() && isLessThan<TransactByField>( causer_r ) )
347             {
348               fieldValueAssign<TransactByField>( causer_r );
349               // ??? adapt TransactDetailField ?
350             }
351           return true;
352         }
353       // Here: transact status is to be changed:
354       if (    ! fieldValueIs<TransactField>( KEEP_STATE )
355            && isGreaterThan<TransactByField>( causer_r ) )
356         return false;
357
358       if ( toTansact_r )
359         {
360           fieldValueAssign<TransactField>( TRANSACT );
361           // ??? adapt TransactDetailField ?
362         }
363       else
364         {
365           fieldValueAssign<TransactField>( KEEP_STATE );
366           fieldValueAssign<TransactDetailField>( NO_DETAIL );
367         }
368       fieldValueAssign<TransactByField>( causer_r );
369       return true;
370     }
371
372     bool maySetTransact( bool val_r, TransactByValue causer )
373     {
374         bit::BitField<FieldType> savBitfield = _bitfield;
375         bool ret = setTransact (val_r, causer);
376         _bitfield = savBitfield;
377         return ret;
378     }
379
380     /** */
381     bool setSoftLock( TransactByValue causer_r )
382     {
383       if ( ! setTransact( false, causer_r ) )
384         return false;
385       if ( fieldValueIs<TransactField>( KEEP_STATE )
386            && isLessThan<TransactByField>( causer_r ) )
387         fieldValueAssign<TransactByField>( causer_r );
388       return true;
389     }
390
391     /** Not the same as setTransact( false ).
392      */
393     bool resetTransact( TransactByValue causer_r )
394     {
395       if ( ! setTransact( false, causer_r ) )
396         return false;
397       if ( fieldValueIs<TransactField>( KEEP_STATE ) )
398         fieldValueAssign<TransactByField>( SOLVER );
399       return true;
400     }
401
402     /** Soft toggle between TRANSACT and KEEP_STATE.
403      * Similar to setTransact, but leaving KEEP_STATE also requires
404      * a superior \a causerLimit_r. So this is a kind of soft lock.
405      * \code
406      * // SOLVER wants to set TRANSACT, iff KEEP_STATE is
407      * // not superior to APPL_LOW.
408      * setSoftTransact( true, SOLVER, APPL_LOW );
409      * \endcode
410     */
411     bool setSoftTransact( bool toTansact_r, TransactByValue causer_r,
412                           TransactByValue causerLimit_r )
413     {
414       if ( fieldValueIs<TransactField>( KEEP_STATE )
415            && toTansact_r != transacts()
416            && isGreaterThan<TransactByField>( causerLimit_r ) )
417         {
418           // any transact status change requires a superior causer.
419           return false;
420         }
421       return setTransact( toTansact_r, causer_r );
422     }
423
424     bool setSoftTransact( bool toTansact_r, TransactByValue causer_r )
425     { return setSoftTransact( toTansact_r, causer_r, causer_r ); }
426
427     bool maySetSoftTransact( bool val_r, TransactByValue causer,
428                              TransactByValue causerLimit_r )
429     {
430         bit::BitField<FieldType> savBitfield = _bitfield;
431         bool ret = setSoftTransact( val_r, causer, causerLimit_r );
432         _bitfield = savBitfield;
433         return ret;
434     }
435
436     bool maySetSoftTransact( bool val_r, TransactByValue causer )
437     { return maySetSoftTransact( val_r, causer, causer ); }
438
439     bool setToBeInstalled (TransactByValue causer)
440     {
441       if (isInstalled()) return false;
442       return setTransact (true, causer);
443     }
444
445     bool maySetToBeInstalled (TransactByValue causer)
446     {
447         bit::BitField<FieldType> savBitfield = _bitfield;
448         bool ret = setToBeInstalled (causer);
449         _bitfield = savBitfield;
450         return ret;
451     }
452
453     bool setToBeUninstalled (TransactByValue causer)
454     {
455       if (!isInstalled()) return false;
456       return setTransact (true, causer);
457     }
458
459     bool maySetToBeUninstalled (TransactByValue causer)
460     {
461         bit::BitField<FieldType> savBitfield = _bitfield;
462         bool ret = setToBeUninstalled (causer);
463         _bitfield = savBitfield;
464         return ret;
465     }
466
467     //------------------------------------------------------------------------
468     // *** These are only for the Resolver ***
469
470     bool setToBeUninstalledDueToObsolete ( )
471     {
472       if (!setToBeUninstalled (SOLVER)) return false;
473       fieldValueAssign<TransactDetailField>(DUE_TO_OBSOLETE);
474       return true;
475     }
476
477     bool setToBeUninstalledDueToUpgrade ( TransactByValue causer )
478     {
479       if (!setToBeUninstalled (causer)) return false;
480       fieldValueAssign<TransactDetailField>(DUE_TO_UPGRADE);
481       return true;
482     }
483
484     bool setToBeInstalledSoft ( )
485     {
486       if (isInstalled()
487           || !setSoftTransact (true, SOLVER))
488           return false;
489
490       fieldValueAssign<TransactDetailField>(SOFT_INSTALL);
491       return true;
492     }
493
494     bool setToBeUninstalledSoft ( )
495     {
496       if (!isInstalled()
497           || !setSoftTransact (true, SOLVER))
498           return false;
499
500       fieldValueAssign<TransactDetailField>(SOFT_REMOVE);
501       return true;
502     }
503
504     bool maySetToBeUninstalledSoft ()
505     {
506         bit::BitField<FieldType> savBitfield = _bitfield;
507         bool ret = setToBeUninstalledSoft ();
508         _bitfield = savBitfield;
509         return ret;
510     }      
511
512     bool isSoftInstall () {
513         return fieldValueIs<TransactDetailField> (SOFT_INSTALL);
514     }
515
516     bool isSoftUninstall () {
517         return fieldValueIs<TransactDetailField> (SOFT_REMOVE);
518     }
519
520     bool setSoftInstall (bool flag) {
521         fieldValueAssign<TransactDetailField>(flag?SOFT_INSTALL:0);
522         return true;
523     }
524
525     bool setSoftUninstall (bool flag) {
526         fieldValueAssign<TransactDetailField>(flag?SOFT_REMOVE:0);
527         return true;
528     }
529
530     bool isSeen () const
531     { return fieldValueIs<SolverStateField>( SEEN ); }
532
533     bool setSeen (bool value)
534     {
535       fieldValueAssign<SolverStateField>( value ? SEEN : NORMAL );
536       return true;
537     }
538
539     bool setStatus( ResStatus newStatus_r )
540     {
541       // State field is immutable!
542       if ( _bitfield.value<StateField>() != newStatus_r._bitfield.value<StateField>() )
543         return false;
544       // Transaction state change allowed?
545       if ( ! setTransactValue( newStatus_r.getTransactValue(), newStatus_r.getTransactByValue() ) )
546         return false;
547
548       // Ok, we take it all..
549       _bitfield = newStatus_r._bitfield;
550       return true;
551     }
552
553     /** \name Builtin ResStatus constants. */
554     //@{
555     static const ResStatus toBeInstalled;
556     static const ResStatus toBeInstalledSoft;
557     static const ResStatus toBeUninstalled;
558     static const ResStatus toBeUninstalledSoft;
559     static const ResStatus toBeUninstalledDueToUnlink;
560     static const ResStatus toBeUninstalledDueToObsolete;
561     static const ResStatus toBeUninstalledDueToUpgrade;
562     static const ResStatus installed;   // installed, status after successful target 'install' commit
563     static const ResStatus uninstalled; // uninstalled, status after successful target 'uninstall' commit
564     static const ResStatus satisfied;   // uninstalled, satisfied
565     static const ResStatus complete;    // installed, satisfied
566     static const ResStatus unneeded;    // uninstalled, unneeded
567     static const ResStatus needed;      // uninstalled, incomplete
568     static const ResStatus incomplete;  // installed, incomplete
569     static const ResStatus recommended; // recommended
570     static const ResStatus suggested;   // suggested      
571     //@}
572
573   private:
574     /** Ctor for intialization of builtin constants. */
575     ResStatus( StateValue s,
576                TransactValue t      = KEEP_STATE,
577                InstallDetailValue i = EXPLICIT_INSTALL,
578                RemoveDetailValue r  = EXPLICIT_REMOVE,
579                SolverStateValue ssv = NORMAL );
580
581     /** Return whether the corresponding Field has value \a val_r.
582     */
583     template<class _Field>
584       bool fieldValueIs( FieldType val_r ) const
585       { return _bitfield.isEqual<_Field>( val_r ); }
586
587     /** Set the corresponding Field to value \a val_r.
588     */
589     template<class _Field>
590       void fieldValueAssign( FieldType val_r )
591       { _bitfield.assign<_Field>( val_r ); }
592
593     /** compare two values.
594     */
595     template<class _Field>
596       bool isGreaterThan( FieldType val_r )
597           { return _bitfield.value<_Field>() > val_r; }
598
599     template<class _Field>
600       bool isLessThan( FieldType val_r )
601           { return _bitfield.value<_Field>() < val_r; }
602
603   private:
604     BitFieldType _bitfield;
605   };
606   ///////////////////////////////////////////////////////////////////
607
608   /** \relates ResStatus Stream output */
609   std::ostream & operator<<( std::ostream & str, const ResStatus & obj );
610
611   /** \relates ResStatus */
612   inline bool operator==( const ResStatus & lhs, const ResStatus & rhs )
613   { return lhs._bitfield == rhs._bitfield; }
614
615   /** \relates ResStatus */
616   inline bool operator!=( const ResStatus & lhs, const ResStatus & rhs )
617   { return ! (lhs == rhs); }
618
619   /////////////////////////////////////////////////////////////////
620 } // namespace zypp
621 ///////////////////////////////////////////////////////////////////
622 #endif // ZYPP_RESSTATUS_H