#ifndef ZYPP_DISKUSAGE_COUNTER_H
#define ZYPP_DISKUSAGE_COUNTER_H
-#include "zypp/ResPool.h"
-
#include <set>
#include <string>
#include <iosfwd>
+#include "zypp/ResPool.h"
+#include "zypp/Bitmap.h"
+#include "zypp/base/Flags.h"
+
///////////////////////////////////////////////////////////////////
namespace zypp
{ /////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////
+ /// \class DiskUsageCounter
+ /// \brief Compute disk space occupied by packages across partitions/directories
+ ///////////////////////////////////////////////////////////////////
class DiskUsageCounter
{
public:
-
- /**
- * @short Mount point description
- **/
+ ///////////////////////////////////////////////////////////////////
+ /// \class MountPoint
+ /// \brief Mount point description
+ /// If \ref block_size is set \ref DiskUsageCoutner will assume
+ /// half a block_size is wasted per file, in case a package
+ /// provides detailed isk usage information.
+ ///////////////////////////////////////////////////////////////////
struct MountPoint
{
- /**
- * Directory name
- **/
- std::string dir;
-
- /**
- * Block size of the mount point
- **/
- long long block_size;
-
- /**
- * Total size in K (1024)
- **/
- long long total_size;
-
- /**
- * Used size in K (1024)
- **/
- long long used_size;
-
- /**
- * Used size after commiting the pool (in K)
- **/
- mutable long long pkg_size;
-
- bool readonly;
-
- /**
- * Ctor - initialize directory and package size
- **/
- MountPoint(std::string d = "/", long long bs = 0LL, long long total = 0LL, long long used = 0LL, long long pkg = 0LL, bool ro=false) :
- dir(d), block_size(bs), total_size(total), used_size(used), pkg_size(pkg), readonly(ro)
+ friend std::ostream & operator<<( std::ostream & str, const MountPoint & obj );
+ std::string dir; ///< Directory name
+ std::string fstype; ///< Filesystem type (provided by \ref detectMountPoints)
+ long long block_size; ///< Block size of the filesystem in B (0 if you don't care)
+ long long total_size; ///< Total size of the filesystem in KiB (0 if you don't care)
+ long long used_size; ///< Used size of the filesystem in KiB (0 if you don't care)
+ mutable long long pkg_size; ///< Used size after installation in KiB (computed by \ref DiskUsageCoutner)
+ // hint bits:
+ bool readonly:1; ///< hint for readonly partitions
+ bool growonly:1; ///< hint for growonly partitions (e.g. snapshotting btrfs)
+
+
+ /** HinFlags for ctor */
+ enum Hint
+ {
+ NoHint = 0,
+ Hint_readonly = (1<<0), ///< readonly partitions
+ Hint_growonly = (1<<1), ///< growonly partitions (e.g. snapshotting btrfs)
+ };
+ ZYPP_DECLARE_FLAGS(HintFlags,Hint);
+
+ /** Ctor initialize directory, fstype and sizes */
+ MountPoint( const std::string & d = "/",
+ const std::string & f = std::string(),
+ long long bs = 0LL, long long total = 0LL, long long used = 0LL, long long pkg = 0LL,
+ HintFlags hints = NoHint )
+ : dir(d), fstype(f)
+ , block_size(bs), total_size(total), used_size(used), pkg_size(pkg)
+ , readonly(hints.testFlag(Hint_readonly))
+ , growonly(hints.testFlag(Hint_growonly))
+ {}
+ /** \overload <tt>const char *</tt> to allow e.g. initiailzer lists
+ * \code
+ * MountPointSet( { "/", "/usr", "/var" } )
+ * \endcode
+ */
+ MountPoint( const char * d,
+ const std::string & f = std::string(),
+ long long bs = 0LL, long long total = 0LL, long long used = 0LL, long long pkg = 0LL,
+ HintFlags hints = NoHint )
+ : MountPoint( std::string(d?d:""), f, bs, total, used, pkg, hints )
+ {}
+
+
+ /** Ctor initialize directory and sizes */
+ MountPoint( const std::string & d,
+ long long bs, long long total = 0LL, long long used = 0LL, long long pkg = 0LL,
+ HintFlags hints = NoHint )
+ : MountPoint( d, std::string(), bs, total, used, pkg, hints )
+ {}
+ /** \overload <tt>const char *</tt> */
+ MountPoint( const char * d,
+ long long bs, long long total = 0LL, long long used = 0LL, long long pkg = 0LL,
+ HintFlags hints = NoHint )
+ : MountPoint( std::string(d?d:""), bs, total, used, pkg, hints )
+ {}
+
+
+ /** Ctor just name and hints, all sizes 0 */
+ MountPoint( const std::string & d, HintFlags hints )
+ : MountPoint( d, std::string(), 0LL, 0LL, 0LL, 0LL, hints )
+ {}
+ /** \overload <tt>const char *</tt> */
+ MountPoint( const char * d, HintFlags hints )
+ : MountPoint( std::string(d?d:""), hints )
+ {}
+ /** \overload to prevent propagation Hint -> long long */
+ MountPoint( const std::string & d, Hint hint )
+ : MountPoint( d, HintFlags(hint) )
+ {}
+ /** \overload to prevent propagation Hint -> long long */
+ MountPoint( const char * d, Hint hint )
+ : MountPoint( std::string(d?d:""), HintFlags(hint) )
{}
- // sort by directory name
+
+ /** \deprecated Use HintFlags instead of a trailing 'bool ro' argument.
+ * \code
+ * - MountPoint( "/usr", ..., true ); // readonly
+ * + MountPoint( "/usr", ..., MountPoint::Hint_readonly );
+ * \endcode
+ */
+ ZYPP_DEPRECATED MountPoint( const std::string & d, long long bs, long long total, long long used, long long pkg, bool ro )
+ : MountPoint( d, bs, total, used, pkg, HintFlags(ro?Hint_readonly:NoHint) )
+ {}
+ /** \deprecated Use HintFlags instead of a trailing 'bool ro' argument.
+ * \code
+ * - MountPoint( "/usr", ..., true ); // readonly
+ * + MountPoint( "/usr", ..., MountPoint::Hint_readonly );
+ * \endcode
+ */
+ ZYPP_DEPRECATED MountPoint( const char * d, long long bs, long long total, long long used, long long pkg, bool ro )
+ : MountPoint( d, bs, total, used, pkg, HintFlags(ro?Hint_readonly:NoHint) )
+ {}
+
+
+ /** Sort by directory name */
bool operator<( const MountPoint & rhs ) const
- {
- return dir < rhs.dir;
- }
+ { return dir < rhs.dir; }
+ /** Block size of the filesystem as \ref ByteCount for convenience. */
ByteCount blockSize() const
{ return ByteCount( block_size, ByteCount::B ); }
+ /** Total size of the filesystem as \ref ByteCount for convenience. */
ByteCount totalSize() const
{ return ByteCount( total_size, ByteCount::K ); }
+ /** Used size of the filesystem as \ref ByteCount for convenience. */
ByteCount usedSize() const
{ return ByteCount( used_size, ByteCount::K ); }
+ /** Free size of the filesystem as \ref ByteCount for convenience. */
ByteCount freeSize() const
{ return ByteCount( total_size-used_size, ByteCount::K ); }
+ /** Used size after installation as \ref ByteCount for convenience. */
ByteCount usedAfterCommit() const
{ return ByteCount( pkg_size, ByteCount::K ); }
+ /** Free size after installation as \ref ByteCount for convenience. */
ByteCount freeAfterCommit() const
{ return ByteCount( total_size-pkg_size, ByteCount::K ); }
+ /** Size change due to installation as \ref ByteCount for convenience. */
ByteCount commitDiff() const
{ return ByteCount( pkg_size-used_size, ByteCount::K ); }
};
+ ///////////////////////////////////////////////////////////////////
typedef std::set<MountPoint> MountPointSet;
DiskUsageCounter()
{}
- DiskUsageCounter( const MountPointSet & m )
- : mps( m )
+ /** Ctor taking the MountPointSet to compute */
+ DiskUsageCounter( const MountPointSet & mps_r )
+ : _mps( mps_r )
{}
- bool setMountPoints( const MountPointSet & m )
- {
- mps = m;
- return true;
- }
+ /** Set a MountPointSet to compute */
+ void setMountPoints( const MountPointSet & mps_r )
+ { _mps = mps_r; }
+ /** Get the current MountPointSet */
const MountPointSet & getMountPoints() const
- {
- return mps;
- }
+ { return _mps; }
- static MountPointSet detectMountPoints(const std::string &rootdir = "/");
+ /** Get mountpoints of system below \a rootdir
+ * If we happen to detect snapshotting btrfs partitions, the MountPoint::growonly
+ * hint is set. Disk usage computation will assume that deleted packages will not
+ * free any space (kept in a snapshot).
+ */
+ static MountPointSet detectMountPoints( const std::string & rootdir = "/" );
+ /** Only one entry for "/" to collect total sizes */
static MountPointSet justRootPartition();
- /**
- * Compute disk usage of the pool
- **/
- MountPointSet disk_usage( const ResPool & pool );
- /**
- * Compute disk usage of one solvable
- */
- MountPointSet disk_usage( sat::Solvable solv_r );
- /** \overload */
- MountPointSet disk_usage( const PoolItem & pi_r )
- { return disk_usage( pi_r.satSolvable() ); }
- /** \overload */
- MountPointSet disk_usage( const ResObject::constPtr & obj_r )
+ /** Compute disk usage if the current transaction woud be commited. */
+ MountPointSet disk_usage( const ResPool & pool ) const;
+
+ /** Compute disk usage of a single Solvable */
+ MountPointSet disk_usage( sat::Solvable solv_r ) const;
+ /** \overload for PoolItem */
+ MountPointSet disk_usage( const PoolItem & pi_r ) const
+ { return disk_usage( sat::asSolvable()( pi_r ) ); }
+ /** \overload for ResObject */
+ MountPointSet disk_usage( const ResObject::constPtr & obj_r ) const
+ { return disk_usage( sat::asSolvable()( obj_r ) ); }
+
+ /** Compute disk usage of a collection defined by a solvable bitmap. */
+ MountPointSet disk_usage( const Bitmap & bitmap_r ) const;
+
+ /** Compute disk usage of a collection (convertible by \ref asSolvable). */
+ template<class Iterator>
+ MountPointSet disk_usage( Iterator begin_r, Iterator end_r ) const
{
- if ( ! obj_r )
- return MountPointSet();
- return disk_usage( obj_r->satSolvable() );
+ Bitmap bitmap( Bitmap::poolSize );
+ for_( it, begin_r, end_r )
+ bitmap.set( sat::asSolvable()( *it ).id() );
+ return disk_usage( bitmap );
}
private:
-
- MountPointSet mps;
+ MountPointSet _mps;
};
///////////////////////////////////////////////////////////////////
+ ZYPP_DECLARE_OPERATORS_FOR_FLAGS(DiskUsageCounter::MountPoint::HintFlags);
+
/** \relates DiskUsageCounter::MountPoint Stream output */
std::ostream & operator<<( std::ostream & str, const DiskUsageCounter::MountPoint & obj );
+ /** \relates DiskUsageCounter::MountPointSet Stream output */
+ std::ostream & operator<<( std::ostream & str, const DiskUsageCounter::MountPointSet & obj );
+
+ /** \relates DiskUsageCounter Stream output */
+ inline std::ostream & operator<<( std::ostream & str, const DiskUsageCounter & obj )
+ { return str << obj.getMountPoints(); }
+
/////////////////////////////////////////////////////////////////
} // namespace zypp
///////////////////////////////////////////////////////////////////