//------------------------------------------------------------------------------
// File: IConfigEngine.hh
// Author: Andreas-Joachim Peters - CERN
//------------------------------------------------------------------------------
/************************************************************************
* EOS - the CERN Disk Storage System *
* Copyright (C) 2016 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 .*
************************************************************************/
#pragma once
#include "mgm/Namespace.hh"
#include "common/Logging.hh"
#include "XrdOuc/XrdOucString.hh"
#include "XrdOuc/XrdOucHash.hh"
#include
#include
//------------------------------------------------------------------------------
//! @brief Interface Class responsible to handle configuration (load, save,
//! publish)
//!
//! The XrdMgmOfs class runs an asynchronous thread which applies configuration
//! changes from a remote master MGM on the configuration object.
//------------------------------------------------------------------------------
EOSMGMNAMESPACE_BEGIN
//------------------------------------------------------------------------------
//! Config engine changelog interface
//------------------------------------------------------------------------------
class ICfgEngineChangelog : public eos::common::LogId
{
public:
//----------------------------------------------------------------------------
//! Constructor
//----------------------------------------------------------------------------
ICfgEngineChangelog()
{
mMutex.SetBlocking(true);
}
//----------------------------------------------------------------------------
//! Destructor
//----------------------------------------------------------------------------
virtual ~ICfgEngineChangelog() = default;
//----------------------------------------------------------------------------
//! Add entry to the changelog
//!
//! @param key entry action
//! @param value entry key
//! @param comment entry value
//----------------------------------------------------------------------------
virtual void AddEntry(const std::string& action, const std::string& key,
const std::string& value, const std::string& comment = "") = 0;
//----------------------------------------------------------------------------
//! Get tail of the changelog
//!
//! @param nlines number of lines to return
//! @param tail string to hold the response
//!
//! @return true if successful, otherwise false
//----------------------------------------------------------------------------
virtual bool Tail(unsigned int nlines, std::string& tail) = 0;
protected:
mutable eos::common::RWMutex mMutex; ///< Mutex protecting the config changes
};
//------------------------------------------------------------------------------
//! @brief Abstract class providing reset/load/store functionality
//------------------------------------------------------------------------------
class IConfigEngine : public eos::common::LogId
{
public:
//----------------------------------------------------------------------------
//! XrdOucHash callback function to apply a configuration value
//!
//! @param key configuration key
//! @param val configuration value
//! @param arg match pattern
//!
//! @return < 0 - the hash table item is deleted
//! = 0 - the next hash table item is processed
//! > 0 - processing stops and the hash table item is returned
//----------------------------------------------------------------------------
static int ApplyEachConfig(const char* key, XrdOucString* val,
XrdOucString* err);
//----------------------------------------------------------------------------
//! Construct key given prefix and input
//----------------------------------------------------------------------------
static std::string FormFullKey(const char* prefix, const char* key)
{
if (prefix) {
return SSTR(prefix << ":" << key);
}
return SSTR(key);
}
//----------------------------------------------------------------------------
//! Constructor
//----------------------------------------------------------------------------
IConfigEngine();
//----------------------------------------------------------------------------
//! Destructor
//----------------------------------------------------------------------------
virtual ~IConfigEngine() = default;
//----------------------------------------------------------------------------
//! Get tail of the changelog
//!
//! @param nlines number of lines to return
//! @param tail string to hold the response
//!
//! @return true if successful, otherwise false
//----------------------------------------------------------------------------
bool Tail(unsigned int nlines, std::string& tail)
{
if (!mChangelog) {
return false;
}
return mChangelog->Tail(nlines, tail);
}
//----------------------------------------------------------------------------
//! Load a given configuration file
//!
//! @param filename name of the file holding the configuration to be loaded
//! @param err string holding any errors
//! @param apply_stall_redirect if true then skip applying stall and redirect
//! rules from the configuration
//!
//! @return true if loaded successfully, otherwise false
//----------------------------------------------------------------------------
virtual bool LoadConfig(const std::string& filename, XrdOucString& err,
bool apply_stall_redirect = false) = 0;
//----------------------------------------------------------------------------
//! Save configuration to specified destination
//!
//! @param filename name of the file where the current configuration will be saved
//! @param overwrite force overwrite of if the file exists already
//! @param comment comments
//! @param err string holding any errors
//!
//! @return true if saved successfully, otherwise false
//----------------------------------------------------------------------------
virtual bool SaveConfig(std::string filename, bool overwrite,
const std::string& comment, XrdOucString& err) = 0;
//----------------------------------------------------------------------------
//! List all configurations
//!
//! @param configlist string holding the list of all configurations
//! @param showbackups if true then show also the backups
//!
//! @return true if listing successful, otherwise false
//----------------------------------------------------------------------------
virtual bool ListConfigs(XrdOucString& configlist,
bool showbackups = false) = 0;
//----------------------------------------------------------------------------
//! Do an autosave
//----------------------------------------------------------------------------
virtual bool AutoSave() = 0;
//----------------------------------------------------------------------------
//! Get a configuration value
//----------------------------------------------------------------------------
bool Get(const std::string& prefix, const std::string& key,
std::string& out);
//----------------------------------------------------------------------------
//! Set a configuration value
//!
//! @param prefix identifies the type of configuration parameter
//! @param key key of the configuration to set
//! @param val value of the configuration
//! @param from_local mark if change comes from local MGM or remote one
//! @param save_config mark if configuration should also be saved or not
//----------------------------------------------------------------------------
virtual void SetConfigValue(const char* prefix, const char* key,
const char* val, bool from_local = true,
bool save_config = true) = 0;
//----------------------------------------------------------------------------
//! Delete a configuration value
//!
//! @param prefix identifies the type of configuration parameter
//! @param key key of the configuration to delete
//! @param tochangelog if true add entry also to the changelog
//----------------------------------------------------------------------------
virtual void DeleteConfigValue(const char* prefix, const char* key,
bool tochangelog = true) = 0;
//----------------------------------------------------------------------------
//! Delete a configuration key from the responsible object
//!
//! @param key configuration key to be deleted
//----------------------------------------------------------------------------
void ApplyKeyDeletion(const char* key);
//----------------------------------------------------------------------------
//! Delete configuration matching the pattern
//!
//! @param prefix identifies the type of configuration parameter
//! @param match matching pattern
//----------------------------------------------------------------------------
void DeleteConfigValueByMatch(const char* prefix, const char* match);
//----------------------------------------------------------------------------
//! Apply a configuration definition - the configuration engine informs the
//! corresponding objects about the new values
//!
//! @param err object collecting any possible errors
//! @param apply_stall_redirect if true then skip applying stall and redirect
//! rules from the configuration
//!
//! @return true if successful, otherwise false
//----------------------------------------------------------------------------
bool ApplyConfig(XrdOucString& err, bool apply_stall_redirect = false);
//----------------------------------------------------------------------------
//! Dump method for selective configuration printing
//!
//! @param out output string
//! @param filename string holding the name of the config file to dump
//!
//! @return true if successful, otherwise false
//----------------------------------------------------------------------------
bool DumpConfig(XrdOucString& out, const std::string& filename);
//----------------------------------------------------------------------------
//! Reset the current configuration
//!
//! @param apply_stall_redirect
//----------------------------------------------------------------------------
void ResetConfig(bool apply_stall_redirect = true);
//----------------------------------------------------------------------------
//! Set the autosave mode
//----------------------------------------------------------------------------
inline void SetAutoSave(bool val)
{
mAutosave = val;
}
//----------------------------------------------------------------------------
//! Publish the given configuration change
//----------------------------------------------------------------------------
void PublishConfigChange(const std::string& key, const std::string& value);
//----------------------------------------------------------------------------
//! Publish the deletion of the given configuration key
//----------------------------------------------------------------------------
void PublishConfigDeletion(const std::string& key);
protected:
std::unique_ptr mChangelog; ///< Changelog object
//! Protect the static configuration definitions hash
std::recursive_mutex mMutex;
bool mAutosave; ///< Create autosave file for each change
XrdOucString mConfigFile = "default"; ///< Currently loaded configuration
//! Configuration definitions currently in memory
std::map sConfigDefinitions;
//----------------------------------------------------------------------------
//! Check if configuration key is deprecated
//----------------------------------------------------------------------------
bool IsDeprecated(const std::string& config_key) const;
//----------------------------------------------------------------------------
//! Filter out entries from the map
//----------------------------------------------------------------------------
void FilterDeprecated(std::map& map);
//----------------------------------------------------------------------------
//! Filter configuration
//!
//! @param out output representation of the configuration after filtering
//! @param cfg_name configuration name
//!
//! @return 0 if successful, otherwise errno
//----------------------------------------------------------------------------
virtual int FilterConfig(std::ostream& out, const std::string& cfg_name) = 0;
};
EOSMGMNAMESPACE_END