Move the reading environment variables to a new class. New class's implemented as singleton class. --- src/osaf/Makefile.am | 6 +- src/osaf/consensus/consensus.cc | 104 ++++++---------------- src/osaf/consensus/consensus.h | 12 +-- src/osaf/consensus/consensus_env.cc | 129 ++++++++++++++++++++++++++++ src/osaf/consensus/consensus_env.h | 56 ++++++++++++ 5 files changed, 219 insertions(+), 88 deletions(-) create mode 100644 src/osaf/consensus/consensus_env.cc create mode 100644 src/osaf/consensus/consensus_env.h
diff --git a/src/osaf/Makefile.am b/src/osaf/Makefile.am index 9d334b4a4..e60b33ae6 100644 --- a/src/osaf/Makefile.am +++ b/src/osaf/Makefile.am @@ -28,7 +28,8 @@ noinst_HEADERS += \ src/osaf/immutil/immutil.h \ src/osaf/saflog/saflog.h \ src/osaf/consensus/key_value.h \ - src/osaf/consensus/consensus.h + src/osaf/consensus/consensus.h \ + src/osaf/consensus/consensus_env.h # immtools headers # IMM configuration modifier @@ -67,7 +68,8 @@ lib_libosaf_common_la_SOURCES = \ src/osaf/immutil/immutil.c \ src/osaf/saflog/saflog.c \ src/osaf/consensus/key_value.cc \ - src/osaf/consensus/consensus.cc + src/osaf/consensus/consensus.cc \ + src/osaf/consensus/consensus_env.cc # immtools code # IMM configuration modifier diff --git a/src/osaf/consensus/consensus.cc b/src/osaf/consensus/consensus.cc index 0e37fa38d..9e32784ba 100644 --- a/src/osaf/consensus/consensus.cc +++ b/src/osaf/consensus/consensus.cc @@ -30,7 +30,7 @@ SaAisErrorT Consensus::PromoteThisNode(const bool graceful_takeover, TRACE_ENTER(); SaAisErrorT rc; - if (use_consensus_ == false) { + if (cfg_.use_consensus == false) { return SA_AIS_OK; } @@ -126,7 +126,7 @@ SaAisErrorT Consensus::RemoveTakeoverRequest() { SaAisErrorT Consensus::Demote(const std::string& node) { TRACE_ENTER(); - if (use_consensus_ == false) { + if (cfg_.use_consensus == false) { return SA_AIS_OK; } @@ -172,11 +172,11 @@ SaAisErrorT Consensus::DemoteThisNode() { return Demote(base::Conf::NodeName()); } -bool Consensus::IsEnabled() const { return use_consensus_; } +bool Consensus::IsEnabled() const { return cfg_.use_consensus; } bool Consensus::IsWritable() const { TRACE_ENTER(); - if (use_consensus_ == false) { + if (cfg_.use_consensus == false) { return true; } @@ -197,27 +197,29 @@ bool Consensus::IsWritable() const { } } -bool Consensus::IsRemoteFencingEnabled() const { return use_remote_fencing_; } +bool Consensus::IsRemoteFencingEnabled() const { + return cfg_.use_remote_fencing; +} bool Consensus::IsRelaxedNodePromotionEnabled() const { - return relaxed_node_promotion_; + return cfg_.relaxed_node_promotion; } bool Consensus::PrioritisePartitionSize() const { - return prioritise_partition_size_; + return cfg_.prioritise_partition_size; } uint32_t Consensus::PrioritisePartitionSizeWaitTime() const { - return prioritise_partition_size_mds_wait_time_; + return cfg_.prioritise_partition_size_mds_wait_time; } uint32_t Consensus::TakeoverValidTime() const { - return takeover_valid_time_; + return cfg_.takeover_valid_time; } std::string Consensus::CurrentActive() const { TRACE_ENTER(); - if (use_consensus_ == false) { + if (cfg_.use_consensus == false) { return ""; } @@ -252,78 +254,28 @@ Consensus::Consensus() { Consensus::~Consensus() {} void Consensus::ProcessEnvironmentSettings() { - uint32_t split_brain_enable = base::GetEnv("FMS_SPLIT_BRAIN_PREVENTION", 0); - plugin_path_ = base::GetEnv("FMS_KEYVALUE_STORE_PLUGIN_CMD", ""); - uint32_t use_remote_fencing = base::GetEnv("FMS_USE_REMOTE_FENCING", 0); - uint32_t prioritise_partition_size = - base::GetEnv("FMS_TAKEOVER_PRIORITISE_PARTITION_SIZE", 1); - uint32_t prioritise_partition_size_mds_wait_time = - base::GetEnv("FMS_TAKEOVER_PRIORITISE_PARTITION_SIZE_MDS_WAIT_TIME", 4); - uint32_t relaxed_node_promotion = - base::GetEnv("FMS_RELAXED_NODE_PROMOTION", 0); - config_file_ = base::GetEnv("FMS_CONF_FILE", ""); - - // if not specified in fmd.conf, - // takeover requests are valid for 20 seconds - takeover_valid_time_ = - base::GetEnv("FMS_TAKEOVER_REQUEST_VALID_TIME", 20); - // expiration time of takeover request is twice the max wait time - max_takeover_retry_ = takeover_valid_time_ / 2; - - if (split_brain_enable == 1 && plugin_path_.empty() == false) { - use_consensus_ = true; - } else { - use_consensus_ = false; - } - - if (use_remote_fencing == 1) { - use_remote_fencing_ = true; - } - - if (prioritise_partition_size == 0) { - prioritise_partition_size_ = false; - } + ConsensusEnv& env = ConsensusEnv::GetInstance(); - if (use_consensus_ == true && relaxed_node_promotion == 1) { - relaxed_node_promotion_ = true; - } - - prioritise_partition_size_mds_wait_time_ = - prioritise_partition_size_mds_wait_time; + cfg_ = env.GetConfiguration(); } bool Consensus::ReloadConfiguration() { - ConfigFileReader reader; - ConfigFileReader::SettingsMap map; + ConsensusEnv& env = ConsensusEnv::GetInstance(); - if (config_file_.empty() == true) { - LOG_ER("config file not defined"); + if (!env.ReloadConfiguration()) { return false; } - - map = reader.ParseFile(config_file_); - for (const auto& kv : map) { - if (kv.first.compare(0, kFmsEnvPrefix.size(), kFmsEnvPrefix) != 0) { - // we only care about environment variables beginning with 'FMS' - continue; - } - int rc; - TRACE("Setting '%s' to '%s'", kv.first.c_str(), kv.second.c_str()); - rc = setenv(kv.first.c_str(), kv.second.c_str(), 1); - osafassert(rc == 0); - } - ProcessEnvironmentSettings(); return true; } std::string Consensus::PluginPath() const { - return plugin_path_; + return cfg_.plugin_path; } bool Consensus::FenceNode(const std::string& node) { - if (use_remote_fencing_ == true) { + if (cfg_.use_remote_fencing == true) { LOG_WA("Fencing remote node %s", node.c_str()); // @todo currently passing UINT_MAX as node ID, since // we can't always obtain a valid node ID? @@ -339,7 +291,7 @@ bool Consensus::FenceNode(const std::string& node) { void Consensus::MonitorLock(ConsensusCallback callback, const uint32_t user_defined) { TRACE_ENTER(); - if (use_consensus_ == false) { + if (cfg_.use_consensus == false) { return; } @@ -349,7 +301,7 @@ void Consensus::MonitorLock(ConsensusCallback callback, void Consensus::MonitorTakeoverRequest(ConsensusCallback callback, const uint32_t user_defined) { TRACE_ENTER(); - if (use_consensus_ == false) { + if (cfg_.use_consensus == false) { return; } @@ -374,7 +326,7 @@ void Consensus::CheckForExistingTakeoverRequest() { // or until the takeover request is gone rc = ReadTakeoverRequest(tokens); while (rc == SA_AIS_OK && - retries < max_takeover_retry_) { + retries < cfg_.max_takeover_retry) { ++retries; TRACE("Takeover request still present"); std::this_thread::sleep_for(kSleepInterval); @@ -404,12 +356,12 @@ SaAisErrorT Consensus::CreateTakeoverRequest(const std::string& current_owner, SaAisErrorT rc; uint32_t retries = 0; rc = KeyValue::Create(kTakeoverRequestKeyname, takeover_request, - takeover_valid_time_); + cfg_.takeover_valid_time); while (rc == SA_AIS_ERR_FAILED_OPERATION && retries < kMaxRetry) { ++retries; std::this_thread::sleep_for(kSleepInterval); rc = KeyValue::Create(kTakeoverRequestKeyname, takeover_request, - takeover_valid_time_); + cfg_.takeover_valid_time); } if (rc == SA_AIS_ERR_EXIST) { @@ -422,7 +374,7 @@ SaAisErrorT Consensus::CreateTakeoverRequest(const std::string& current_owner, // or until the takeover request is gone rc = ReadTakeoverRequest(tokens); while (rc == SA_AIS_OK && - retries < max_takeover_retry_) { + retries < cfg_.max_takeover_retry) { ++retries; TRACE("Takeover request still present"); std::this_thread::sleep_for(kSleepInterval); @@ -451,7 +403,7 @@ SaAisErrorT Consensus::CreateTakeoverRequest(const std::string& current_owner, rc = SA_AIS_ERR_FAILED_OPERATION; // wait up to max_takeover_retry seconds for request to be answered retries = 0; - while (retries < max_takeover_retry_) { + while (retries < cfg_.max_takeover_retry) { std::vector<std::string> tokens; if (ReadTakeoverRequest(tokens) == SA_AIS_OK) { const std::string state = @@ -513,7 +465,7 @@ SaAisErrorT Consensus::WriteTakeoverResult( // previous value must match rc = KeyValue::Set(kTakeoverRequestKeyname, takeover_result, - takeover_request, takeover_valid_time_); + takeover_request, cfg_.takeover_valid_time); return rc; } @@ -578,7 +530,7 @@ Consensus::TakeoverState Consensus::HandleTakeoverRequest( const std::string& request) { TRACE_ENTER(); - if (use_consensus_ == false) { + if (cfg_.use_consensus == false) { return TakeoverState::UNDEFINED; } @@ -632,7 +584,7 @@ Consensus::TakeoverState Consensus::HandleTakeoverRequest( return TakeoverState::UNDEFINED; } - if (prioritise_partition_size_ == true) { + if (cfg_.prioritise_partition_size == true) { if (proposed_cluster_size > cluster_size) { result = TakeoverState::ACCEPTED; } else { diff --git a/src/osaf/consensus/consensus.h b/src/osaf/consensus/consensus.h index 1aba56157..d05d57780 100644 --- a/src/osaf/consensus/consensus.h +++ b/src/osaf/consensus/consensus.h @@ -20,6 +20,7 @@ #include <vector> #include "base/macros.h" #include "osaf/consensus/key_value.h" +#include "osaf/consensus/consensus_env.h" #include "saAis.h" class Consensus { @@ -98,18 +99,9 @@ class Consensus { const std::string& request); private: - bool use_consensus_{false}; - bool use_remote_fencing_{false}; - bool prioritise_partition_size_{true}; - uint32_t prioritise_partition_size_mds_wait_time_{4}; - bool relaxed_node_promotion_{false}; - uint32_t takeover_valid_time_{20}; - uint32_t max_takeover_retry_{0}; - std::string config_file_{}; - std::string plugin_path_{}; + ConsensusCfg cfg_; const std::string kTestKeyname = "opensaf_write_test"; - const std::string kFmsEnvPrefix = "FMS"; const std::chrono::milliseconds kSleepInterval = std::chrono::milliseconds(1000); // in ms static constexpr uint32_t kLockTimeout = 0; // lock is persistent by default diff --git a/src/osaf/consensus/consensus_env.cc b/src/osaf/consensus/consensus_env.cc new file mode 100644 index 000000000..72294ff81 --- /dev/null +++ b/src/osaf/consensus/consensus_env.cc @@ -0,0 +1,129 @@ +/* -*- OpenSAF -*- + * + * (C) Copyright 2018 Ericsson AB 2018 - All Rights Reserved. + * + * 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. This file and program are licensed + * under the GNU Lesser General Public License Version 2.1, February 1999. + * The complete license can be accessed from the following location: + * http://opensource.org/licenses/lgpl-license.php + * See the Copying file included with the OpenSAF distribution for full + * licensing terms. + * + */ +#include "osaf/consensus/consensus_env.h" +#include "base/getenv.h" +#include "base/logtrace.h" +#include "base/config_file_reader.h" + +ConsensusEnv& ConsensusEnv::GetInstance() { + TRACE_ENTER(); + static ConsensusEnv configuration; + + return configuration; +} + +ConsensusCfg ConsensusEnv::GetConfiguration() { + TRACE_ENTER(); + + m_NCS_LOCK(&lock_, NCS_LOCK_WRITE); + ConsensusCfg ret = cfg_; + m_NCS_UNLOCK(&lock_, NCS_LOCK_WRITE); + + return ret; +} + +bool ConsensusEnv::ReloadConfiguration() { + TRACE_ENTER(); + ConfigFileReader reader; + ConfigFileReader::SettingsMap map; + + m_NCS_LOCK(&lock_, NCS_LOCK_WRITE); + if (cfg_.config_file.empty() == true) { + m_NCS_UNLOCK(&lock_, NCS_LOCK_WRITE); + LOG_ER("config file not defined"); + return false; + } + map = reader.ParseFile(cfg_.config_file); + for (const auto& kv : map) { + if (kv.first.compare(0, kFmsEnvPrefix.size(), kFmsEnvPrefix) != 0) { + // we only care about environment variables beginning with 'FMS' + continue; + } + int rc; + TRACE("Setting '%s' to '%s'", kv.first.c_str(), kv.second.c_str()); + rc = setenv(kv.first.c_str(), kv.second.c_str(), 1); + osafassert(rc == 0); + } + LoadEnv(); + m_NCS_UNLOCK(&lock_, NCS_LOCK_WRITE); + + return true; +} + +ConsensusEnv::ConsensusEnv() { + TRACE_ENTER(); + + m_NCS_LOCK_INIT(&lock_); + m_NCS_LOCK(&lock_, NCS_LOCK_WRITE); + cfg_.use_consensus = false; + cfg_.use_remote_fencing = false; + cfg_.prioritise_partition_size = true; + cfg_.prioritise_partition_size_mds_wait_time = 4; + cfg_.relaxed_node_promotion = false; + cfg_.takeover_valid_time = 20; + cfg_.max_takeover_retry = 0; + cfg_.plugin_path = ""; + cfg_.config_file = ""; + LoadEnv(); + m_NCS_UNLOCK(&lock_, NCS_LOCK_WRITE); +} + +ConsensusEnv::~ConsensusEnv() { + TRACE_ENTER(); + + m_NCS_LOCK_DESTROY(&lock_); +} + +void ConsensusEnv::LoadEnv() { + TRACE_ENTER(); + uint32_t split_brain_enable = base::GetEnv("FMS_SPLIT_BRAIN_PREVENTION", 0); + cfg_.plugin_path = base::GetEnv("FMS_KEYVALUE_STORE_PLUGIN_CMD", ""); + uint32_t use_remote_fencing = base::GetEnv("FMS_USE_REMOTE_FENCING", 0); + uint32_t prioritise_partition_size = + base::GetEnv("FMS_TAKEOVER_PRIORITISE_PARTITION_SIZE", 1); + uint32_t prioritise_partition_size_mds_wait_time = + base::GetEnv("FMS_TAKEOVER_PRIORITISE_PARTITION_SIZE_MDS_WAIT_TIME", 4); + uint32_t relaxed_node_promotion = + base::GetEnv("FMS_RELAXED_NODE_PROMOTION", 0); + + cfg_.config_file = base::GetEnv("FMS_CONF_FILE", ""); + // if not specified in fmd.conf, + // takeover requests are valid for 20 seconds + cfg_.takeover_valid_time = + base::GetEnv("FMS_TAKEOVER_REQUEST_VALID_TIME", 20); + // expiration time of takeover request is twice the max wait time + cfg_.max_takeover_retry = cfg_.takeover_valid_time / 2; + + if (split_brain_enable == 1 && cfg_.plugin_path.empty() == false) { + cfg_.use_consensus = true; + } else { + cfg_.use_consensus = false; + } + + if (use_remote_fencing == 1) { + cfg_.use_remote_fencing = true; + } + + if (prioritise_partition_size == 0) { + cfg_.prioritise_partition_size = false; + } + + if (cfg_.use_consensus == true && relaxed_node_promotion == 1) { + cfg_.relaxed_node_promotion = true; + } + + cfg_.prioritise_partition_size_mds_wait_time = + prioritise_partition_size_mds_wait_time; +} diff --git a/src/osaf/consensus/consensus_env.h b/src/osaf/consensus/consensus_env.h new file mode 100644 index 000000000..964f98d66 --- /dev/null +++ b/src/osaf/consensus/consensus_env.h @@ -0,0 +1,56 @@ +/* -*- OpenSAF -*- + * + * (C) Copyright 2018 Ericsson AB 2018 - All Rights Reserved. + * + * 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. This file and program are licensed + * under the GNU Lesser General Public License Version 2.1, February 1999. + * The complete license can be accessed from the following location: + * http://opensource.org/licenses/lgpl-license.php + * See the Copying file included with the OpenSAF distribution for full + * licensing terms. + * + */ +#ifndef OSAF_CONSENSUS_CONSENSUS_ENV_H_ +#define OSAF_CONSENSUS_CONSENSUS_ENV_H_ + +#include <string> +#include "base/ncs_osprm.h" +#include "base/ncssysf_lck.h" + +typedef struct _ConsensusCfg { + bool use_consensus; + bool use_remote_fencing; + bool prioritise_partition_size; + uint32_t prioritise_partition_size_mds_wait_time; + bool relaxed_node_promotion; + uint32_t takeover_valid_time; + uint32_t max_takeover_retry; + std::string plugin_path; + std::string config_file; +} ConsensusCfg; + +class ConsensusEnv { + public: + // Get the instance of class + static ConsensusEnv &GetInstance(); + // Get a copy of configurations + ConsensusCfg GetConfiguration(); + // Update the environment variables from the configuration file, + // and update the configurations + bool ReloadConfiguration(); + virtual ~ConsensusEnv(); + + private: + NCS_LOCK lock_; + ConsensusCfg cfg_; + const std::string kFmsEnvPrefix = "FMS"; + + // Private instantiation + ConsensusEnv(); + // Load configurations from the environment variables + void LoadEnv(); +}; + +#endif // OSAF_CONSENSUS_CONSENSUS_ENV_H_ -- 2.17.1 _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel