Commit d70599c4 authored by Georgios Bitzes's avatar Georgios Bitzes

NS: Implement container resolver based on oneof (path, cid, cxid), use in recompute_tree_size

parent 611df2e1
Pipeline #467472 passed with stages
in 27 minutes and 53 seconds
//------------------------------------------------------------------------------
// File: DBG.hh
// Author: Georgios Bitzes - CERN
//------------------------------------------------------------------------------
/************************************************************************
* EOS - the CERN Disk Storage System *
* Copyright (C) 2018 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 <http://www.gnu.org/licenses/>.*
************************************************************************/
#pragma once
#include <iostream>
#define DBG(message) std::cerr << __FILE__ << ":" << __LINE__ << " -- " << #message << " = " << message << std::endl
// ----------------------------------------------------------------------
// File: ParseUtils.hh
// Author: Georgios Bitzes - CERN
// ----------------------------------------------------------------------
/************************************************************************
* 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 <http://www.gnu.org/licenses/>.*
************************************************************************/
//------------------------------------------------------------------------------
//! @author Georgios Bitzes <georgios.bitzes@cern.ch>
//! @brief Parse utilities with proper error checking
//------------------------------------------------------------------------------
#ifndef EOSCOMMON_PARSE_UTILS_HH
#define EOSCOMMON_PARSE_UTILS_HH
#include "common/Namespace.hh"
#include <climits>
EOSCOMMONNAMESPACE_BEGIN
inline bool parseInt64(const std::string &str, int64_t &ret, int base = 10) {
char *endptr = NULL;
ret = std::strtoll(str.c_str(), &endptr, base);
if(endptr != str.c_str() + str.size() || ret == LLONG_MIN || ret == LONG_LONG_MAX) {
return false;
}
return true;
}
EOSCOMMONNAMESPACE_END
#endif
......@@ -31,6 +31,7 @@
#include "namespace/interface/IView.hh"
#include "namespace/interface/ContainerIterators.hh"
#include "namespace/ns_quarkdb/Constants.hh"
#include "namespace/Resolver.hh"
#include "mgm/XrdMgmOfs.hh"
#include "mgm/Quota.hh"
#include "mgm/Stat.hh"
......@@ -551,52 +552,21 @@ NsCmd::TreeSizeSubcmd(const eos::console::NsProto_TreeSizeProto& tree,
eos::console::ReplyProto& reply)
{
using eos::console::NsProto_TreeSizeProto;
using eos::console::NsProto_ContainerSpecificationProto;
std::ostringstream oss;
eos::console::NsProto_ContainerSpecificationProto::ContainerCase cont_type =
tree.container().container_case();
eos::common::RWMutexWriteLock ns_wr_lock(gOFS->eosViewRWMutex);
std::shared_ptr<IContainerMD> cont {nullptr};
if (cont_type == NsProto_ContainerSpecificationProto::kPath) {
try {
// @todo (esindril): how to deal with symlinks
cont = gOFS->eosView->getContainer(tree.container().path());
} catch (const eos::MDException& e) {
oss << "error: " << e.what();
reply.set_std_err(oss.str());
reply.set_retc(e.getErrno());
return;
}
} else {
eos::IContainerMD::id_t cid = 0;
try {
if (cont_type == NsProto_ContainerSpecificationProto::kCid) {
cid = std::stoull(tree.container().cid(), nullptr, 10);
} else {
cid = std::stoull(tree.container().cxid(), nullptr, 16);
}
} catch (const std::exception& e) {
oss << "error: " << e.what();
reply.set_std_err(oss.str());
reply.set_retc(EINVAL);
return;
}
std::shared_ptr<IContainerMD> cont;
try {
cont = gOFS->eosDirectoryService->getContainerMD(cid);
} catch (const eos::MDException& e) {
oss << "error: " << e.what();
reply.set_std_err(oss.str());
reply.set_retc(e.getErrno());
return;
}
try {
cont = eos::Resolver::resolveContainer(gOFS->eosView, tree.container());
}
catch(const eos::MDException& e) {
reply.set_std_err(SSTR(e.what()));
reply.set_retc(e.getErrno());
return;
}
if (cont == nullptr) {
oss << "error: container not found";
reply.set_std_err(oss.str());
reply.set_std_err("error: container not found");
reply.set_retc(ENOENT);
return;
}
......
......@@ -25,8 +25,10 @@
# EosNsCommon-Sources library
#-------------------------------------------------------------------------------
include_directories(
${CMAKE_BINARY_DIR}
${CMAKE_SOURCE_DIR}
${XROOTD_INCLUDE_DIR}
${PROTOBUF_INCLUDE_DIRS}
${FOLLY_INCLUDE_DIRS}
)
......@@ -39,6 +41,7 @@ add_library(
PermissionHandler.cc PermissionHandler.hh
Prefetcher.cc Prefetcher.hh
Resolver.cc Resolver.hh
# Namespace interface
interface/IView.hh
......@@ -59,6 +62,8 @@ add_library(
utils/TestHelpers.cc
utils/Buffer.hh)
add_dependencies(EosNsCommon-Objects EosCliProto-Objects)
set_target_properties(
EosNsCommon-Objects
PROPERTIES
......@@ -74,6 +79,7 @@ target_include_directories(
target_link_libraries(
EosNsCommon PUBLIC
EosProtobuf
${Z_LIBRARY} fmt)
set_target_properties(
......@@ -101,6 +107,7 @@ if (Linux)
target_link_libraries(
EosNsCommon-Static PUBLIC
EosProtobuf
${Z_LIBRARY_STATIC} fmt)
set_target_properties(
......
/************************************************************************
* EOS - the CERN Disk Storage System *
* Copyright (C) 2018 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 <http://www.gnu.org/licenses/>.*
************************************************************************/
//------------------------------------------------------------------------------
//! @author Georgios Bitzes <georgios.bitzes@cern.ch>
//! @brief Utility to resolve files and containers based on proto messages
//------------------------------------------------------------------------------
#include "namespace/Resolver.hh"
#include "common/ParseUtils.hh"
EOSNSNAMESPACE_BEGIN
//------------------------------------------------------------------------------
//! Resolve a container specification message to a ContainerMD.
//! Assumes caller holds eosViewRWMutex.
//------------------------------------------------------------------------------
IContainerMDPtr Resolver::resolveContainer(IView *view, const ContainerSpecificationProto &proto) {
ContainerSpecificationProto::ContainerCase type = proto.container_case();
switch(type) {
case ContainerSpecificationProto::kPath: {
return view->getContainer(proto.path());
}
case ContainerSpecificationProto::kCid: {
int64_t cid;
if(!eos::common::parseInt64(proto.cid(), cid)) {
throw_mdexception(EINVAL, "Unable to parse Container ID: " << proto.cid());
}
return view->getContainerMDSvc()->getContainerMD(cid);
}
case ContainerSpecificationProto::kCxid: {
int64_t cid;
if(!eos::common::parseInt64(proto.cxid(), cid, 16)) {
throw_mdexception(EINVAL, "Unable to parse Container ID: " << proto.cxid());
}
return view->getContainerMDSvc()->getContainerMD(cid);
}
default: {
throw_mdexception(EINVAL, "Provided protobuf message is empty, unable to resolve container");
}
}
}
EOSNSNAMESPACE_END
/************************************************************************
* EOS - the CERN Disk Storage System *
* Copyright (C) 2018 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 <http://www.gnu.org/licenses/>.*
************************************************************************/
//------------------------------------------------------------------------------
//! @author Georgios Bitzes <georgios.bitzes@cern.ch>
//! @brief Utility to resolve files and containers based on proto messages
//------------------------------------------------------------------------------
#pragma once
#include <chrono>
#include "namespace/Namespace.hh"
#include "namespace/MDException.hh"
#include "namespace/interface/Identifiers.hh"
#include "namespace/interface/IView.hh"
#include "proto/Ns.pb.h"
EOSNSNAMESPACE_BEGIN
using ContainerSpecificationProto = eos::console::NsProto_ContainerSpecificationProto;
class Resolver {
public:
//----------------------------------------------------------------------------
//! Resolve a container specification message to a ContainerMD.
//! Assumes caller holds eosViewRWMutex.
//----------------------------------------------------------------------------
static IContainerMDPtr resolveContainer(IView *view, const ContainerSpecificationProto &proto);
};
EOSNSNAMESPACE_END
......@@ -24,8 +24,6 @@
#ifndef EOS_NS_CONTAINER_MD_HH
#define EOS_NS_CONTAINER_MD_HH
#define DBG(message) std::cerr << __FILE__ << ":" << __LINE__ << " -- " << #message << " = " << message << std::endl
#include "namespace/interface/IContainerMD.hh"
#include "namespace/interface/IFileMD.hh"
#include "namespace/ns_quarkdb/BackendClient.hh"
......
......@@ -28,6 +28,7 @@
#include "namespace/ns_quarkdb/tests/TestUtils.hh"
#include "namespace/utils/TestHelpers.hh"
#include "namespace/utils/RmrfHelper.hh"
#include "namespace/Resolver.hh"
#include <algorithm>
#include <cstdint>
#include <memory>
......@@ -223,6 +224,40 @@ TEST_F(HierarchicalViewF, ZeroSizedFilenames)
ASSERT_THROW(cont1->addContainer(cont2.get()), eos::MDException);
}
//------------------------------------------------------------------------------
// Test namespace resolver based on (path, cid, cxid)
//------------------------------------------------------------------------------
TEST_F(HierarchicalViewF, Resolver) {
// Make a lot of containers
for(size_t i = 0; i < 50; i++) {
view()->createContainer(SSTR("/dir" << i), true);
}
eos::ContainerSpecificationProto spec;
ASSERT_THROW(eos::Resolver::resolveContainer(view(), spec), eos::MDException);
spec.set_path("/dir49");
eos::IContainerMDPtr cont = eos::Resolver::resolveContainer(view(), spec);
ASSERT_EQ(cont->getName(), "dir49");
spec.set_cid("48");
cont = eos::Resolver::resolveContainer(view(), spec);
ASSERT_EQ(cont->getName(), "dir46");
spec.set_cxid("30");
cont = eos::Resolver::resolveContainer(view(), spec);
ASSERT_EQ(cont->getName(), "dir46");
spec.set_path("/chicken");
ASSERT_THROW(eos::Resolver::resolveContainer(view(), spec), eos::MDException);
spec.set_cid("chicken chicken");
ASSERT_THROW(eos::Resolver::resolveContainer(view(), spec), eos::MDException);
spec.set_cxid("chicken");
ASSERT_THROW(eos::Resolver::resolveContainer(view(), spec), eos::MDException);
}
TEST_F(HierarchicalViewF, QuotaTest)
{
srandom(time(nullptr));
......
......@@ -29,8 +29,6 @@
#include <functional>
#include <folly/executors/IOThreadPoolExecutor.h>
#define DBG(message) std::cerr << __FILE__ << ":" << __LINE__ << " -- " << #message << " = " << message << std::endl
using std::placeholders::_1;
#ifdef __APPLE__
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment