#include <iostream>
#include <fstream>
-#include "zypp/base/Logger.h"
+#include "zypp/base/Easy.h"
+#include "zypp/base/LogTools.h"
#include "zypp/base/String.h"
#include "zypp/DiskUsageCounter.h"
-#include "zypp/Package.h"
+#include "zypp/sat/Pool.h"
+#include "zypp/sat/detail/PoolImpl.h"
+using std::endl;
///////////////////////////////////////////////////////////////////
namespace zypp
{ /////////////////////////////////////////////////////////////////
- DiskUsageCounter::MountPointSet DiskUsageCounter::disk_usage(const ResPool &pool)
- {
- MountPointSet result = mps;
+ ///////////////////////////////////////////////////////////////////
+ namespace
+ { /////////////////////////////////////////////////////////////////
- if (mps.empty())
+ struct SatMap : private base::NonCopyable
{
- // partitioning is not set
- return result;
- }
+ SatMap( unsigned capacity_r = 1 )
+ {
+ ::map_init( &_installedmap, sat::Pool::instance().capacity() );
+ }
- // set used size after commit to the current used size
- for (MountPointSet::iterator mpit = result.begin();
- mpit != result.end();
- mpit++)
- {
- mpit->pkg_size = mpit->used_size;
- }
+ void add( sat::Solvable solv_r )
+ {
+ MAPSET( &_installedmap, solv_r.id() );
+ }
+
+ void add( const PoolItem & pi_r )
+ { add( pi_r->satSolvable() ); }
- // iterate through all packages
- for (ResPool::byKind_iterator it = pool.byKindBegin(ResTraits<Package>::kind);
- it != pool.byKindEnd(ResTraits<Package>::kind);
- ++it)
+ void add( const ResObject::constPtr & obj_r )
+ { add( obj_r->satSolvable() ); }
+
+ mutable ::Map _installedmap;
+ };
+
+ DiskUsageCounter::MountPointSet calcDiskUsage( const DiskUsageCounter::MountPointSet & mps_r, const SatMap & installedmap_r )
{
- bool inst = it->status().isToBeInstalled();
- bool rem = it->status().isToBeUninstalled();
+ DiskUsageCounter::MountPointSet result = mps_r;
- // if the package is not selected for installation or removing
- // it can't affect disk usage
- if (inst || rem)
+ if ( result.empty() )
{
- Package::constPtr pkg = asKind<Package>( it->resolvable() );
- DiskUsage du = pkg->diskusage();
- DiskUsage du_another_package;
- Edition edition_another_package;
-
- // the same package has been selected for installation
- bool found_installed = false;
- // the same package has been selected for uninstallation
- bool found_to_install = false;
-
- // the du is empty or the package is selected for installation (check whether the package is already installed)
- if (du.size() == 0 || inst)
- {
- // disk usage is unknown for already installed packages
- // find the same package from any installation source
- std::string name = (*it)->name();
-
- for (ResPool::byName_iterator nameit = pool.byNameBegin(name);
- nameit != pool.byNameEnd(name);
- ++nameit)
- {
- // is version and architecture same?
- if (isKind<Package>(nameit->resolvable()))
- {
- // found a package
- Package::constPtr pkg_from_source = asKind<Package>( nameit->resolvable() );
-
- if (nameit->status().isToBeInstalled())
- {
- found_to_install = true;
- }
-
- // check the version
- if ((*it)->edition() == (*nameit)->edition() && (*it)->arch() == (*nameit)->arch())
- {
- if (inst)
- {
- if (nameit->status().isInstalled() && !nameit->status().isToBeUninstalled())
- {
- found_installed = true;
- XXX << name << '-' << (*it)->edition() << ": found already installed package (" << (*nameit)->edition() << ")" << std::endl;
- }
- }
- else
- {
- // the package will be uninstalled and du is empty, try to use du from another object
- du = pkg_from_source->diskusage();
- if (du.size() > 0)
- {
- XXX << name << '-' << (*it)->edition() << ": using DiskUsage from another Package object (" << (*nameit)->edition() << ")" << std::endl;
- break;
- }
- }
- }
- else
- {
- if (inst && nameit->status().isInstalled() && !nameit->status().isToBeUninstalled())
- {
- // just freshen the package, don't change du statistics
- found_installed = true;
- XXX << name << '-' << (*it)->edition() << ": found already installed package (" << (*nameit)->edition() << ")" << std::endl;
- }
- else if (pkg_from_source->diskusage().size() > 0)
- {
- // found different version of the package, remember the disk usage
- // it will be used the same version is not found
- du_another_package = pkg_from_source->diskusage();
- edition_another_package = (*nameit)->edition();
- }
- }
- }
- }
+ // partitioning is not set
+ return result;
+ }
- // don't subtract the disk usage for updated package
- if (du.size() == 0 && du_another_package.size() > 0 && !(rem && found_to_install))
- {
- XXX << name << '-' << (*it)->edition() << ": using DU info from version " << edition_another_package << std::endl;
- du = du_another_package;
- }
- }
+ sat::Pool satpool( sat::Pool::instance() );
+ if ( ! satpool.findSystemRepo() )
+ {
+ // take care we have at least an empty stystem repo.
+ // ::pool_calc_duchanges requires it.
+ satpool.systemRepo();
+ satpool.prepare();
+ }
- // don't modify du if the installed package is already installed (freshening)
- if (du.size() > 0 && !(inst && found_installed))
- {
- // iterate trough all mount points, add usage to each directory
- // directory tree must be processed from leaves to the root directory
- // so iterate in reverse order so e.g. /usr is used before /
- for (MountPointSet::reverse_iterator mpit = result.rbegin();
- mpit != result.rend();
- mpit++)
- {
- // get usage for the mount point
- DiskUsage::Entry entry = du.extract(mpit->dir);
-
- // add or subtract it to the current value
- if (inst)
- {
- mpit->pkg_size += entry._size;
- }
- else // the package will be uninstalled
- {
- mpit->pkg_size -= entry._size;
- }
- }
- }
+ // init satsolver result vector with mountpoints
+ static const ::DUChanges _initdu = { 0, 0, 0 };
+ std::vector< ::DUChanges> duchanges( result.size(), _initdu );
+ {
+ unsigned idx = 0;
+ for_( it, result.begin(), result.end() )
+ {
+ duchanges[idx].path = it->dir.c_str();
+ ++idx;
+ }
}
+
+ // now calc...
+ ::pool_calc_duchanges( satpool.get(),
+ satpool.systemRepo().get(),
+ &installedmap_r._installedmap,
+ &duchanges[0],
+ duchanges.size() );
+
+ // and process the result
+ {
+ unsigned idx = 0;
+ for_( it, result.begin(), result.end() )
+ {
+ static const ByteCount blockAdjust( 2, ByteCount::K ); // (files * blocksize) / (2 * 1K)
+
+ it->pkg_size = it->used_size // current usage
+ + duchanges[idx].kbytes // package data size
+ + ( duchanges[idx].files * it->block_size / blockAdjust ); // half block per file
+ ++idx;
+ }
+ }
+
+ return result;
}
- return result;
+ /////////////////////////////////////////////////////////////////
+ } // namespace
+ ///////////////////////////////////////////////////////////////////
+
+ DiskUsageCounter::MountPointSet DiskUsageCounter::disk_usage( const ResPool & pool_r )
+ {
+ SatMap installedmap( sat::Pool::instance().capacity() );
+ // build installedmap (installed != transact)
+ // stays installed or gets installed
+ for_( it, pool_r.begin(), pool_r.end() )
+ {
+ if ( it->status().isInstalled() != it->status().transacts() )
+ {
+ installedmap.add( *it );
+ }
+ }
+ return calcDiskUsage( mps, installedmap );
}
+ DiskUsageCounter::MountPointSet DiskUsageCounter::disk_usage( sat::Solvable solv_r )
+ {
+ SatMap installedmap;
+ installedmap.add( solv_r );
+ return calcDiskUsage( mps, installedmap );
+ }
DiskUsageCounter::MountPointSet DiskUsageCounter::detectMountPoints(const std::string &rootdir)
{
continue;
}
+ if ( words[2] == "vfat" || words[2] == "fat" || words[2] == "ntfs" || words[2] == "ntfs-3g")
+ {
+ MIL << words[1] << " contains ignored fs (" << words[2] << ')' << std::endl;
+ continue;
+ }
+
//
// Filter some common unwanted mountpoints
//
return ret;
}
+ DiskUsageCounter::MountPointSet DiskUsageCounter::justRootPartition()
+ {
+ DiskUsageCounter::MountPointSet ret;
+ ret.insert( DiskUsageCounter::MountPoint() );
+ return ret;
+ }
+
std::ostream & operator<<( std::ostream & str, const DiskUsageCounter::MountPoint & obj )
{
- str << "dir:[" << obj.dir << "] [ bs: " << obj.block_size << " ts: " << obj.total_size << "]" << std::endl;
+ str << "dir:[" << obj.dir << "] [ bs: " << obj.blockSize()
+ << " ts: " << obj.totalSize()
+ << " us: " << obj.usedSize()
+ << " (+-: " << obj.commitDiff()
+ << ")]";
return str;
}
+ /////////////////////////////////////////////////////////////////
} // namespace zypp
///////////////////////////////////////////////////////////////////