/************************************************************************
* EOS - the CERN Disk Storage System *
* Copyright (C) 2011 CERN/Switzerland *
* *
* This program is free software: you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation, either version 3 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program. If not, see .*
************************************************************************/
//------------------------------------------------------------------------------
// author: Georgios Bitzes
// desc: Utility to calculate balance statistics over a set of files
//------------------------------------------------------------------------------
#pragma once
namespace eos
{
//------------------------------------------------------------------------------
//! Class to calculate balance statistics over a set of files
//------------------------------------------------------------------------------
class BalanceCalculator
{
public:
//----------------------------------------------------------------------------
//! Constructor
//----------------------------------------------------------------------------
BalanceCalculator()
{
filesystembalance.set_empty_key(0);
spacebalance.set_empty_key("");
schedulinggroupbalance.set_empty_key("");
sizedistribution.set_empty_key(-1);
sizedistributionn.set_empty_key(-1);
}
//----------------------------------------------------------------------------
//! Take the given fmd into account for statistics calculations
//----------------------------------------------------------------------------
void account(const std::shared_ptr& fmd)
{
for (unsigned int i = 0; i < fmd->getNumLocation(); i++) {
auto loc = fmd->getLocation(i);
size_t size = fmd->getSize();
if (!loc) {
eos_static_err("fsid 0 found %s %llu", fmd->getName().c_str(), fmd->getId());
continue;
}
filesystembalance[loc] += size;
if ((i == 0) && (size)) {
auto bin = (int) log10((double) size);
sizedistribution[ bin ] += size;
sizedistributionn[ bin ]++;
}
eos::common::RWMutexReadLock lock(FsView::gFsView.ViewMutex);
eos::common::FileSystem* filesystem = FsView::gFsView.mIdView.lookupByID(loc);
if (filesystem != nullptr) {
eos::common::FileSystem::fs_snapshot_t fs;
if (filesystem->SnapShotFileSystem(fs, true)) {
spacebalance[fs.mSpace] += size;
schedulinggroupbalance[fs.mGroup] += size;
}
}
}
}
//----------------------------------------------------------------------------
//! Print a summary into the given stream
//----------------------------------------------------------------------------
template // std::ofstream or std::stringstream
void printSummary(S& ss)
{
XrdOucString sizestring = "";
for (const auto& it : filesystembalance) {
ss << "fsid=" << it.first << " \tvolume=";
ss << std::left << std::setw(12) <<
eos::common::StringConversion::GetReadableSizeString(sizestring, it.second,
"B");
ss << " \tnbytes=" << it.second << std::endl;
}
for (const auto& its : spacebalance) {
ss << "space=" << its.first << " \tvolume=";
ss << std::left << std::setw(12) <<
eos::common::StringConversion::GetReadableSizeString(sizestring, its.second,
"B");
ss << " \tnbytes=" << its.second << std::endl;
}
for (const auto& itg : schedulinggroupbalance) {
ss << "sched=" << itg.first << " \tvolume=";
ss << std::left << std::setw(12) <<
eos::common::StringConversion::GetReadableSizeString(sizestring, itg.second,
"B");
ss << " \tnbytes=" << itg.second << std::endl;
}
for (const auto& itsd : sizedistribution) {
unsigned long long lowerlimit = 0;
unsigned long long upperlimit = 0;
if (((itsd.first) - 1) > 0) {
lowerlimit = pow(10, (itsd.first));
}
if ((itsd.first) > 0) {
upperlimit = pow(10, (itsd.first) + 1);
}
XrdOucString sizestring1;
XrdOucString sizestring2;
XrdOucString sizestring3;
XrdOucString sizestring4;
unsigned long long avgsize = (sizedistributionn[itsd.first]
? itsd.second / sizedistributionn[itsd.first] : 0);
ss << "sizeorder=" << std::right << setfill('0') << std::setw(
2) << itsd.first;
ss << " \trange=[ " << setfill(' ') << std::left << std::setw(12);
ss << eos::common::StringConversion::GetReadableSizeString(
sizestring1, lowerlimit, "B");
ss << " ... " << std::left << std::setw(12);
ss << eos::common::StringConversion::GetReadableSizeString(
sizestring2, upperlimit, "B") << " ]";
ss << " volume=" << std::left << std::setw(12);
ss << eos::common::StringConversion::GetReadableSizeString(
sizestring3, itsd.second, "B");
ss << " \tavgsize=" << std::left << std::setw(12);
ss << eos::common::StringConversion::GetReadableSizeString(
sizestring4, avgsize, "B");
ss << " \tnbytes=" << itsd.second;
ss << " \t avgnbytes=" << avgsize;
ss << " \t nfiles=" << sizedistributionn[itsd.first];
}
}
private:
google::dense_hash_map filesystembalance;
google::dense_hash_map spacebalance;
google::dense_hash_map schedulinggroupbalance;
google::dense_hash_map sizedistribution;
google::dense_hash_map sizedistributionn;
};
}