/************************************************************************
* EOS - the CERN Disk Storage System *
* Copyright (C) 2019 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
//! @brief Utility class to recompute a quotanode
//------------------------------------------------------------------------------
#include "namespace/ns_quarkdb/utils/QuotaRecomputer.hh"
#include "namespace/ns_quarkdb/views/HierarchicalView.hh"
#include "namespace/Constants.hh"
#include "namespace/ns_quarkdb/explorer/NamespaceExplorer.hh"
#include "common/LayoutId.hh"
EOSNSNAMESPACE_BEGIN
//------------------------------------------------------------------------------
// Constructor
//------------------------------------------------------------------------------
QuotaRecomputer::QuotaRecomputer(qclient::QClient* qcl,
folly::Executor* exec)
: mQcl(qcl), mExecutor(exec) {}
//------------------------------------------------------------------------------
// Filtering class for NamespaceExplorer to ignore sub-quotanodes when
// recomputing a quotanode.
//------------------------------------------------------------------------------
class QuotaNodeFilter : public ExpansionDecider
{
public:
QuotaNodeFilter(uint64_t root) : rootContainer(root) {}
virtual bool shouldExpandContainer(const eos::ns::ContainerMdProto& proto,
const eos::IContainerMD::XAttrMap& attrs,
const std::string& fullPath) override
{
if (proto.id() == rootContainer) {
return true; // always expand root, no matter what
}
if ((proto.flags() & eos::QUOTA_NODE_FLAG) == 0) {
return true; // not a quota node, continue
}
return false; // quota node, ignore
}
private:
uint64_t rootContainer;
};
//------------------------------------------------------------------------------
// Given a quotanode, re-calculate the quota values,
// store into QuotaNodeCore.
//------------------------------------------------------------------------------
MDStatus QuotaRecomputer::recompute(const std::string& cont_uri,
const eos::IContainerMD::id_t cont_id,
QuotaNodeCore& qnc)
{
// Reset qnc contents
qnc = {};
if (cont_id == 0ull) {
return MDStatus(EINVAL, "error: requested computation for cid=0");
}
ExplorationOptions options;
options.depthLimit = 2048;
options.expansionDecider.reset(new QuotaNodeFilter(cont_id));
NamespaceExplorer explorer(cont_uri, options, *mQcl, mExecutor);
NamespaceItem item;
while (explorer.fetch(item)) {
if (item.isFile) {
// Calculate physical size
uint64_t logicalSize = item.fileMd.size();
uint64_t physicalSize = item.fileMd.size() *
eos::common::LayoutId::GetSizeFactor(item.fileMd.layout_id());
// Account file.
qnc.addFile(item.fileMd.uid(), item.fileMd.gid(), logicalSize,
physicalSize);
}
}
return MDStatus(); // OK
}
EOSNSNAMESPACE_END