Commit 9ec5ed6e authored by Eric Cano's avatar Eric Cano
Browse files

Added a configuration parameter class for taped.

Added a sourced parameter which keeps track of the origin of a parameter.
Ported parsing of configuration files from CASTOR.
parent 29f9c958
......@@ -21,7 +21,7 @@
#include "common/log/SyslogLogger.hpp"
#include "common/processCap/ProcessCap.hpp"
#include "tapeserver/daemon/CommandLineParams.hpp"
#include "tapeserver/daemon/GlobalConfiguration.hpp"
#include "tapeserver/daemon/TapedConfiguration.hpp"
#include "tapeserver/daemon/TpconfigLines.hpp"
#include "tapeserver/daemon/TapeDaemon.hpp"
......@@ -107,8 +107,8 @@ static int exceptionThrowingMain(
logStartOfDaemon(log, commandLine);
// Parse /etc/cta/cta.conf and /etc/cta/TPCONFIG for global parameters
const GlobalConfiguration globalConfig =
GlobalConfiguration::createFromCtaConf(commandLine.configFileLocation, log);
const TapedConfiguration globalConfig =
TapedConfiguration::createFromCtaConf(commandLine.configFileLocation, log);
// Create the object providing utilities for working with UNIX capabilities
cta::server::ProcessCap capUtils;
......
......@@ -3,13 +3,15 @@ cmake_minimum_required (VERSION 2.6)
add_library(ctatapedaemon
CommandLineParams.cpp
ConfigurationFile.cpp
GlobalConfiguration.cpp
SourcedParameter.cpp
TapedConfiguration.cpp
TapeDaemon.cpp
TpconfigLine.cpp
TpconfigLines.cpp)
add_library(ctadaemonunittests SHARED
ConfigurationFileTests.cpp)
ConfigurationFileTests.cpp
TapedConfigurationTests.cpp)
target_link_libraries(ctadaemonunittests
ctatapedaemon
......
/*
* The CERN Tape Archive (CTA) project
* Copyright (C) 2015 CERN
*
* 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/>.
*/
#include "tapeserver/daemon/SourcedParameter.hpp"
namespace cta {
namespace tape {
namespace daemon {
template<>
void SourcedParameter<time_t>::set(const std::string & value, const std::string & source) {
if (!utils::isValidUInt(value)) {
std::stringstream err;
err << "In SourcedParameter::set: badly formatted integer"
<< " for category=" << m_category << " key=" << m_key
<< " value=\'" << value << "'";
throw BadlyFormattedInteger(err.str());
}
std::istringstream(value) >> m_value;
m_source = source;
m_set = true;
}
template<>
void SourcedParameter<std::string>::set(const std::string & value, const std::string & source) {
m_value = value;
m_source = source;
m_set = true;
}
}}} // namespace cta::tape::daemon
\ No newline at end of file
/*
* The CERN Tape Archive (CTA) project
* Copyright (C) 2015 CERN
*
* 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 "common/exception/Exception.hpp"
#include "tapeserver/daemon/ConfigurationFile.hpp"
#include "common/utils/utils.hpp"
#include <limits>
namespace cta {
namespace tape {
namespace daemon {
/**
* A templated class allowing the tracking of parameter with their source.
* If the parameter is not set (implicitly defined as the source being
* an empty string), access to the value will be denied (exception)
*/
template<class C>
class SourcedParameter {
public:
CTA_GENERATE_EXCEPTION_CLASS(MandatoryParameterNotDefined);
CTA_GENERATE_EXCEPTION_CLASS(UnsupportedParameterType);
CTA_GENERATE_EXCEPTION_CLASS(BadlyFormattedInteger);
/// Constructor for mandatory options (they do not have default values)
SourcedParameter(const std::string & category, const std::string & key):
m_category(category), m_key(key) {
if (std::is_arithmetic<C>::value) {
m_value=std::numeric_limits<C>::max();
}
}
/// Constructor for optional options (they have default values)
SourcedParameter(const std::string & category, const std::string & key,
const C & value, const std::string & source):
m_category(category), m_key(key), m_value(value), m_source(source), m_set(true) {}
C operator() () {
if (m_set) return m_value;
throw MandatoryParameterNotDefined(std::string("In SourcedParameter::operator(): "
"value not defined for parameter \'" + m_category + "\' :"));
}
/// Function setting the parameter from a string (with integer interpretation)
void set(const std::string & value, const std::string & source);
/// Try and find the entry from the configuration file. Throw an exception for missing mandatory options.
void setFromConfigurationFile(ConfigurationFile & configFile, const std::string & configFilePath) {
try {
auto & entry = configFile.entries.at(m_category).at(m_key);
std::stringstream source;
source << configFilePath << ":" << entry.line;
set(entry.value, source.str());
} catch (std::out_of_range &) {
// If the config entry has a default, it's fine. If not, throw an exception.
if (m_set) return;
std::stringstream err;
err << "In SourcedParameter::setFromConfigurationFile: mandatory parameter not found: "
<< "category=" << m_category << " key=" << m_key << " configFilePath=" << configFilePath;
throw MandatoryParameterNotDefined(err.str());
}
}
const C & value() { return m_value; }
const std::string & category() { return m_category; }
const std::string & key() { return m_key; }
const std::string & source() { return m_source; }
private:
std::string m_category; ///< The category of the parameter
std::string m_key; ///< The key of the parameter
C m_value; ///< The value of the parameter
std::string m_source; ///< The source from which the parameter was gotten.
bool m_set = false; ///< Flag checking if the parameter was ever set.
};
}}} // namespace cta::tape::daemon
\ No newline at end of file
......@@ -26,7 +26,7 @@ namespace cta { namespace tape { namespace daemon {
TapeDaemon::TapeDaemon(const cta::daemon::CommandLineParams & commandLine,
log::Logger& log,
const GlobalConfiguration& globalConfig,
const TapedConfiguration& globalConfig,
cta::server::ProcessCap& capUtils):
cta::server::Daemon(log),
m_globalConfiguration(globalConfig), m_capUtils(capUtils),
......
......@@ -20,7 +20,7 @@
#include "common/threading/Daemon.hpp"
#include "tapeserver/daemon/CommandLineParams.hpp"
#include "tapeserver/daemon/GlobalConfiguration.hpp"
#include "tapeserver/daemon/TapedConfiguration.hpp"
#include "common/processCap/ProcessCap.hpp"
#include <signal.h>
......@@ -42,7 +42,7 @@ public:
TapeDaemon(
const cta::daemon::CommandLineParams & commandLine,
log::Logger &log,
const GlobalConfiguration &globalConfig,
const TapedConfiguration &globalConfig,
cta::server::ProcessCap &capUtils);
virtual ~TapeDaemon();
......@@ -226,7 +226,7 @@ protected:
throw();
/** The tape server's configuration */
const GlobalConfiguration& m_globalConfiguration;
const TapedConfiguration& m_globalConfiguration;
/**
* Object providing utilities for working UNIX capabilities.
......
......@@ -16,34 +16,39 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "GlobalConfiguration.hpp"
#include "TapedConfiguration.hpp"
#include "ConfigurationFile.hpp"
namespace cta { namespace tape { namespace daemon {
GlobalConfiguration GlobalConfiguration::createFromCtaConf(cta::log::Logger& log) {
//------------------------------------------------------------------------------
// GlobalConfiguration::createFromCtaConf w/o path
//------------------------------------------------------------------------------
TapedConfiguration TapedConfiguration::createFromCtaConf(cta::log::Logger& log) {
return createFromCtaConf("/etc/cta/cta.conf", log);
}
GlobalConfiguration GlobalConfiguration::createFromCtaConf(
//------------------------------------------------------------------------------
// GlobalConfiguration::createFromCtaConf w path
//------------------------------------------------------------------------------
TapedConfiguration TapedConfiguration::createFromCtaConf(
const std::string& generalConfigPath, cta::log::Logger& log) {
GlobalConfiguration ret;
TapedConfiguration ret;
// Parse config file
ConfigurationFile cf(generalConfigPath);
// Extract configuration from parsed config file
// tpConfigPath: this element is optional
try {
ConfigurationFile::value_t & v = cf.entries.at("Taped").at("tpConfigPath");
std::stringstream src;
src << generalConfigPath << ":" << v.line;
ret.tpConfigPath.set(v.value, src.str());
} catch (...) {}
ret.tpConfigPath.setFromConfigurationFile(cf, generalConfigPath);
ret.wdIdleSessionTimer.setFromConfigurationFile(cf, generalConfigPath);
ret.wdMountMaxSecs.setFromConfigurationFile(cf, generalConfigPath);
ret.wdNoBlockMoveMaxSecs.setFromConfigurationFile(cf, generalConfigPath);
ret.wdScheduleMaxSecs.setFromConfigurationFile(cf, generalConfigPath);
ret.objectStoreURL.setFromConfigurationFile(cf, generalConfigPath);
ret.fileCatalogURL.setFromConfigurationFile(cf, generalConfigPath);
return ret;
}
GlobalConfiguration::GlobalConfiguration():
tpConfigPath("tpConfigPath", "/etc/cta/TPCONFIG", "Compile time default") {}
cta::log::DummyLogger GlobalConfiguration::gDummyLogger("");
//------------------------------------------------------------------------------
// GlobalConfiguration::gDummyLogger (static member)
//------------------------------------------------------------------------------
cta::log::DummyLogger TapedConfiguration::gDummyLogger("");
}}} // namespace cta::tape::daemon
......@@ -24,6 +24,7 @@
#include "DriveConfiguration.hpp"
#include "common/log/DummyLogger.hpp"
#include "common/exception/Exception.hpp"
#include "SourcedParameter.hpp"
namespace cta {
namespace tape {
......@@ -32,56 +33,50 @@ namespace daemon {
* Class containing all the parameters needed by the watchdog process
* to spawn a transfer session per drive.
*/
struct GlobalConfiguration {
static GlobalConfiguration createFromCtaConf(
struct TapedConfiguration {
static TapedConfiguration createFromCtaConf(
cta::log::Logger &log = gDummyLogger);
static GlobalConfiguration createFromCtaConf(
static TapedConfiguration createFromCtaConf(
const std::string & generalConfigPath,
cta::log::Logger & log = gDummyLogger);
// Default constructor.
GlobalConfiguration();
std::map<std::string, DriveConfiguration> driveConfigs;
/**
* A templated class allowing the tracking of parameter with their source.
* If the parameter is not set (implicitly defined as the source being
* an empty string), access to the value will be denied (exception)
*/
template<class C>
class SourcedParameter {
public:
CTA_GENERATE_EXCEPTION_CLASS(ParameterNotDefined);
SourcedParameter(const std::string & name): m_name(name) {
if (std::is_arithmetic<C>::value) {
m_value=std::numeric_limits<C>::max();
}
}
SourcedParameter(const std::string & name, C value, const std::string & source):
m_name(name), m_value(value), m_source(source) {}
C operator() () {
if (m_source.empty()) {
throw ParameterNotDefined(std::string("In SourcedParameter::operator(): "
"value not defined for parameter \'" + m_name + "\' :"));
}
return m_value;
}
void set(const std::string & value, const std::string & source) {
m_value = value;
m_source = source;
}
const std::string & name() { return m_name; }
const std::string & source() { return m_source; }
private:
std::string m_name;
C m_value;
std::string m_source;
};
//----------------------------------------------------------------------------
// The actual parameters:
SourcedParameter<std::string> tpConfigPath;
//----------------------------------------------------------------------------
// Basics: tp config
//----------------------------------------------------------------------------
/// Path to the file describing the tape drives (TPCONFIG)
SourcedParameter<std::string> tpConfigPath = decltype(tpConfigPath)
("taped" , "tpConfigPath", "/etc/cta/TPCONFIG", "Compile time default");
/// Extracted drives configuration.
std::map<std::string, DriveConfiguration> driveConfigs;
//----------------------------------------------------------------------------
// Watchdog: parameters for timeouts in various situations.
//----------------------------------------------------------------------------
/// Maximum time allowed to complete a single mount scheduling.
SourcedParameter<time_t> wdScheduleMaxSecs = decltype(wdScheduleMaxSecs)
("taped", "WatchdogScheduleMaxSecs", 60, "Compile time default");
/// Maximum time allowed to complete mount a tape.
SourcedParameter<time_t> wdMountMaxSecs =decltype(wdMountMaxSecs)
("taped", "WatchdogMountMaxSecs", 900, "Compile time default");
/// Maximum time allowed after mounting without a single tape block move
SourcedParameter<time_t> wdNoBlockMoveMaxSecs = decltype(wdNoBlockMoveMaxSecs)
("taped", "WatchdogNoBlockMoveMaxSecs", 1800, "Compile time default");
/// Time to wait after scheduling came up idle
SourcedParameter<time_t> wdIdleSessionTimer = decltype(wdIdleSessionTimer)
("taped", "WatchdogNoBlockMoveMaxSecs", 10, "Compile time default");
//----------------------------------------------------------------------------
// The central storage access configuration
//----------------------------------------------------------------------------
/// URL of the object store.
SourcedParameter<std::string> objectStoreURL = decltype(objectStoreURL)
("general", "ObjectStoreURL");
/// URL of the file catalog
SourcedParameter<std::string> fileCatalogURL = decltype(fileCatalogURL)
("general", "FileCatalogURL");
private:
/** A private dummy logger which will simplify the implementaion of the
/** A private dummy logger which will simplify the implementation of the
* functions (just unconditionally log things). */
static cta::log::DummyLogger gDummyLogger;
} ;
......
/*
* The CERN Tape Archive (CTA) project
* Copyright (C) 2015 CERN
*
* 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/>.
*/
#include <gtest/gtest.h>
#include "tapeserver/daemon/ConfigurationFile.hpp"
#include "tapeserver/daemon/TapedConfiguration.hpp"
#include "tests/TempFile.hpp"
namespace unitTests {
TEST(cta_Daemon, TapedConfiguration) {
TempFile incompleteConfFile, completeConfFile;
incompleteConfFile.stringFill(
"# My incomplete taped configuration file\n"
);
completeConfFile.stringFill(
"#A good enough configuration file for taped\n"
"general ObjectStoreURL vfsObjectStore:///tmp/dir\n"
"general FileCatalogURL sqliteFileCatalog:///tmp/dir2\n"
);
ASSERT_THROW(cta::tape::daemon::TapedConfiguration::createFromCtaConf(incompleteConfFile.path()),
cta::tape::daemon::SourcedParameter<std::string>::MandatoryParameterNotDefined);
auto completeConfig =
cta::tape::daemon::TapedConfiguration::createFromCtaConf(completeConfFile.path());
ASSERT_EQ(completeConfFile.path()+":2", completeConfig.objectStoreURL.source());
ASSERT_EQ("vfsObjectStore:///tmp/dir", completeConfig.objectStoreURL.value());
ASSERT_EQ(completeConfFile.path()+":3", completeConfig.fileCatalogURL.source());
ASSERT_EQ("sqliteFileCatalog:///tmp/dir2", completeConfig.fileCatalogURL.value());
}
} // namespace unitTests
\ No newline at end of file
Supports Markdown
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