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