Imported Upstream version 17.20.0
[platform/upstream/libzypp.git] / zypp / target / rpm / librpmDb.h
1 /*---------------------------------------------------------------------\
2 |                          ____ _   __ __ ___                          |
3 |                         |__  / \ / / . \ . \                         |
4 |                           / / \ V /|  _/  _/                         |
5 |                          / /__ | | | | | |                           |
6 |                         /_____||_| |_| |_|                           |
7 |                                                                      |
8 \---------------------------------------------------------------------*/
9 /** \file zypp/target/rpm/librpmDb.h
10  *
11 */
12 #ifndef librpmDb_h
13 #define librpmDb_h
14
15 #include <iosfwd>
16
17 #include "zypp/base/ReferenceCounted.h"
18 #include "zypp/base/NonCopyable.h"
19 #include "zypp/base/PtrTypes.h"
20 #include "zypp/PathInfo.h"
21 #include "zypp/Package.h"
22 #include "zypp/target/rpm/RpmHeader.h"
23 #include "zypp/target/rpm/RpmException.h"
24
25 namespace zypp
26 {
27 namespace target
28 {
29 namespace rpm
30 {
31
32 ///////////////////////////////////////////////////////////////////
33 //
34 //      CLASS NAME : librpmDb
35 /**
36  * @short Manage access to librpm database.
37  **/
38 class librpmDb : public base::ReferenceCounted, private base::NonCopyable
39 {
40 public:
41   typedef intrusive_ptr<librpmDb> Ptr;
42   typedef intrusive_ptr<const librpmDb> constPtr;
43 private:
44   /**
45    * <B>INTENTIONALLY UNDEFINED<\B> because of bug in Ptr classes
46    * which allows implicit conversion from librpmDb::Ptr to
47    * librpmDb::constPtr. Currently we don't want to provide non const
48    * handles, as the database is opened READONLY.
49   *
50    * \throws RpmException
51    *
52    **/
53   static void dbAccess( librpmDb::Ptr & ptr_r );
54
55 public:
56
57   ///////////////////////////////////////////////////////////////////
58   //
59   //    static interface
60   //
61   ///////////////////////////////////////////////////////////////////
62 private:
63
64   /**
65    * Current root directory for all operations.
66    * (initialy /)
67    **/
68   static Pathname _defaultRoot;
69
70   /**
71    * Current directory (below root) that contains the rpmdb.
72    * (initialy /var/lib/rpm)
73    **/
74   static const Pathname _defaultDbPath;
75
76   /**
77    * Current rpmdb handle.
78    **/
79   static librpmDb::constPtr _defaultDb;
80
81   /**
82    * Whether access is blocked (no _defaultDb will be available).
83    **/
84   static bool _dbBlocked;
85
86   /**
87    * For internal use. Pointer returned should immediately be
88    * wrapped into librpmDb::Ptr.
89    *
90    * \throws RpmException
91    *
92    **/
93   static librpmDb * newLibrpmDb();
94
95   /**
96    * Access the database at the current default location. If necessary
97    * (eg. after @ref dbRelease), the database is opened. This just creates
98    * the internal handle. Once the handle is passed to e.g. some
99    * @ref db_const_iterator, the database will be closed if the last
100    * outstanding reference goes out of scope. If no external reference is
101    * created, you'll have to explicitly call @ref dbRelease to close the
102    * database.
103    *
104    * \throws RpmException
105    *
106    **/
107   static void dbAccess();
108
109 public:
110
111   /**
112    * Initialize lib librpm (read configfiles etc.). It's called
113    * on demand but you may call it anytime.
114    *
115    * @return Whether librpm is initialized.
116    **/
117   static bool globalInit();
118
119   /**
120    * @return librpm macro expansion.
121    **/
122   static std::string expand( const std::string & macro_r );
123
124   /**
125    * @return String '(root_r)sub_r' used in debug output.
126    **/
127   static std::string stringPath( const Pathname & root_r, const Pathname & sub_r )
128   {
129     return std::string( "'(" ) + root_r.asString() + ")" + sub_r.asString() + "'";
130   }
131
132 public:
133
134   /**
135    * @return Current root directory for all operations.
136    **/
137   static const Pathname & defaultRoot()
138   {
139     return _defaultRoot;
140   }
141
142   /**
143    * @return Current directory (below root) that contains the rpmdb.
144    **/
145   static const Pathname & defaultDbPath()
146   {
147     return _defaultDbPath;
148   }
149
150   /**
151    * Adjust access to the given database location, making it the new
152    * default location on success. No relative Pathnames are allowed.
153    *
154    * It's not possible to access a database while access is blocked
155    * (see @ref blockAccess), but valid Pathnames provided will be stored
156    * as new default location.
157    *
158    * It's not allowed to switch to another location while a database
159    * is accessed. Use @ref dbRelease to force releasing the database first.
160   *
161    * \throws RpmException
162    *
163    **/
164   static void dbAccess( const Pathname & root_r );
165
166   /**
167    * Same as &ref dbAccess(), but returns the database handle if
168    * avaialble, otherwise NULL. This creates an external reference, thus
169    * it should not be used longer than necessary. Be prepared that the
170    * handle might become invalid (see @ref dbRelease) later.
171    *
172    * \throws RpmException
173    *
174    **/
175   static void dbAccess( librpmDb::constPtr & ptr_r );
176
177   /**
178    * If there are no outstanding references to the database (e.g. by @ref db_const_iterator),
179    * the database is closed. Subsequent calls to @ref dbAccess may however
180    * open the database again.
181    *
182    * If forced, the internal reference is dropped and it will look like
183    * the database was closed. But physically the database will be closed
184    * after all outstanding references are gone.
185    *
186    * @return The number of outstandig references to the database, 0 if
187    * if database was physically closed.
188    **/
189   static unsigned dbRelease( bool force_r = false );
190
191   /**
192    * Blocks further access to rpmdb. Basically the same as @ref dbRelease( true ),
193    * but subsequent calls to @ref dbAccess will fail returning E_RpmDB_access_blocked.
194    *
195    * @return The number of outstandig references to the database, 0 if
196    * if database was physically closed.
197    **/
198   static unsigned blockAccess();
199
200   /**
201    * Allow access to rpmdb e.g. after @ref blockAccess. Subsequent calls to
202    * @ref dbAccess will perform.
203    *
204    * <B>NOTE:</B> Initially we're in blocked mode. So you must call @ref unblockAccess
205    * unblockAccess at least once. Othwise nothing will happen.
206    *
207    * @return The number of outstandig references to the database, 0 if
208    * if database was physically closed.
209    **/
210   static void unblockAccess();
211
212   /**
213    * @return Whether database access is blocked.
214    **/
215   static bool isBlocked()
216   {
217     return _dbBlocked;
218   }
219
220   /**
221    * Dump debug info.
222    **/
223   static std::ostream & dumpState( std::ostream & str );
224
225 public:
226
227   /**
228    * Subclass to retrieve database content.
229    **/
230   class db_const_iterator;
231
232 private:
233   ///////////////////////////////////////////////////////////////////
234   //
235   //    internal database handle interface (nonstatic)
236   //
237   ///////////////////////////////////////////////////////////////////
238
239   /**
240    * Hides librpm specific data
241    **/
242   class D;
243   D & _d;
244
245 protected:
246
247   /**
248    * Private constructor! librpmDb objects are to be created via
249    * static interface only.
250    **/
251   librpmDb( const Pathname & root_r, const Pathname & dbPath_r, bool readonly_r );
252
253   /**
254    * Trigger from @ref Rep, after refCount was decreased.
255    **/
256   virtual void unref_to( unsigned refCount_r ) const;
257
258 public:
259
260   /**
261    * Destructor. Closes rpmdb.
262    **/
263   virtual ~librpmDb();
264
265   /**
266    * @return This handles root directory for all operations.
267    **/
268   const Pathname & root() const;
269
270   /**
271    * @return This handles directory that contains the rpmdb.
272    **/
273   const Pathname & dbPath() const;
274
275   /**
276    * Return any database error. Usg. if the database was
277    * blocked by calling @ref dbRelease(true) or @ref blockAccess.
278    **/
279   shared_ptr<RpmException> error() const;
280
281   /**
282    * @return Whether handle is valid.
283    **/
284   bool valid() const
285   {
286     return( ! error() );
287   }
288
289   /**
290    * @return True if handle is valid and database is empty.
291    **/
292   bool empty() const;
293
294   /**
295    * @return Number of entries in the database (0 if not valid).
296    **/
297   unsigned size() const;
298
299 public:
300
301   /**
302    * Dont call it ;) It's for development and testing only.
303    **/
304   void * dont_call_it() const;
305
306   /**
307    * Dump debug info.
308    **/
309   virtual std::ostream & dumpOn( std::ostream & str ) const;
310 };
311
312 ///////////////////////////////////////////////////////////////////
313
314 ///////////////////////////////////////////////////////////////////
315 //
316 //      CLASS NAME : librpmDb::db_const_iterator
317 /**
318  * @short Subclass to retrieve database content.
319  *
320  *
321  **/
322 class librpmDb::db_const_iterator
323 {
324   db_const_iterator & operator=( const db_const_iterator & ); // NO ASSIGNMENT!
325   db_const_iterator ( const db_const_iterator & );            // NO COPY!
326   friend std::ostream & operator<<( std::ostream & str, const db_const_iterator & obj );
327   friend class librpmDb;
328
329 private:
330
331   /**
332    * Hides librpm specific data
333    **/
334   class D;
335   D & _d;
336
337 public:
338
339   /**
340    * Constructor. Iterator is initialized to @ref findAll.
341    * The default form accesses librpmDb's default database.
342    * Explicitly providing a database handle should not be
343    * neccesary, except for testing.
344    **/
345   db_const_iterator( librpmDb::constPtr dbptr_r = 0 );
346
347   /**
348    * Destructor.
349    **/
350   ~db_const_iterator();
351
352   /**
353    * Return any database error.
354    *
355    * <B>NOTE:</B> If the database gets blocked (see @ref dbRelease)
356    * dbError will immediately report this, but an already running
357    * iteration will proceed to its end. Then the database is dropped.
358    **/
359   shared_ptr<RpmException> dbError() const;
360
361   /**
362    * Advance to next RpmHeader::constPtr.
363    **/
364   void operator++();
365
366   /**
367    * Returns the current headers index in database,
368    * 0 if no header.
369    **/
370   unsigned dbHdrNum() const;
371
372   /**
373    * Returns the current RpmHeader::constPtr or
374    * NULL, if no more entries available.
375    **/
376   const RpmHeader::constPtr & operator*() const;
377
378   /**
379    * Forwards to the current RpmHeader::constPtr.
380    **/
381   const RpmHeader::constPtr & operator->() const
382   {
383     return operator*();
384   }
385
386 public:
387
388   /**
389    * Reset to iterate all packages. Returns true if iterator
390    * contains at least one entry.
391    *
392    * <B>NOTE:</B> No entry (false) migt be returned due to a
393    * meanwhile blocked database (see @ref dbRelease). Use
394    * @ref dbError to check this.
395    **/
396   bool findAll();
397
398   /**
399    * Reset to iterate all packages that own a certain file.
400    **/
401   bool findByFile( const std::string & file_r );
402
403   /**
404    * Reset to iterate all packages that provide a certain tag.
405    **/
406   bool findByProvides( const std::string & tag_r );
407
408   /**
409    * Reset to iterate all packages that require a certain tag.
410    **/
411   bool findByRequiredBy( const std::string & tag_r );
412
413   /**
414    * Reset to iterate all packages that conflict with a certain tag.
415    **/
416   bool findByConflicts( const std::string & tag_r );
417
418   /**
419    * Reset to iterate all packages with a certain name.
420    *
421    * <B>NOTE:</B> Multiple entries for one package installed
422    * in different versions are possible but not desired. Usually
423    * you'll want to use @ref findPackage instead.
424    *
425    * findByName is needed to retrieve pseudo packages like
426    * 'gpg-pubkey', which in fact exist in multiple instances.
427    **/
428   bool findByName( const std::string & name_r );
429
430 public:
431
432   /**
433    * Find package by name.
434    *
435    * Multiple entries for one package installed in different versions
436    * are possible but not desired. If so, the last package installed
437    * is returned.
438    **/
439   bool findPackage( const std::string & name_r );
440
441   /**
442    * Find package by name and edition.
443    * Commonly used by PMRpmPackageDataProvider.
444    **/
445   bool findPackage( const std::string & name_r, const Edition & ed_r );
446
447   /**
448    * Abbr. for <code>findPackage( which_r->name(), which_r->edition() );</code>
449    **/
450   bool findPackage( const Package::constPtr & which_r );
451 };
452
453 ///////////////////////////////////////////////////////////////////
454 } //namespace rpm
455 } //namespace target
456 } // namespace zypp
457
458 #endif // librpmDb_h
459