Commit 8468eabd authored by Steven Murray's avatar Steven Murray
Browse files

Removed ctautil and CastorConfiguration

parent 485a123f
......@@ -141,7 +141,6 @@ set_property(TARGET ctacommon PROPERTY VERSION "${CTA_LIBVERSION}")
install (TARGETS ctacommon DESTINATION usr/${CMAKE_INSTALL_LIBDIR})
target_link_libraries (ctacommon
ctautils
pthread
uuid
z
......
......@@ -196,7 +196,6 @@ The shared libraries
%{_libdir}/libctacatalogue.so*
%{_libdir}/libctacommon.so*
#TODO: merge util and common
%{_libdir}/libctautils.so*
%{_libdir}/libctascheduler.so*
%{_libdir}/libctaobjectstore.so*
%{_libdir}/libctamediachanger.so*
......
......@@ -76,7 +76,7 @@ add_library (ctaobjectstore SHARED
set_property(TARGET ctaobjectstore PROPERTY SOVERSION "${CTA_SOVERSION}")
set_property(TARGET ctaobjectstore PROPERTY VERSION "${CTA_LIBVERSION}")
target_link_libraries(ctaobjectstore rados json-c ctautils cryptopp)
target_link_libraries(ctaobjectstore rados json-c cryptopp)
set_source_files_properties(BackendRados.cpp PROPERTIES COMPILE_FLAGS -Wno-deprecated-declarations)
install (TARGETS ctaobjectstore DESTINATION usr/${CMAKE_INSTALL_LIBDIR})
......@@ -98,7 +98,7 @@ install(TARGETS ctaobjectstoreunittests DESTINATION usr/${CMAKE_INSTALL_LIBDIR})
add_executable(cta-objectstore-initialize cta-objectstore-initialize.cpp)
set_property(TARGET cta-objectstore-initialize APPEND PROPERTY INSTALL_RPATH ${PROTOBUF3_RPATH})
target_link_libraries(cta-objectstore-initialize
${PROTOBUF3_LIBRARIES} ctaobjectstore ctacommon ctautils)
${PROTOBUF3_LIBRARIES} ctaobjectstore ctacommon)
add_executable(cta-objectstore-list cta-objectstore-list.cpp)
set_property(TARGET cta-objectstore-list APPEND PROPERTY INSTALL_RPATH ${PROTOBUF3_RPATH})
......
......@@ -30,7 +30,7 @@ set_property(TARGET ctascheduler PROPERTY VERSION "${CTA_LIBVERSION}")
install (TARGETS ctascheduler DESTINATION usr/${CMAKE_INSTALL_LIBDIR})
target_link_libraries (ctascheduler ctacommon ctaobjectstore ${PROTOBUF3_LIBRARIES} ctautils ctaeos)
target_link_libraries (ctascheduler ctacommon ctaobjectstore ${PROTOBUF3_LIBRARIES} ctaeos)
#add_library (ctaschedulerutils SHARED
# _old_prototype_DummyScheduler.cpp)
......
......@@ -21,4 +21,3 @@ cmake_minimum_required (VERSION 2.6)
add_subdirectory (legacymsg)
add_subdirectory (messages)
add_subdirectory (tape)
add_subdirectory (utils)
/******************************************************************************
*
* This file is part of the Castor project.
* See http://castor.web.cern.ch/castor
*
* Copyright (C) 2003 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 2
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Implementation of the handling of the CASTOR configuration file
*
* @author Castor Dev team, castor-dev@cern.ch
*****************************************************************************/
#include "castor/common/CastorConfiguration.hpp"
#include "common/exception/NoEntry.hpp"
#include <algorithm>
#include <fstream>
#include <errno.h>
// Global configurations, indexed by original file name
std::map<std::string, castor::common::CastorConfiguration> s_castorConfigs;
// Lock for the global configuration
static pthread_mutex_t s_globalConfigLock = PTHREAD_MUTEX_INITIALIZER;
//------------------------------------------------------------------------------
// getConfig
//------------------------------------------------------------------------------
castor::common::CastorConfiguration&
castor::common::CastorConfiguration::getConfig(std::string fileName)
{
// This method is non thread safe, and is protected by the s_globalConfigLock
// lock
int rc = pthread_mutex_lock(&s_globalConfigLock);
if (0 != rc) {
cta::exception::Exception e;
e.getMessage() << "Failed to get CASTOR configuration:"
" Failed to take a lock on s_globalConfigLock";
throw e;
}
// take care to catch all exceptions so that the lock is not leaked
try {
// do we have this configuration already in cache ?
if (s_castorConfigs.end() == s_castorConfigs.find(fileName)) {
// no such configuration. Create it
s_castorConfigs.insert(std::make_pair(fileName,
CastorConfiguration(fileName)));
}
// we can now release the lock. Concurrent read only access is ok.
pthread_mutex_unlock(&s_globalConfigLock);
return s_castorConfigs[fileName];
} catch (...) {
// release the lock
pthread_mutex_unlock(&s_globalConfigLock);
// rethrow
throw;
}
}
//------------------------------------------------------------------------------
// constructor
//------------------------------------------------------------------------------
castor::common::CastorConfiguration::CastorConfiguration(std::string fileName)
: m_fileName(fileName),
m_lastUpdateTime(0) {
// create internal r/w lock
int rc = pthread_rwlock_init(&m_lock, NULL);
if (0 != rc) {
cta::exception::Exception e;
e.getMessage() << "CastorConfiguration constructor Failed"
": Failed to create internal r/w lock";
throw e;
}
}
//------------------------------------------------------------------------------
// copy constructor
//------------------------------------------------------------------------------
castor::common::CastorConfiguration::CastorConfiguration(
const CastorConfiguration & other) :
m_fileName(other.m_fileName), m_lastUpdateTime(other.m_lastUpdateTime),
m_config(other.m_config) {
// create a new internal r/w lock
int rc = pthread_rwlock_init(&m_lock, NULL);
if (0 != rc) {
cta::exception::Exception e;
e.getMessage() << "CastorConfiguration copy constructor failed"
": Failed to create a new internal r/w lock";
throw e;
}
}
//------------------------------------------------------------------------------
// destructor
//------------------------------------------------------------------------------
castor::common::CastorConfiguration::~CastorConfiguration() {
// relase read write lock
pthread_rwlock_destroy(&m_lock);
}
//------------------------------------------------------------------------------
// assignment operator
//------------------------------------------------------------------------------
castor::common::CastorConfiguration &
castor::common::CastorConfiguration::operator=(
const castor::common::CastorConfiguration & other)
{
m_fileName = other.m_fileName;
m_lastUpdateTime = other.m_lastUpdateTime;
m_config = other.m_config;
// create a new internal r/w lock
int rc = pthread_rwlock_init(&m_lock, NULL);
if (0 != rc) {
cta::exception::Exception e;
e.getMessage() << "Assignment operator of CastorConfiguration object failed"
": Failed to create a new internal r/w lock";
throw e;
}
return *this;
}
//------------------------------------------------------------------------------
// getConfEntString
//------------------------------------------------------------------------------
const std::string& castor::common::CastorConfiguration::getConfEntString(
const std::string &category, const std::string &key,
const std::string &defaultValue, cta::log::Logger *const log) {
try {
if (isStale()) {
tryToRenewConfig();
}
// get read lock
int rc = pthread_rwlock_rdlock(&m_lock);
if (0 != rc) {
cta::exception::Exception e;
e.getMessage() << "Failed to get configuration entry " << category << ":"
<< key << ": Failed to get read lock";
throw e;
}
// get the entry
std::map<std::string, ConfCategory>::const_iterator catIt = m_config.find(category);
if (m_config.end() != catIt) {
// get the entry
ConfCategory::const_iterator entIt = catIt->second.find(key);
if (catIt->second.end() != entIt) {
// release the lock
pthread_rwlock_unlock(&m_lock);
if(NULL != log) {
std::list<cta::log::Param> params = {
cta::log::Param("category", category),
cta::log::Param("key", key),
cta::log::Param("value", entIt->second),
cta::log::Param("source", m_fileName)};
(*log)(cta::log::INFO, "Configuration entry", params);
}
return entIt->second;
}
}
// no entry found
if(NULL != log) {
std::list<cta::log::Param> params = {
cta::log::Param("category", category),
cta::log::Param("key", key),
cta::log::Param("value", defaultValue),
cta::log::Param("source", "DEFAULT")};
(*log)(cta::log::INFO, "Configuration entry", params);
}
// Unlock and return default
pthread_rwlock_unlock(&m_lock);
} catch (cta::exception::Exception ex) {
// exception caught : Unlock and return default
pthread_rwlock_unlock(&m_lock);
// log the exception
if(NULL != log) {
std::list<cta::log::Param> params = {
cta::log::Param("category", category),
cta::log::Param("key", key),
cta::log::Param("value", defaultValue),
cta::log::Param("source", "DEFAULT")};
(*log)(cta::log::INFO, "Configuration entry", params);
}
} catch (...) {
// release the lock
pthread_rwlock_unlock(&m_lock);
throw;
}
return defaultValue;
}
//------------------------------------------------------------------------------
// getConfEntString
//------------------------------------------------------------------------------
const std::string& castor::common::CastorConfiguration::getConfEntString(
const std::string &category, const std::string &key, cta::log::Logger *const log) {
// check whether we need to reload the configuration
if (isStale()) {
tryToRenewConfig();
}
// get read lock
int rc = pthread_rwlock_rdlock(&m_lock);
if (0 != rc) {
cta::exception::Exception e;
e.getMessage() << "Failed to get configuration entry " << category << ":"
<< key << ": Failed to get read lock";
throw e;
}
// get the entry
try {
std::map<std::string, ConfCategory>::const_iterator catIt =
m_config.find(category);
if (m_config.end() == catIt) {
cta::exception::NoEntry e;
e.getMessage() << "Failed to get configuration entry " << category << ":"
<< key << ": Failed to find " << category << " category";
throw e;
}
// get the entry
ConfCategory::const_iterator entIt = catIt->second.find(key);
if (catIt->second.end() == entIt) {
cta::exception::NoEntry e;
e.getMessage() << "Failed to get configuration entry " << category << ":"
<< key << ": Failed to find " << key << " key";
throw e;
}
if(NULL != log) {
std::list<cta::log::Param> params = {
cta::log::Param("category", category),
cta::log::Param("key", key),
cta::log::Param("value", entIt->second),
cta::log::Param("source", m_fileName)};
(*log)(cta::log::INFO, "Configuration entry", params);
}
// release the lock
pthread_rwlock_unlock(&m_lock);
return entIt->second;
} catch (...) {
// release the lock
pthread_rwlock_unlock(&m_lock);
throw;
}
}
//------------------------------------------------------------------------------
// isStale
//------------------------------------------------------------------------------
bool castor::common::CastorConfiguration::isStale()
{
// get read lock
int rc = pthread_rwlock_rdlock(&m_lock);
if (0 != rc) {
cta::exception::Exception e;
e.getMessage() << "Failed to determine if CASTOR configuration is stale"
": Failed to get read lock";
throw e;
}
try {
// get the timeout
int timeout = getTimeoutNolock();
// release the lock
pthread_rwlock_unlock(&m_lock);
// return whether we should renew
return time(0) > m_lastUpdateTime + timeout;
} catch (...) {
// release the lock
pthread_rwlock_unlock(&m_lock);
throw;
}
}
//------------------------------------------------------------------------------
// tryToRenewConfig
//------------------------------------------------------------------------------
void castor::common::CastorConfiguration::tryToRenewConfig()
{
// we should probably renew. First take the write lock.
int rc = pthread_rwlock_wrlock(&m_lock);
if (0 != rc) {
cta::exception::Exception e;
e.getMessage() << "Failed to renew configuration cache"
": Failed to take write lock";
throw e;
}
// now check that we should really renew, because someone may have done it
// while we waited for the lock
try {
if (time(0) > m_lastUpdateTime + getTimeoutNolock()) {
// now we should really renew
renewConfigNolock();
}
} catch (...) {
// release the lock
pthread_rwlock_unlock(&m_lock);
throw;
}
// release the lock
pthread_rwlock_unlock(&m_lock);
return;
}
//------------------------------------------------------------------------------
// getTimeoutNolock
//------------------------------------------------------------------------------
int castor::common::CastorConfiguration::getTimeoutNolock()
{
// start with the default (300s = 5mn)
int timeout = 300;
// get value from config
std::map<std::string, ConfCategory>::const_iterator catIt =
m_config.find("Config");
if (m_config.end() != catIt) {
ConfCategory::const_iterator entIt = catIt->second.find("ExpirationDelay");
if (catIt->second.end() != entIt) {
// parse the timeout into an integer
timeout = atoi(entIt->second.c_str());
}
}
// return timeout
return timeout;
}
//------------------------------------------------------------------------------
// renewConfigNolock
//------------------------------------------------------------------------------
void castor::common::CastorConfiguration::renewConfigNolock()
{
// reset the config
m_config.clear();
// try to open the configuration file, throwing an exception if there is a
// failure
std::ifstream file(m_fileName.c_str());
if(file.fail()) {
cta::exception::Exception ex;
ex.getMessage() << __FUNCTION__ << " failed"
": Failed to open file"
": m_fileName=" << m_fileName;
throw ex;
}
std::string line;
while(std::getline(file, line)) {
// get rid of potential tabs
std::replace(line.begin(),line.end(),'\t',' ');
// get the category
std::istringstream sline(line);
std::string category;
if (!(sline >> category)) continue; // empty line
if (category[0] == '#') continue; // comment
// get the key
std::string key;
if (!(sline >> key)) continue; // no key on line
if (key[0] == '#') continue; // key commented
// get and store value
while (sline.get() == ' '){}; sline.unget(); // skip spaces
std::string value;
std::getline(sline, value, '#');
value.erase(value.find_last_not_of(" \n\r\t")+1); // right trim
m_config[category][key] = value;
}
m_lastUpdateTime = time(0);
}
/******************************************************************************
*
* This file is part of the Castor project.
* See http://castor.web.cern.ch/castor
*
* Copyright (C) 2003 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 2
* 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*
* Implementation of the handling of the CASTOR configuration file
*
* @author Castor Dev team, castor-dev@cern.ch
*****************************************************************************/
#pragma once
#include "common/exception/NoEntry.hpp"
#include "common/log/Logger.hpp"
#include "common/utils/utils.hpp"
#include "common/exception/Exception.hpp"
#include "common/exception/InvalidConfigEntry.hpp"
#include <string>
#include <map>
namespace castor {
namespace common {
/**
* represents a category from the CASTOR configuration file
*/
typedef std::map<std::string, std::string> ConfCategory;
/**
* a class representing the configuration of castor.
* This configurations is obtained from the local file given in the
* constructor and will be updated regularly. The time between two
* updates is taken from the Config/ExpirationDelay entry of the
* configuration itself and defaults to 5mn if no such entry is found
*/
class CastorConfiguration {
public:
/**
* static method for getting a given configuration
* @param fileName the name of the file to be used for filling this configuration
*/
static CastorConfiguration& getConfig(const std::string filename = "/etc/castor/castor.conf")
;
public:
/**
* constructor
* @param fileName the file that should be used to build the configuration
*/
CastorConfiguration(std::string fileName = "/etc/castor/castor.conf")
;
/**
* copy constructor
* @param other instance of CastorConfiguration class
*/
CastorConfiguration(const CastorConfiguration & other)
;
/**
* destrcutor
*/
virtual ~CastorConfiguration();
/**
* assignment operator
* @param other instance of CastorConfiguration class
*/
CastorConfiguration & operator=(const CastorConfiguration & other);
/**
* Retrieves a configuration entry.
*
* If this method is passed a logger object then it will log the value
* of the configuration entry together with an indication of whether the
* value was found in the castor configuration file or whether the
* specified default value was used instead.
*
* @param category the category of the entry
* @param key the key of the entry
* @param defaultValue the value to be returned if the configuration entry
* is not in the configuration file
* @param log pointer to NULL or an optional logger object
*/
const std::string& getConfEntString(const std::string &category,
const std::string &key, const std::string &defaultValue,
cta::log::Logger *const log = NULL);
/**
* Retrieves a configuration entry.
*
* Besides other possible exceptions, this method throws a
* cta::exception::NoEntry exception if the specified configuration
* entry is not in the configuration file.
*
* If this method is passed a logger object then this method will log the
* the value of the configuration entry.
*
* @param category the category of the entry
* @param key the key of the entry
* @param log pointer to NULL or an optional logger object
*/
const std::string& getConfEntString(const std::string &category,
const std::string &key, cta::log::Logger *const log = NULL);
/**
* Retrieves a configuration entry as an integer.
*
* If this method is passed a logger object then it will log the value
* of the configuration entry together with an indication of whether the
* value was found in the castor configuration file or whether the
* specified default value was used instead.
*
* @param category category of the configuration parameter
* @param name category of the configuration parameter
* @param defaultValue the value to be returned if the configuration entry
* is not in the configuration file
* @param log pointer to NULL or an optional logger object
* @return the integer value
*/
template<typename T> T getConfEntInt(const std::string &category,
const std::string &key, const T defaultValue,
cta::log::Logger *const log = NULL) {
std::string strValue;
try {
strValue = getConfEntString(category, key);
} catch(cta::exception::Exception &ex) {
if(NULL != log) {
std::list<cta::log::Param> params = {
cta::log::Param("category", category),
cta::log::Param("key", key),
cta::log::Param("value", defaultValue),
cta::log::Param("source", "DEFAULT")};
(*log)(cta::log::INFO, "Configuration entry", params);
}
return defaultValue;
}
if (!cta::utils::isValidUInt(strValue.c_str())) {
cta::exception::InvalidConfigEntry ex(category.c_str(),
key.c_str(), strValue.c_str());
ex.getMessage() << "Failed to get configuration entry " << category <<
":" << key << ": Value is not a valid unsigned integer: value=" <<
strValue;
throw ex;
}
T value;
std::stringstream ss;
ss << strValue.c_str();
ss >> value;
if(NULL != log) {
std::list<cta::log::Param> params = {