-----Original Message-----
From: Anders Widell [mailto:anders.wid...@ericsson.com]
Sent: Monday, February 29, 2016 8:39 PM
To: Mathivanan Naickan Palanivelu
Cc: opensaf-devel@lists.sourceforge.net
Subject: [PATCH 2 of 2] clm: Supervise and when necessary activate
system
controller functionality [#79]
osaf/services/infrastructure/nid/config/nodeinit.conf.controller
| 2 +-
osaf/services/saf/clmsv/config/clmna.conf | 8 +
osaf/services/saf/clmsv/nodeagent/Makefile.am | 11 +-
osaf/services/saf/clmsv/nodeagent/cb.h | 1 +
osaf/services/saf/clmsv/nodeagent/election_starter.cc | 142
++++++++++
osaf/services/saf/clmsv/nodeagent/election_starter.h | 94 ++++++
osaf/services/saf/clmsv/nodeagent/election_starter_wrapper.cc | 46
+++
osaf/services/saf/clmsv/nodeagent/election_starter_wrapper.h | 45 +++
osaf/services/saf/clmsv/nodeagent/evt.h | 5 +-
osaf/services/saf/clmsv/nodeagent/main.c | 101 +++++--
10 files changed, 421 insertions(+), 34 deletions(-)
Add support in the CLM node agent to supervise the existence of
ACTIVE and
STANDBY system controllers. When no ACTIVE or STANDBY controllers are
present, the CLM node agent will activate the controller
functionality by
setting the RDE role of the node with the lowest NODE_ID to ACTIVE.
diff --git
a/osaf/services/infrastructure/nid/config/nodeinit.conf.controller
b/osaf/services/infrastructure/nid/config/nodeinit.conf.controller
--- a/osaf/services/infrastructure/nid/config/nodeinit.conf.controller
+++ b/osaf/services/infrastructure/nid/config/nodeinit.conf.controller
@@ -54,6 +54,7 @@
###########################################################
##################
xxCLCCLIDIRxx/osaf-transport:TRANSPORT:S:xxCLCCLIDIRxx/osaf-
transport:6000:-6:2:1:start:stop
+xxCLCCLIDIRxx/osaf-clmna:CLMNA:S:xxCLCCLIDIRxx/osaf-
clmna:8000::9:1:sta
+rt:stop
xxCLCCLIDIRxx/osaf-rded:RDE:S:xxCLCCLIDIRxx/osaf-rded:12000:-
6:2:1:start:stop
xxCLCCLIDIRxx/osaf-fmd:HLFM:S:xxCLCCLIDIRxx/osaf-fmd:12000:-
6:2:1:start:stop
xxCLCCLIDIRxx/osaf-immd:IMMD:S:xxCLCCLIDIRxx/osaf-
immd:4000:4:2:1:start:stop
@@ -62,6 +63,5 @@ xxCLCCLIDIRxx/osaf-logd:LOGD:S:xxCLCCLID
xxCLCCLIDIRxx/osaf-ntfd:NTFD:S:xxCLCCLIDIRxx/osaf-
ntfd:4000:4:2:1:start:stop
xxCLCCLIDIRxx/osaf-plmd:PLMD:S:xxCLCCLIDIRxx/osaf-
plmd:6500:4:2:1:start:stop
xxCLCCLIDIRxx/osaf-clmd:CLMD:S:xxCLCCLIDIRxx/osaf-
clmd:192000:4:2:1:start:stop
-xxCLCCLIDIRxx/osaf-clmna:CLMNA:S:xxCLCCLIDIRxx/osaf-
clmna:4000::9:1:start:stop
xxCLCCLIDIRxx/osaf-amfd:AMFD:S:xxCLCCLIDIRxx/osaf-amfd:192000:-
6:0:1:start:stop
xxCLCCLIDIRxx/osaf-amfnd:AMFND:S:xxCLCCLIDIRxx/osaf-
amfnd:192000::0:1:start:stop
diff --git a/osaf/services/saf/clmsv/config/clmna.conf
b/osaf/services/saf/clmsv/config/clmna.conf
--- a/osaf/services/saf/clmsv/config/clmna.conf
+++ b/osaf/services/saf/clmsv/config/clmna.conf
@@ -9,5 +9,13 @@
# Healthcheck keys
export CLMNA_ENV_HEALTHCHECK_KEY="Default"
+# Time in milliseconds without an SC to wait before starting an
+election. CLMNA # will detect the presence of system controllers in
the
+cluster (ACTIVE and # STANDBY). If no system controller has been seen
+during the configured time # period, CLMNA will initate an election
+with the own node as a candidate for a # new active system controller.
+Note that lowering this value will increase the # risk of
split-brain. Values
lower than 5000 are not recommended.
+#export CLMNA_ELECTION_DELAY_TIME=5000
+
# Uncomment the next line to enable info level logging #args="--
loglevel=info"
diff --git a/osaf/services/saf/clmsv/nodeagent/Makefile.am
b/osaf/services/saf/clmsv/nodeagent/Makefile.am
--- a/osaf/services/saf/clmsv/nodeagent/Makefile.am
+++ b/osaf/services/saf/clmsv/nodeagent/Makefile.am
@@ -23,7 +23,9 @@ SUBDIRS = scripts
noinst_HEADERS = \
cb.h \
clmna.h \
- evt.h
+ evt.h \
+ election_starter.h \
+ election_starter_wrapper.h
osaf_execbindir = $(pkglibdir)
osaf_execbin_PROGRAMS = osafclmna
@@ -35,9 +37,12 @@ osafclmna_CPPFLAGS = \
osafclmna_SOURCES = \
main.c \
- amf.c
+ amf.c \
+ election_starter.cc \
+ election_starter_wrapper.cc
osafclmna_LDADD = \
$(top_builddir)/osaf/libs/common/clmsv/libclmsv_common.la \
$(top_builddir)/osaf/libs/core/libopensaf_core.la \
- $(top_builddir)/osaf/libs/saf/libSaAmf/libSaAmf.la
+ $(top_builddir)/osaf/libs/saf/libSaAmf/libSaAmf.la \
+ $(top_builddir)/osaf/libs/agents/infrastructure/rda/librda.la
diff --git a/osaf/services/saf/clmsv/nodeagent/cb.h
b/osaf/services/saf/clmsv/nodeagent/cb.h
--- a/osaf/services/saf/clmsv/nodeagent/cb.h
+++ b/osaf/services/saf/clmsv/nodeagent/cb.h
@@ -57,6 +57,7 @@ typedef struct clmna_cb_t {
tmr_t scale_out_retry_tmr;
bool is_scale_out_retry_tmr_running;
bool nid_started; /**< true if started by NID */
+ void* election_starter;
} CLMNA_CB;
diff --git a/osaf/services/saf/clmsv/nodeagent/election_starter.cc
b/osaf/services/saf/clmsv/nodeagent/election_starter.cc
new file mode 100644
--- /dev/null
+++ b/osaf/services/saf/clmsv/nodeagent/election_starter.cc
@@ -0,0 +1,142 @@
+/* -*- OpenSAF -*-
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * 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.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include "election_starter.h"
+#include <cassert>
+#include <cerrno>
+#include <cstdlib>
+#include <cstring>
+#include <set>
+#include "ncsgl_defs.h"
+#include "rda_papi.h"
+#include "nid_api.h"
+#include "logtrace.h"
+#include "base/getenv.h"
+
+const char* const ElectionStarter::service_name_[2] = {
+ "Node",
+ "Controller"
+};
+
+ElectionStarter::NodeCollection::NodeCollection()
+ : last_change(base::ReadMonotonicClock()) { }
+
+ElectionStarter::ElectionStarter(bool is_nid_started, uint32_t
own_node_id)
+ : election_delay_time_(
+ base::MillisToTimespec(
+ base::GetEnv("CLMNA_ELECTION_DELAY_TIME",
+ kDefaultElectionDelayTime))),
+ is_nid_started_{is_nid_started},
+ starting_election_{false},
+ last_election_start_attempt_(base::ReadMonotonicClock()),
+ own_node_id_{own_node_id},
+ controller_nodes_{},
+ nodes_with_lower_node_id_{},
+ nodes_with_greater_or_equal_node_id_{} { }
+
+void ElectionStarter::StartElection() {
+ TRACE_ENTER();
+ if (starting_election_ == false) {
+ LOG_NO("Starting to promote this node to a system controller");
+ starting_election_ = true;
+ if (is_nid_started_ && nid_notify(const_cast<char*>("CLMNA"),
+ NCSCC_RC_SUCCESS, nullptr) !=
+ NCSCC_RC_SUCCESS) {
+ LOG_ER("nid notify failed");
+ }
+ }
+ SaAmfHAStateT ha_state;
+ if (rda_get_role(&ha_state) == NCSCC_RC_SUCCESS &&
+ ha_state == SA_AMF_HA_QUIESCED) {
+ PCS_RDA_REQ rda_req;
+ rda_req.req_type = PCS_RDA_SET_ROLE;
+ rda_req.info.io_role = PCS_RDA_ACTIVE;
+ if (pcs_rda_request(&rda_req) == PCSRDA_RC_SUCCESS) {
+ starting_election_ = false;
+ }
+ }
+ last_election_start_attempt_ = base::ReadMonotonicClock();
+ TRACE_LEAVE();
+}
+
+ElectionStarter::NodeCollection& ElectionStarter::GetNodeCollection(
+ uint32_t node_id, ServiceType service_type) {
+ assert(service_type == Controller || service_type == Node);
+ if (service_type == Controller) {
+ return controller_nodes_;
+ } else if (node_id < own_node_id_) {
+ return nodes_with_lower_node_id_;
+ } else {
+ return nodes_with_greater_or_equal_node_id_;
+ }
+}
+
+void ElectionStarter::UpEvent(uint32_t node_id, ServiceType
+service_type) {
+ TRACE_ENTER2("%s up event on node %" PRIx32,
service_name_[service_type],
+ node_id);
+ NodeCollection& nodes = GetNodeCollection(node_id, service_type);
+ std::pair<std::set<uint32_t>::iterator, bool> result =
nodes.tree.insert(
+ node_id);
+ if (result.second) nodes.last_change = base::ReadMonotonicClock();
+ TRACE_LEAVE();
+}
+
+void ElectionStarter::DownEvent(uint32_t node_id, ServiceType
+service_type) {
+ TRACE_ENTER2("%s down event on node %" PRIx32,
service_name_[service_type],
+ node_id);
+ NodeCollection& nodes = GetNodeCollection(node_id, service_type);
+ std::set<uint32_t>::size_type result = nodes.tree.erase(node_id);
+ if (result != 0) nodes.last_change = base::ReadMonotonicClock();
+ TRACE_LEAVE();
+}
+
+timespec ElectionStarter::Poll() {
+ TRACE_ENTER();
+ timespec timeout = CalculateTimeRemainingUntilNextEvent();
+ if (timeout == base::kZeroSeconds) {
+ StartElection();
+ timeout = base::kOneHundredMilliseconds;
+ }
+ TRACE_LEAVE2("timeout = %f", base::TimespecToDouble(timeout));
+ return timeout;
+}
+
+timespec ElectionStarter::CalculateTimeRemainingUntilNextEvent() const
+{
+ timespec timeout;
+ if (controller_nodes_.tree.size() == 0 &&
+ nodes_with_lower_node_id_.tree.size() == 0) {
+ timeout =
+ base::Max(controller_nodes_.last_change +
election_delay_time_,
+ nodes_with_lower_node_id_.last_change +
election_delay_time_,
+ last_election_start_attempt_ +
+base::kOneHundredMilliseconds);
+ } else {
+ timeout = base::kTimespecMax;
+ }
+ return CalculateTimeRemainingUntil(timeout);
+}
+
+timespec ElectionStarter::CalculateTimeRemainingUntil(
+ const timespec& time_stamp) {
+ timespec current_time = base::ReadMonotonicClock();
+ if (time_stamp >= current_time) return time_stamp - current_time;
+ else return base::kZeroSeconds;
+}
diff --git a/osaf/services/saf/clmsv/nodeagent/election_starter.h
b/osaf/services/saf/clmsv/nodeagent/election_starter.h
new file mode 100644
--- /dev/null
+++ b/osaf/services/saf/clmsv/nodeagent/election_starter.h
@@ -0,0 +1,94 @@
+/* -*- OpenSAF -*-
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * 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.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#ifndef
OPENSAF_SERVICES_SAF_CLMSV_NODEAGENT_ELECTION_STARTER_H_
+#define
OPENSAF_SERVICES_SAF_CLMSV_NODEAGENT_ELECTION_STARTER_H_
+
+#include <stdint.h>
+#include <set>
+#include "base/macros.h"
+#include "base/time.h"
+
+class ElectionStarter {
+ DELETE_COPY_AND_MOVE_OPERATORS(ElectionStarter);
+ public:
+ enum ServiceType {
+ /**
+ * A service that runs on all nodes in the cluster, including
all system
+ * controller nodes.
+ */
+ Node,
+ /**
+ * A service that only runs on ACTIVE and STANDBY (i.e. not
spare) system
+ * controller nodes.
+ */
+ Controller
+ };
+
+ /**
+ * Report the service up event of a service which of type @a
service_type
on
+ * the node @a node_id. Note that you have to call Poll() after
calling this
+ * method.
+ */
+ ElectionStarter(bool is_nid_started, uint32_t own_node_id);
+ /**
+ * Report the service up event of a service which of type @a
service_type
on
+ * the node @a node_id. Note that you have to call Poll() after
calling this
+ * method.
+ */
+ void UpEvent(uint32_t node_id, ServiceType service_type);
+ /**
+ * Report the service down event of a service which of type @a
service_type
+ * on the node @a node_id. Note that you have to call Poll()
after calling
+ * this method.
+ */
+ void DownEvent(uint32_t node_id, ServiceType service_type);
+ /**
+ * Do the work and return the time you can wait until you need
to call Poll()
+ * again Note that you always have to call Poll() immediately
after any
+ * UpEvent() or DownEvent(), regardless of the return value from
any
previous
+ * call to Poll().
+ */
+ timespec Poll();
+
+ private:
+ static const uint64_t kDefaultElectionDelayTime = 5000;
+
+ struct NodeCollection {
+ NodeCollection();
+ std::set<uint32_t> tree;
+ timespec last_change;
+ };
+
+ void StartElection();
+ NodeCollection& GetNodeCollection(uint32_t node_id, ServiceType
+ service); timespec CalculateTimeRemainingUntilNextEvent() const;
+ static timespec CalculateTimeRemainingUntil(const timespec&
+ time_stamp);
+
+ timespec election_delay_time_;
+ bool is_nid_started_;
+ bool starting_election_;
+ timespec last_election_start_attempt_; uint32_t own_node_id_;
+
+ NodeCollection controller_nodes_;
+ NodeCollection nodes_with_lower_node_id_;
+ NodeCollection nodes_with_greater_or_equal_node_id_;
+ static const char* const service_name_[2]; };
+
+#endif /*
OPENSAF_SERVICES_SAF_CLMSV_NODEAGENT_ELECTION_STARTER_H_ */
diff --git
a/osaf/services/saf/clmsv/nodeagent/election_starter_wrapper.cc
b/osaf/services/saf/clmsv/nodeagent/election_starter_wrapper.cc
new file mode 100644
--- /dev/null
+++ b/osaf/services/saf/clmsv/nodeagent/election_starter_wrapper.cc
@@ -0,0 +1,46 @@
+/* -*- OpenSAF -*-
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * 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.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE
+#endif
+#include "election_starter_wrapper.h"
+#include "election_starter.h"
+
+void ElectionStarterUpEvent(void* instance, uint32_t node_id,
+ enum ElectionStarterServiceType service) {
+ static_cast<ElectionStarter*>(instance)->UpEvent(
+ node_id,
+ service == ElectionStarterServiceNode ?
+ ElectionStarter::Node : ElectionStarter::Controller); }
+
+void ElectionStarterDownEvent(void* instance, uint32_t node_id,
+ enum ElectionStarterServiceType service)
+{
+ static_cast<ElectionStarter*>(instance)->DownEvent(
+ node_id,
+ service == ElectionStarterServiceNode ?
+ ElectionStarter::Node : ElectionStarter::Controller); }
+
+struct timespec ElectionStarterPoll(void* instance) {
+ return static_cast<ElectionStarter*>(instance)->Poll();
+}
+
+void* ElectionStarterConstructor(bool is_nid_started, uint32_t
+own_node_id) {
+ return new ElectionStarter(is_nid_started, own_node_id); }
diff --git
a/osaf/services/saf/clmsv/nodeagent/election_starter_wrapper.h
b/osaf/services/saf/clmsv/nodeagent/election_starter_wrapper.h
new file mode 100644
--- /dev/null
+++ b/osaf/services/saf/clmsv/nodeagent/election_starter_wrapper.h
@@ -0,0 +1,45 @@
+/* -*- OpenSAF -*-
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * 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.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#ifndef
+OPENSAF_SERVICES_SAF_CLMSV_NODEAGENT_ELECTION_STARTER_WRAP
PER_H_
+#define
+OPENSAF_SERVICES_SAF_CLMSV_NODEAGENT_ELECTION_STARTER_WRAP
PER_H_
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <time.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum ElectionStarterServiceType {
+ ElectionStarterServiceNode,
+ ElectionStarterServiceController
+};
+
+void ElectionStarterUpEvent(void* instance, uint32_t node_id,
+ enum ElectionStarterServiceType service);
+void ElectionStarterDownEvent(void* instance, uint32_t node_id,
+ enum ElectionStarterServiceType
service);
+struct timespec ElectionStarterPoll(void* instance);
+void* ElectionStarterConstructor(bool is_nid_started, uint32_t
+own_node_id);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*
OPENSAF_SERVICES_SAF_CLMSV_NODEAGENT_ELECTION_STARTER_WRAPP
ER_H_ */
diff --git a/osaf/services/saf/clmsv/nodeagent/evt.h
b/osaf/services/saf/clmsv/nodeagent/evt.h
--- a/osaf/services/saf/clmsv/nodeagent/evt.h
+++ b/osaf/services/saf/clmsv/nodeagent/evt.h
@@ -24,7 +24,7 @@
typedef NCS_IPC_MSG CLMNA_MBX_MSG;
typedef enum clmna_evt_type {
CLMNA_EVT_INVALID = 0,
- CLMNA_EVT_DUMMY_MSG,
+ CLMNA_EVT_CHANGE_MSG,
CLMNA_EVT_MAX_MSG
} CLMNA_EVT_TYPE;
@@ -32,6 +32,9 @@ typedef struct clmna_evt_tags {
CLMNA_MBX_MSG next;
CLMNA_EVT_TYPE type;
bool caused_by_timer_expiry;
+ NCSMDS_CHG change;
+ NODE_ID node_id;
+ MDS_SVC_ID svc_id;
} CLMNA_EVT;
diff --git a/osaf/services/saf/clmsv/nodeagent/main.c
b/osaf/services/saf/clmsv/nodeagent/main.c
--- a/osaf/services/saf/clmsv/nodeagent/main.c
+++ b/osaf/services/saf/clmsv/nodeagent/main.c
@@ -16,6 +16,10 @@
*
*/
+#define _GNU_SOURCE
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
#include <stdbool.h>
#include "cb.h"
#include <ncs_main_papi.h>
@@ -30,7 +34,11 @@
#include "clmsv_enc_dec.h"
#include "evt.h"
#include "clmna.h"
-#include<errno.h>
+#include "osaf_poll.h"
+#include "osaf_time.h"
+#include "ncsgl_defs.h"
+#include "mds_papi.h"
+#include "election_starter_wrapper.h"
enum {
FD_TERM = 0,
@@ -47,7 +55,7 @@ static NCS_SEL_OBJ usr1_sel_obj;
#define CLMNA_MDS_SUB_PART_VERSION 1
-#define CLMS_NODEUP_WAIT_TIME 1000
+#define CLMS_NODEUP_WAIT_TIME 60000
#define CLMNA_SCALE_OUT_RETRY_TIME 100
#define CLMNA_SVC_PVT_SUBPART_VERSION 1 #define
CLMNA_WRT_CLMS_SUBPART_VER_AT_MIN_MSG_FMT 1 @@ -156,6
+164,36 @@ static uint32_t clmna_mds_rcv(struct ncs
return NCSCC_RC_SUCCESS;
}
+static void clmna_handle_mds_change_evt(bool caused_by_timer_expiry,
+ NCSMDS_CHG change, NODE_ID node_id, MDS_SVC_ID svc_id) {
+ if ((change == NCSMDS_NEW_ACTIVE || change == NCSMDS_UP) &&
+ svc_id == NCSMDS_SVC_ID_CLMS && clmna_cb->server_synced ==
false) {
+ if (clmna_process_dummyup_msg(caused_by_timer_expiry)
!= SA_AIS_OK) {
+ /* NID will anyway stop and retry */
+ LOG_ER("Exiting");
+ }
+ }
+
+ if (caused_by_timer_expiry == false &&
+ (change == NCSMDS_UP || change == NCSMDS_DOWN) &&
+ (svc_id == NCSMDS_SVC_ID_CLMNA || svc_id ==
NCSMDS_SVC_ID_RDE)) {
+ if (change == NCSMDS_UP) {
+ ElectionStarterUpEvent(clmna_cb->election_starter,
+ node_id,
+ svc_id ==
NCSMDS_SVC_ID_CLMNA ?
+ ElectionStarterServiceNode :
+ ElectionStarterServiceController);
+ } else {
+ ElectionStarterDownEvent(clmna_cb-
election_starter,
+ node_id,
+ svc_id ==
NCSMDS_SVC_ID_CLMNA ?
+ ElectionStarterServiceNode :
+
ElectionStarterServiceController);
+ }
+ }
+}
+
static uint32_t clmna_mds_svc_evt(struct ncsmds_callback_info
*mds_cb_info) {
TRACE_ENTER2("%d", mds_cb_info->info.svc_evt.i_change);
@@ -169,11 +207,6 @@ static uint32_t clmna_mds_svc_evt(struct
clmna_cb->clms_mds_dest = mds_cb_info-
info.svc_evt.i_dest;
TRACE("subpart version: %u", mds_cb_info-
info.svc_evt.i_rem_svc_pvt_ver);
TRACE("svc_id %d", mds_cb_info-
info.svc_evt.i_svc_id);
- evt = calloc(1, sizeof(CLMNA_EVT));
- evt->type = CLMNA_EVT_DUMMY_MSG;
- evt->caused_by_timer_expiry = false;
- if (m_NCS_IPC_SEND(&clmna_cb->mbx, evt,
NCS_IPC_PRIORITY_VERY_HIGH) != NCSCC_RC_SUCCESS)
- LOG_ER("IPC send to mailbox failed: %s",
__FUNCTION__);
break;
default:
break;
@@ -183,6 +216,17 @@ static uint32_t clmna_mds_svc_evt(struct
break;
}
+ evt = calloc(1, sizeof(CLMNA_EVT));
+ evt->type = CLMNA_EVT_CHANGE_MSG;
+ evt->caused_by_timer_expiry = false;
+ evt->change = mds_cb_info->info.svc_evt.i_change;
+ evt->node_id = mds_cb_info->info.svc_evt.i_node_id;
+ evt->svc_id = mds_cb_info->info.svc_evt.i_svc_id;
+ if (m_NCS_IPC_SEND(&clmna_cb->mbx, evt,
NCS_IPC_PRIORITY_VERY_HIGH) !=
+ NCSCC_RC_SUCCESS) {
+ LOG_ER("IPC send to mailbox failed: %s", __FUNCTION__);
+ }
+
TRACE_LEAVE();
return NCSCC_RC_SUCCESS;
}
@@ -302,7 +346,8 @@ static uint32_t clmna_mds_init(void)
NCSADA_INFO ada_info;
NCSMDS_INFO mds_info;
uint32_t rc = NCSCC_RC_SUCCESS;
- MDS_SVC_ID svc = NCSMDS_SVC_ID_CLMS;
+ MDS_SVC_ID svc[] = { NCSMDS_SVC_ID_CLMS,
NCSMDS_SVC_ID_CLMNA,
+ NCSMDS_SVC_ID_RDE };
TRACE_ENTER();
@@ -345,8 +390,8 @@ static uint32_t clmna_mds_init(void)
mds_info.i_op = MDS_SUBSCRIBE;
mds_info.info.svc_subscribe.i_scope = NCSMDS_SCOPE_NONE;
- mds_info.info.svc_subscribe.i_num_svcs = 1;
- mds_info.info.svc_subscribe.i_svc_ids = &svc;
+ mds_info.info.svc_subscribe.i_num_svcs = 3;
+ mds_info.info.svc_subscribe.i_svc_ids = svc;
rc = ncsmds_api(&mds_info);
if (rc != NCSCC_RC_SUCCESS) {
@@ -434,8 +479,11 @@ static void scale_out_tmr_exp(void *arg)
if (clmna_cb->is_scale_out_retry_tmr_running == true) {
CLMNA_EVT *evt = calloc(1, sizeof(CLMNA_EVT));
if (evt != NULL) {
- evt->type = CLMNA_EVT_DUMMY_MSG;
+ evt->type = CLMNA_EVT_CHANGE_MSG;
evt->caused_by_timer_expiry = true;
+ evt->change = NCSMDS_UP;
+ evt->node_id = 0;
+ evt->svc_id = NCSMDS_SVC_ID_CLMS;
if (m_NCS_IPC_SEND(&clmna_cb->mbx, evt,
NCS_IPC_PRIORITY_VERY_HIGH) !=
NCSCC_RC_SUCCESS)
LOG_ER("IPC send to mailbox failed: %s", @@
-567,17 +615,11 @@ void clmna_process_mbx(SYSF_MBX *mbx)
goto done;
}
switch (msg->type) {
- case CLMNA_EVT_DUMMY_MSG:
- if (clmna_cb->server_synced == false) {
- if (clmna_process_dummyup_msg(msg->
- caused_by_timer_expiry) != SA_AIS_OK) {
- /* NID will anyway stop and retry */
- LOG_ER("Exiting");
- free(msg);
- msg = NULL;
- } else
- goto done;
- }
+ case CLMNA_EVT_CHANGE_MSG:
+ clmna_handle_mds_change_evt(msg-
caused_by_timer_expiry,
+ msg->change,
+ msg->node_id,
+ msg->svc_id);
break;
default:
TRACE("Invalid message type");
@@ -673,6 +715,10 @@ int main(int argc, char *argv[])
goto done;
}
+ clmna_cb->election_starter =
+ ElectionStarterConstructor(clmna_cb->nid_started,
+ clmna_cb->node_info.node_id);
+
fds[FD_TERM].fd = term_fd;
fds[FD_TERM].events = POLLIN;
fds[FD_AMF].fd = clmna_cb->nid_started ?
@@ -682,14 +728,11 @@ int main(int argc, char *argv[])
fds[FD_MBX].events = POLLIN;
while (1) {
- ret = poll(fds, nfds, -1);
+ struct timespec timeout = ElectionStarterPoll(clmna_cb-
election_starter);
+ ret = osaf_ppoll(fds, nfds, &timeout, NULL);
- if (ret == -1) {
- if (errno == EINTR)
- continue;
-
- LOG_ER("%s: poll failed - %s", __FUNCTION__,
strerror(errno));
- break;
+ if (ret == 0) {
+ continue;
}
if (fds[FD_TERM].revents & POLLIN) {