Ok, sure. But in that case I would argue that we keep the wrappers. I 
don't see re-writing this piece of code in C as an alternative - it 
would be a step in the wrong direction. I am using std::set in this 
code, and yes, of course there are implementations of common data 
structures like sets and maps in the C language. But since the C 
language lacks support for templates, any generic implementation of a 
container data structure will give you an interface where you have to 
work with void pointers. This means that you will have to do all the 
memory management yourself, and cast your pointers back and forth 
between void* and whatever data type you use. It is both ugly and error 
prone.

regards,
Anders Widell

On 03/31/2016 08:26 PM, Mathivanan Naickan Palanivelu wrote:
> Hi Anders,
>
> Thanks. But I don't intend to use this patch yet. The reasons being I have 
> already been working on some changes
> For the next release and I don't want those to be disturbed; secondly If I 
> intend to convert, I would
> Prefer to have a plan and not do it on the fly.
>
> So, you please go ahead to push your original patch (after fixing the return 
> type). I will look into the wrapper thing after FC.
>
> Cheers,
> Mathi.
>
>> -----Original Message-----
>> From: Anders Widell [mailto:anders.wid...@ericsson.com]
>> Sent: Thursday, March 31, 2016 8:00 PM
>> To: Mathivanan Naickan Palanivelu
>> Cc: opensaf-devel@lists.sourceforge.net
>> Subject: Re: [PATCH 2 of 2] clm: Supervise and when necessary activate
>> system controller functionality [#79]
>>
>> Hi!
>>
>> I did a quick stab at converting the CLM node agent to C++, and here is the
>> result (without the wrappers). Apply it on top of the patch that is already 
>> on
>> review.
>>
>> Due to the stricter type checking in C++, I actually bumped into a potential
>> bug: The function clmna_process_dummyup_msg() is declared to return a
>> value of type SaAisErrorT, but it actually returns the local variable "rc" 
>> which is
>> of type uint32_t, and has the possible values NCSCC_RC_SUCCESS and
>> NCSCC_RC_FAILURE. Maybe it works anyhow, but it clearly is a type mismatch
>> here.
>>
>> regards,
>> Anders Widell
>>
>> On 03/31/2016 03:50 PM, Anders Widell wrote:
>>> I don't like the wrappers either. :-) The alternative is to convert
>>> the whole CLM service to C++, in which case the wrappers will go away.
>>> I think this is the approach to take if you wish to get rid of the
>>> wrappers.
>>>
>>> / Anders W
>>>
>>> On 03/31/2016 03:08 PM, Mathivanan Naickan Palanivelu wrote:
>>>> Ack for the functional change related to startup and the idea of
>>>> election.
>>>> But, I do not favour introducing wrapper files.  I will try to give a
>>>> c version of The election code by tomorrow, if not we can push patch
>>>> 2 tomorrow and
>>>>    we can take it up after FC.
>>>>
>>>> Cheers,
>>>> Mathi.
>>>>
>>>>
>>>>> -----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.controll
>>>>> +++ er
>>>>> @@ -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) {


------------------------------------------------------------------------------
Transform Data into Opportunity.
Accelerate data analysis in your applications with
Intel Data Analytics Acceleration Library.
Click to learn more.
http://pubads.g.doubleclick.net/gampad/clk?id=278785471&iu=/4140
_______________________________________________
Opensaf-devel mailing list
Opensaf-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to