Hi Mahesh See my new comments inline [Lennart]
Thanks Lennart > -----Original Message----- > From: A V Mahesh [mailto:mahesh.va...@oracle.com] > Sent: den 3 augusti 2016 08:21 > To: Lennart Lund <lennart.l...@ericsson.com>; Vu Minh Nguyen > <vu.m.ngu...@dektech.com.au>; Anders Widell > <anders.wid...@ericsson.com> > Cc: opensaf-devel@lists.sourceforge.net > Subject: Re: [PATCH 2 of 3] lgs: director Cluster Membership (CLM) > integration [#1638] V2 > > Hi Lennart, > > I just incorporated possible comments based on the current code base, > This My fist patch for LOG :) , so I just followed how existing > functions/variables organized like. > > I will considered all other inputs while doing complete refracting code > to C++ in a separate ticket soon. > > Please see also inline response [AVM] > > -AVM > > On 8/2/2016 6:30 PM, Lennart Lund wrote: > > Hi > > > > My comments for patch 2 > > > > I have found some things that should be considered in order to get as clean > code as possible: > > 1. > > Functions for handling CLM can be found in several files. It is better to > collect all CLM handling in the lgs_clm file and just include function calls > in the > rest of the code. Also all functions that shall be globally available should > have > a prototype in the corresponding lgs_clm.h file > [AVM] I will considered all your inputs while doing complete > refracting code to C++ in a separate ticket soon. [Lennart] I still think you should do this now. It will also make it easier to do the refactoring later > > 2. > > New global variables are added to the cb structure. Do not use global > variables try at least to keep the scope of state variables, flags and other > variables within the lgs_clm file. Implement setter and getter functions if > needed or even better functions that are using the variables e.g. like the > is_client_clm_member() function. This also makes it possible to make these > functions thread safe (do not use the global cb lock mutex). which means > > that this can be handled in one place instead of all over the code > [AVM] I moved the stuff that is possible based on current code base of > LOG service , i will take care of your suggestions while doing complete > refracting code to C++ in a separate ticket soon. [Lennart] As mentioned in 1) I still think you should do this now > > 3. > > Take advantage of C++ and make simpler handling of lists. It's no longer > needed to use patricia tree handling > > Maybe even create a LgsClm class? > [AVM] Same comment was give by Anders Widell as well. > I will do all NCS_PATRICIA_TREE conversion to std::map of > Log service in one go in a separate ticket soon. [Lennart] Why not now? There will be less and simpler code > > > > See also inline comments [Lennart] > > > > Thanks > > Lennart > > > >> -----Original Message----- > >> From: mahesh.va...@oracle.com [mailto:mahesh.va...@oracle.com] > >> Sent: den 2 augusti 2016 10:18 > >> To: Vu Minh Nguyen <vu.m.ngu...@dektech.com.au>; Lennart Lund > >> <lennart.l...@ericsson.com>; Anders Widell > <anders.wid...@ericsson.com> > >> Cc: opensaf-devel@lists.sourceforge.net > >> Subject: [PATCH 2 of 3] lgs: director Cluster Membership (CLM) > integration > >> [#1638] V2 > >> > >> osaf/services/saf/logsv/lgs/Makefile.am | 7 +- > >> osaf/services/saf/logsv/lgs/lgs_cb.h | 15 +++ > >> osaf/services/saf/logsv/lgs/lgs_clm.cc | 142 > >> +++++++++++++++++++++++++++++++ > >> osaf/services/saf/logsv/lgs/lgs_clm.h | 25 +++++ > >> osaf/services/saf/logsv/lgs/lgs_evt.cc | 143 > >> ++++++++++++++++++++++++++++++++ > >> osaf/services/saf/logsv/lgs/lgs_evt.h | 2 + > >> osaf/services/saf/logsv/lgs/lgs_main.cc | 28 ++++++ > >> osaf/services/saf/logsv/lgs/lgs_mds.cc | 38 ++++++++- > >> osaf/services/saf/logsv/lgs/lgs_util.cc | 83 ++++++++++++++++++ > >> 9 files changed, 480 insertions(+), 3 deletions(-) > >> > >> > >> diff --git a/osaf/services/saf/logsv/lgs/Makefile.am > >> b/osaf/services/saf/logsv/lgs/Makefile.am > >> --- a/osaf/services/saf/logsv/lgs/Makefile.am > >> +++ b/osaf/services/saf/logsv/lgs/Makefile.am > >> @@ -37,7 +37,8 @@ noinst_HEADERS = \ > >> lgs_mbcsv_v3.h \ > >> lgs_mbcsv_v5.h \ > >> lgs_recov.h \ > >> - lgs_imm_gcfg.h > >> + lgs_imm_gcfg.h \ > >> + lgs_clm.h > >> > >> osaf_execbindir = $(pkglibdir) > >> osaf_execbin_PROGRAMS = osaflogd > >> @@ -67,7 +68,8 @@ osaflogd_SOURCES = \ > >> lgs_mbcsv_v3.cc \ > >> lgs_mbcsv_v5.cc \ > >> lgs_recov.cc \ > >> - lgs_imm_gcfg.cc > >> + lgs_imm_gcfg.cc \ > >> + lgs_clm.cc > >> > >> osaflogd_LDADD = \ > >> $(top_builddir)/osaf/tools/safimm/src/libimmutil.la \ > >> @@ -75,4 +77,5 @@ osaflogd_LDADD = \ > >> $(top_builddir)/osaf/libs/saf/libSaAmf/libSaAmf.la \ > >> $(top_builddir)/osaf/libs/saf/libSaImm/libSaImmOi.la \ > >> $(top_builddir)/osaf/libs/saf/libSaImm/libSaImmOm.la \ > >> + $(top_builddir)/osaf/libs/saf/libSaClm/libSaClm.la \ > >> $(top_builddir)/osaf/libs/agents/infrastructure/rda/librda.la > >> diff --git a/osaf/services/saf/logsv/lgs/lgs_cb.h > >> b/osaf/services/saf/logsv/lgs/lgs_cb.h > >> --- a/osaf/services/saf/logsv/lgs/lgs_cb.h > >> +++ b/osaf/services/saf/logsv/lgs/lgs_cb.h > >> @@ -21,6 +21,7 @@ > >> #include <stdbool.h> > >> #include <saLog.h> > >> #include <saImmOi.h> > >> +#include <saClm.h> > >> #include <mbcsv_papi.h> > >> #include <ncs_edu_pub.h> > >> > >> @@ -55,6 +56,11 @@ typedef struct lgs_stream_list { > >> } lgs_stream_list_t; > >> > >> typedef struct { > >> + NCS_PATRICIA_NODE patnode; > >> + NODE_ID node_id; > >> +} lgs_clm_node_t; > >> + > > [Lennart] Would it be possible to not add new patricia node handling? Since > the log service is compiled as C++ code C++ list tools could be used instead? > > lgs_clm_node_find > [AVM] Same comment was give by Anders Widell as well. > I will do all NCS_PATRICIA_TREE conversion to std::map of > Log service in one go in a separate ticket soon. > >> +typedef struct { > >> NCS_PATRICIA_NODE pat_node; > >> uint32_t client_id; > >> uint32_t client_id_net; > >> @@ -73,6 +79,7 @@ typedef struct lgs_cb { > >> MDS_DEST vaddr; /* My identification in MDS > >> */ > >> SaVersionT log_version; /* The version currently supported > >> */ > >> NCS_PATRICIA_TREE client_tree; /* LGA/Library/Client > >> instantiation pat. tree */ > >> + NCS_PATRICIA_TREE clm_node_tree; /* LGA/Library/Client > >> instantiation pat. tree */ > >> SaNameT comp_name; /* Components's name LGS */ > >> SaAmfHandleT amf_hdl; /* AMF handle, obtained thru AMF > >> init */ > >> SaSelectionObjectT amfSelectionObject; /* Selection Object to > >> wait for AMF events */ > >> @@ -80,6 +87,9 @@ typedef struct lgs_cb { > >> bool is_quiesced_set; > >> SaImmOiHandleT immOiHandle; /* IMM OI handle > >> */ > >> SaSelectionObjectT immSelectionObject; /* Selection Object to > >> wait for IMM events */ > >> + SaSelectionObjectT clmSelectionObject; /* Selection Object to wait > >> for clms events */ > >> + SaClmHandleT clm_hdl; /* CLM handle, obtained through CLM init > >> */ > >> + bool clm_initialized; //For CLM init status; > > [Lennart] Why adding new globals? At least this one is not needed. This > variable could be declared locally in lgs_clm.cc only if the is_clm_init() > function is moved from lgs_util.cc to lgs_clm.cc. Try to keep CLM handling > code in one place (could be a class) and avoid global varaibles (avoid using > the > cb structure as an all-purpose "slask" global if possible) > [AVM] clm_initialized is Agent wide information this will used future > purposes like all services concurrently starting ect.. [Lennart] Ok but it can still be placed locally in the lgs_clm.c file and be handled via functions that also implement needed thread safe handling. Please do not add new global variables > > >> SaAmfHAStateT ha_state; /* present AMF HA state of the > >> component */ > >> uint32_t last_client_id; /* Value of last client_id assigned > >> */ > >> uint32_t async_upd_cnt; /* Async Update Count for Warmsync > >> */ > >> @@ -94,6 +104,7 @@ typedef struct lgs_cb { > >> down events > >> Processing */ > >> LGA_DOWN_LIST *lga_down_list_tail; > >> > >> + NCS_SEL_OBJ clm_init_sel_obj; /* Selection object for CLM > >> initialization.*/ > >> bool nid_started; /**< true if started by NID */ > >> SaUint32T scAbsenceAllowed; /* OpenSAF global configuration for > >> recovery handling */ > >> lgs_state_t lgs_recovery_state; /* Indicate current recovery state for > >> the server */ > >> @@ -106,5 +117,9 @@ typedef struct lgs_cb { > >> extern uint32_t lgs_cb_init(lgs_cb_t *); > >> extern void lgs_process_mbx(SYSF_MBX *mbx); > >> extern uint32_t lgs_stream_add(lgs_cb_t *cb, log_stream_t *stream); > >> +extern uint32_t lgs_clm_node_del(NODE_ID node_id); > >> +extern uint32_t lgs_clm_node_add(NODE_ID node_id); > >> +extern uint32_t lgs_clm_node_find(NODE_ID node_id); > >> +extern bool is_client_clm_member(NODE_ID node_id, SaVersionT > *ver); > > [Lennart] Does the function protoypes really belongs here? The code can > be found in lgs_evt.cc and lgs_util.cc but probably belongs to the lgs_clm.cc > file and the prototypes should be in the lgs_clm.h file? > [AVM] Moved. > > > >> #endif > >> diff --git a/osaf/services/saf/logsv/lgs/lgs_clm.cc > >> b/osaf/services/saf/logsv/lgs/lgs_clm.cc > >> new file mode 100644 > >> --- /dev/null > >> +++ b/osaf/services/saf/logsv/lgs/lgs_clm.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): Oracle > >> + * > >> + */ > >> + > >> +#include "lgs.h" > >> +#include "lgs_clm.h" > >> + > >> +/* > >> + * @brief CLM callback for tracking node membership status. > >> + * Depending upon the membership status (joining/leaving > >> cluster) > >> + * of a node, LGS will add or remove node from its data base. > >> + * A node is added when it is part of the cluster and is removed > >> + * when it leaves the cluster membership. An update of status is > >> + * sent to the clients on that node. Based on this status LGA > >> + * will decide return code for different API calls. > >> + * > >> + */ > >> +static void lgs_clm_track_cbk(const SaClmClusterNotificationBufferT_4 > >> *notificationBuffer, > >> + SaUint32T numberOfMembers, SaInvocationT invocation, > >> + const SaNameT *rootCauseEntity, const SaNtfCorrelationIdsT > >> *correlationIds, > >> + SaClmChangeStepT step, SaTimeT timeSupervision, > >> SaAisErrorT error) > >> +{ > >> + NODE_ID node_id; > >> + SaClmClusterChangesT cluster_change; > >> + SaBoolT is_member; > >> + uint32_t i = 0; > >> + > >> + TRACE_ENTER2("'%llu' '%u' '%u'", invocation, step, error); > >> + if (error != SA_AIS_OK) { > >> + TRACE_1("Error received in ClmTrackCallback"); > >> + goto done; > >> + } > >> + lgs_cb->clm_initialized = true; > >> + > >> + for (i = 0; i < notificationBuffer->numberOfItems; i++) { > >> + switch(step) { > >> + case SA_CLM_CHANGE_COMPLETED: > >> + is_member = notificationBuffer- > >>> notification[i].clusterNode.member; > >> + node_id = notificationBuffer- > >>> notification[i].clusterNode.nodeId; > >> + if (lgs_clm_node_find(node_id) == > >> NCSCC_RC_SUCCESS) { > >> + TRACE_1("'%x' is present in LGS db", > >> node_id); > >> + if (!is_member) { > >> + TRACE("CLM Node : %x Left > >> the cluster", node_id); > >> + cluster_change = > >> SA_CLM_NODE_LEFT; > >> + if > >> (lgs_clm_node_del(node_id) == NCSCC_RC_SUCCESS){ > >> + if (lgs_cb->ha_state > >> == SA_AMF_HA_ACTIVE) > >> + > >> send_clm_node_status_change(cluster_change, node_id); > >> + } > >> + } > >> + } else { > >> + TRACE_1("'%x' is not present in LGS > >> db", node_id); > >> + if (is_member) { > >> + TRACE("CLM Node : %x > >> Joined the cluster", node_id); > >> + cluster_change = > >> SA_CLM_NODE_JOINED; > >> + > >> if(lgs_clm_node_add(node_id) == NCSCC_RC_SUCCESS) { > >> + if (lgs_cb->ha_state > >> == SA_AMF_HA_ACTIVE) > >> + > >> send_clm_node_status_change(cluster_change, node_id); > >> + } > >> + } > >> + } > >> + break; > >> + default: > >> + break; > >> + } > >> + } > >> +done: > >> + TRACE_LEAVE(); > >> + return; > >> +} > >> + > >> +static const SaClmCallbacksT_4 clm_callbacks = { > >> + 0, > >> + lgs_clm_track_cbk /*saClmClusterTrackCallback*/ > >> +}; > >> + > >> +/* > >> + * @brief Registers with the CLM service (B.04.01). > >> + * > >> + * @return SaAisErrorT > >> + */ > >> +void *lgs_clm_init_thread(void *cb) > >> +{ > >> + static SaVersionT clmVersion = { 'B', 0x04, 0x01 }; > >> + lgs_cb_t *_lgs_cb = (lgs_cb_t *) cb; > >> + SaAisErrorT rc = SA_AIS_OK; > >> + TRACE_ENTER(); > >> + rc = saClmInitialize_4(&_lgs_cb->clm_hdl, &clm_callbacks, > >> &clmVersion); > >> + if (rc != SA_AIS_OK) { > >> + LOG_ER("saClmInitialize failed with error: %d", rc); > >> + TRACE_LEAVE(); > >> + exit(EXIT_FAILURE); > >> + } > >> + rc = saClmSelectionObjectGet(_lgs_cb->clm_hdl, &lgs_cb- > >>> clmSelectionObject); > >> + if (rc != SA_AIS_OK) { > >> + LOG_ER("saClmSelectionObjectGet failed with error: %d", > >> rc); > >> + TRACE_LEAVE(); > >> + exit(EXIT_FAILURE); > >> + } > >> + //TODO:subscribe for SA_TRACK_START_STEP also. > >> + rc = saClmClusterTrack_4(_lgs_cb->clm_hdl, (SA_TRACK_CURRENT | > >> SA_TRACK_CHANGES), NULL); > >> + if (rc != SA_AIS_OK) { > >> + LOG_ER("saClmClusterTrack failed with error: %d", rc); > >> + TRACE_LEAVE(); > >> + exit(EXIT_FAILURE); > >> + } > >> + TRACE("CLM Initialization SUCCESS......"); > >> + TRACE_LEAVE(); > >> + return NULL; > >> +} > >> + > >> +/* > >> + * @brief Creates a thread to initialize with CLM. > >> + */ > >> +void lgs_init_with_clm(void) > >> +{ > >> + pthread_t thread; > >> + pthread_attr_t attr; > >> + TRACE_ENTER(); > >> + > >> + pthread_attr_init(&attr); > >> + pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); > >> + > >> + if (pthread_create(&thread, &attr, lgs_clm_init_thread, lgs_cb) != 0) > >> { > >> + LOG_ER("pthread_create FAILED: %s", strerror(errno)); > >> + exit(EXIT_FAILURE); > >> + } > >> + pthread_attr_destroy(&attr); > >> + TRACE_LEAVE(); > >> +} > >> diff --git a/osaf/services/saf/logsv/lgs/lgs_clm.h > >> b/osaf/services/saf/logsv/lgs/lgs_clm.h > >> new file mode 100644 > >> --- /dev/null > >> +++ b/osaf/services/saf/logsv/lgs/lgs_clm.h > >> @@ -0,0 +1,25 @@ > >> +/* -*- 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): Oracle > >> + * > >> + */ > >> + > >> +#include <saClm.h> > >> + > >> +#define m_LGS_GET_NODE_ID_FROM_ADEST(adest) (NODE_ID) > >> ((uint64_t)adest >> 32) > >> + > >> +/* > >> + * @brief Creates a thread to initialize with CLM. > >> + */ > >> +void lgs_init_with_clm(void); > >> diff --git a/osaf/services/saf/logsv/lgs/lgs_evt.cc > >> b/osaf/services/saf/logsv/lgs/lgs_evt.cc > >> --- a/osaf/services/saf/logsv/lgs/lgs_evt.cc > >> +++ b/osaf/services/saf/logsv/lgs/lgs_evt.cc > >> @@ -23,6 +23,7 @@ > >> #include "lgs_mbcsv_v2.h" > >> #include "lgs_recov.h" > >> #include "lgs_imm_gcfg.h" > >> +#include "lgs_clm.h" > >> > >> /* Macro to validate the version */ > >> #define m_LOG_VER_IS_VALID(ver) \ > >> @@ -56,6 +57,94 @@ LGSV_LGS_LGA_API_MSG_HANDLER lgs_lga_api > >> }; > >> > >> /** > >> + * Name : lgs_clm_node_tree_init > >> + * Description : This routine is used to initialize the clm_node_tree > >> + * Arguments : lgs_cb - pointer to the lgs Control Block > >> + * Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE > >> + * Notes : None > >> + */ > >> +uint32_t lgs_clm_node_tree_init(lgs_cb_t *lgs_cb) > >> +{ > >> + TRACE_ENTER(); > >> + NCS_PATRICIA_PARAMS param; > >> + memset(¶m, 0, sizeof(NCS_PATRICIA_PARAMS)); > >> + > >> + param.key_size = sizeof(NODE_ID); > >> + if (ncs_patricia_tree_init(&lgs_cb->clm_node_tree, ¶m) != > >> NCSCC_RC_SUCCESS) { > >> + LOG_ER("lgs patricia tee init failed for clm_node_tree"); > >> + return NCSCC_RC_FAILURE; > >> + } > >> + TRACE_LEAVE(); > >> + return NCSCC_RC_SUCCESS; > >> +} > >> + > >> +/** > >> + * Name : lgs_clm_node_find > >> + * Description : This routine finds the clm_node . > >> + * Arguments : node_id - CLM Node id > >> + * Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE > >> + * Notes : None > >> + */ > >> +uint32_t lgs_clm_node_find(NODE_ID node_id) > >> +{ > >> + uint32_t rc = NCSCC_RC_FAILURE; > >> + lgs_clm_node_t *clm_node = (lgs_clm_node_t *) > >> + ncs_patricia_tree_get(&lgs_cb->clm_node_tree, (uint8_t > >> *)&node_id); > >> + > >> + if (clm_node != NULL) > >> + rc = NCSCC_RC_SUCCESS; > >> + else > >> + TRACE("node_id find in DB failed : %x",node_id); > >> + > >> + return rc; > >> +} > >> + > >> +/** > >> + * Name : lgs_clm_node_add > >> + * Description : This routine adds the new node to clm_node_tree. > >> + * Arguments : node_id - CLM Node id > >> + * Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE > >> + * Notes : None > >> + */ > >> +uint32_t lgs_clm_node_add(NODE_ID node_id) > >> +{ > >> + TRACE_ENTER(); > >> + uint32_t rc = NCSCC_RC_FAILURE; > >> + lgs_clm_node_t *clm_node; > >> + > >> + clm_node = (lgs_clm_node_t *) malloc(sizeof(lgs_clm_node_t)); > >> + clm_node->node_id = node_id; > >> + clm_node->patnode.key_info = (uint8_t *)&clm_node->node_id; > >> + rc = ncs_patricia_tree_add(&lgs_cb->clm_node_tree, > >> (NCS_PATRICIA_NODE *)&clm_node->patnode); > >> + if (rc != NCSCC_RC_SUCCESS) > >> + TRACE("node_id add to DB failed : %x",node_id); > >> + TRACE_LEAVE(); > >> + return rc; > >> +} > >> + > >> +/** > >> + * Name : lgs_clm_node_del > >> + * Description : Function to Delete the clm_node. > >> + * Arguments : node_id - CLM Node id > >> + * Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE > >> + * Notes : None. > >> + */ > >> +uint32_t lgs_clm_node_del(NODE_ID node_id) > >> +{ > >> + TRACE_ENTER(); > >> + uint32_t rc = NCSCC_RC_FAILURE; > >> + > >> + lgs_clm_node_t *clm_node = (lgs_clm_node_t *) > >> + ncs_patricia_tree_get(&lgs_cb->clm_node_tree, (uint8_t > >> *)&node_id); > >> + if (clm_node != NULL) > >> + rc = ncs_patricia_tree_del(&lgs_cb->clm_node_tree, > >> (NCS_PATRICIA_NODE *)&clm_node->patnode); > >> + if (rc != NCSCC_RC_SUCCESS) > >> + TRACE("node_id delete to DB failed : %x",node_id); > >> + TRACE_LEAVE(); > >> + return rc; > >> +} > >> + > >> +/** > >> * Get client record from client ID > >> * @param client_id > >> * > >> @@ -583,6 +672,9 @@ uint32_t lgs_cb_init(lgs_cb_t *lgs_cb) > >> lgs_cb->amfSelectionObject = -1; > >> lgs_cb->immSelectionObject = -1; > >> lgs_cb->mbcsv_sel_obj = -1; > >> + lgs_cb->clm_hdl = 0; > >> + lgs_cb->clm_initialized = false; > >> + lgs_cb->clmSelectionObject = -1; > >> > >> /* Assign Version. Currently, hardcoded, This will change later */ > >> lgs_cb->log_version.releaseCode = LOG_RELEASE_CODE; > >> @@ -598,6 +690,12 @@ uint32_t lgs_cb_init(lgs_cb_t *lgs_cb) > >> if (NCSCC_RC_SUCCESS != ncs_patricia_tree_init(&lgs_cb- > >>> client_tree, ®_param)) > >> return NCSCC_RC_FAILURE; > >> > >> + /* Initialize patricia tree for CLM Node list */ > >> + if (NCSCC_RC_SUCCESS != lgs_clm_node_tree_init(lgs_cb)) { > >> + LOG_ER("LGS: ncs_patricia_tree_init FAILED"); > >> + return NCSCC_RC_FAILURE; > >> + } > >> + > >> done: > >> TRACE_LEAVE(); > >> return rc; > >> @@ -637,6 +735,12 @@ static uint32_t proc_initialize_msg(lgs_ > >> goto snd_rsp; > >> } > >> > >> + if (is_client_clm_member(evt->fr_node_id, version) != true){ > >> + ais_rc = SA_AIS_ERR_UNAVAILABLE; > >> + TRACE("client not a CLM member FAILED"); > >> + goto snd_rsp; > >> + } > >> + > >> if ((client = lgs_client_new(evt->fr_dest, 0, NULL)) == NULL) { > >> ais_rc = SA_AIS_ERR_NO_MEMORY; > >> goto snd_rsp; > >> @@ -1451,3 +1555,42 @@ void lgs_process_mbx(SYSF_MBX *mbx) > >> lgs_evt_destroy(msg); > >> } > >> } > >> + > >> +/** > >> + * @brief Sends CLM membership status of the node to all the clients > >> + * on the node except A11 clients. > >> + * @param cluster_change (CLM membership status of node). > >> + * @param NCS node_id. > >> + * @return NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE. > >> + */ > >> +uint32_t > >> send_cluster_membership_msg_to_clients(SaClmClusterChangesT > >> cluster_change, NODE_ID node_id) { > >> + uint32_t rc = NCSCC_RC_SUCCESS; > >> + log_client_t *rp = NULL; > >> + uint32_t client_id_net; > >> + > >> + TRACE_ENTER(); > >> + TRACE_3("node_id: %x, change:%u", node_id, cluster_change); > >> + > >> + rp = reinterpret_cast<log_client_t > >> *>(ncs_patricia_tree_getnext(&lgs_cb->client_tree, NULL)); > >> + > >> + while (rp != NULL) { > >> + /** Store the client_id_net for get Next */ > >> + client_id_net = rp->client_id_net; > >> + NODE_ID tmp_node_id = > >> m_LGS_GET_NODE_ID_FROM_ADEST(rp->mds_dest); > >> + //Do not send to A11 client. Send only to specific Node > >> + if (tmp_node_id == node_id) > >> + rc = send_clm_node_status_lib(cluster_change, rp- > >>> client_id, rp->mds_dest); > >> + > >> + rp = reinterpret_cast<log_client_t > >> *>(ncs_patricia_tree_getnext( > >> + &lgs_cb->client_tree, > >> reinterpret_cast<uint8_t *>(&client_id_net))); > >> + } > >> + > >> + TRACE_LEAVE(); > >> + return rc; > >> +} > >> + > >> +uint32_t send_clm_node_status_change(SaClmClusterChangesT > >> cluster_change, NODE_ID node_id) { > >> + return (send_cluster_membership_msg_to_clients(cluster_change, > >> node_id)); > >> + > >> +} > >> + > >> diff --git a/osaf/services/saf/logsv/lgs/lgs_evt.h > >> b/osaf/services/saf/logsv/lgs/lgs_evt.h > >> --- a/osaf/services/saf/logsv/lgs/lgs_evt.h > >> +++ b/osaf/services/saf/logsv/lgs/lgs_evt.h > >> @@ -77,6 +77,8 @@ extern bool lgs_lga_entry_valid(lgs_cb_t > >> extern uint32_t lgs_remove_lga_down_rec(lgs_cb_t *cb, MDS_DEST > >> mds_dest); > >> extern void lgs_send_write_log_ack(uint32_t client_id, SaInvocationT > >> invocation, SaAisErrorT error, MDS_DEST mds_dest); > >> extern void lgs_free_write_log(const lgsv_write_log_async_req_t > *param); > >> +extern uint32_t send_clm_node_status_lib(SaClmClusterChangesT > >> cluster_change, unsigned int client_id, MDS_DEST mdsDest); > >> +extern uint32_t send_clm_node_status_change(SaClmClusterChangesT > >> cluster_change, NODE_ID node_id); > >> > >> SaAisErrorT create_new_app_stream( > >> lgsv_stream_open_req_t *open_sync_param, > >> diff --git a/osaf/services/saf/logsv/lgs/lgs_main.cc > >> b/osaf/services/saf/logsv/lgs/lgs_main.cc > >> --- a/osaf/services/saf/logsv/lgs/lgs_main.cc > >> +++ b/osaf/services/saf/logsv/lgs/lgs_main.cc > >> @@ -38,6 +38,7 @@ > >> #include "osaf_utility.h" > >> #include "lgs_recov.h" > >> #include "immutil.h" > >> +#include "lgs_clm.h" > >> > >> /* > >> > ========================================================== > >> ============== > >> * DEFINITIONS > >> @@ -49,6 +50,7 @@ enum { > >> FD_MBCSV, > >> FD_MBX, > >> FD_CLTIMER, > >> + FD_CLM, > >> FD_IMM, /* Must be the last in the fds array */ > >> FD_NUM > >> }; > >> @@ -332,6 +334,13 @@ static uint32_t log_initialize(void) > >> goto done; > >> } > >> > >> + /* Create a CLM selection object */ > >> + if ((rc = ncs_sel_obj_create(&lgs_cb->clm_init_sel_obj)) != > >> NCSCC_RC_SUCCESS) > >> + { > >> + LOG_ER("lgsv: CLM ncs_sel_obj_create failed"); > >> + goto done; > >> + } > >> + > >> /* > >> * Initialize a signal handler that will use the selection object. > >> * The signal is sent from our script when AMF does instantiate. > >> @@ -501,6 +510,8 @@ int main(int argc, char *argv[]) > >> fds[FD_IMM].fd = lgs_cb->immSelectionObject; > >> fds[FD_IMM].events = POLLIN; > >> > >> + lgs_cb->clmSelectionObject = lgs_cb->clm_init_sel_obj.rmv_obj; > >> + > >> while (1) { > >> if (cltimer_fd < 0 && log_rtobj_list_no() != 0) { > >> /* Needed only if any "lost" objects are found > >> @@ -513,6 +524,8 @@ int main(int argc, char *argv[]) > >> fds[FD_CLTIMER].events = POLLIN; > >> fds[FD_MBCSV].fd = lgs_cb->mbcsv_sel_obj; > >> fds[FD_MBCSV].events = POLLIN; > >> + fds[FD_CLM].fd = lgs_cb->clmSelectionObject; > >> + fds[FD_CLM].events = POLLIN; > >> > >> /* Protect since the reinit thread may be in the process of > >> * changing the values > >> @@ -567,6 +580,21 @@ int main(int argc, char *argv[]) > >> } > >> } > >> > >> + if (fds[FD_CLM].revents & POLLIN) { > >> + if (lgs_cb->clm_hdl != 0) { > >> + if ((error = saClmDispatch(lgs_cb->clm_hdl, > >> SA_DISPATCH_ALL)) != SA_AIS_OK) { > >> + LOG_ER("saClmDispatch failed: %u", > >> error); > >> + break; > >> + } > >> + } else { > >> + TRACE("init CLM "); > >> + ncs_sel_obj_rmv_ind(&lgs_cb- > >>> clm_init_sel_obj, true, true); > >> + ncs_sel_obj_destroy(&lgs_cb- > >>> clm_init_sel_obj); > >> + lgs_cb->clmSelectionObject = -1; > >> + lgs_init_with_clm(); > >> + } > >> + } > >> + > >> if (fds[FD_CLTIMER].revents & POLLIN) { > >> /* To avoid 'stray objects', after a timeout all runtime > >> * objects that has not been restored shall be deleted > >> diff --git a/osaf/services/saf/logsv/lgs/lgs_mds.cc > >> b/osaf/services/saf/logsv/lgs/lgs_mds.cc > >> --- a/osaf/services/saf/logsv/lgs/lgs_mds.cc > >> +++ b/osaf/services/saf/logsv/lgs/lgs_mds.cc > >> @@ -763,11 +763,19 @@ static uint32_t mds_enc(struct ncsmds_ca > >> goto err; > >> } > >> ncs_encode_32bit(&p8, msg- > >>> info.cbk_info.write_cbk.error); > >> + TRACE_8("LGSV_WRITE_LOG_CALLBACK_IND"); > >> + } else if (msg->info.cbk_info.type == > >> LGSV_CLM_NODE_STATUS_CALLBACK) { > >> + p8 = ncs_enc_reserve_space(uba, 4); > >> + if (!p8) { > >> + TRACE("ncs_enc_reserve_space failed"); > >> + goto err; > >> + } > >> + ncs_encode_32bit(&p8, msg- > >>> info.cbk_info.clm_node_status_cbk.clm_node_status); > >> + TRACE_8("LGSV_CLM_NODE_STATUS_CALLBACK"); > >> } else { > >> TRACE("unknown callback type %d", msg- > >>> info.cbk_info.type); > >> goto err; > >> } > >> - TRACE_8("LGSV_WRITE_LOG_CALLBACK_IND"); > >> } else { > >> TRACE("unknown msg type %d", msg->type); > >> goto err; > >> @@ -1167,6 +1175,16 @@ static uint32_t mds_svc_event(struct ncs > >> osafassert(rc == NCSCC_RC_SUCCESS); > >> } > >> } > >> + } else if (info->info.svc_evt.i_svc_id == NCSMDS_SVC_ID_AVD) { > >> + if (info->info.svc_evt.i_change == NCSMDS_UP) { > >> + TRACE_8("MDS UP dest: %" PRIx64 ", node ID: %x, > >> svc_id: %d", > >> + info->info.svc_evt.i_dest, info- > >>> info.svc_evt.i_node_id, info->info.svc_evt.i_svc_id); > >> + //Subscribed for only INTRA NODE, only one ADEST > >> will come. > >> + if (m_MDS_DEST_IS_AN_ADEST(info- > >>> info.svc_evt.i_dest)) { > >> + TRACE_8("AVD ADEST UP"); > >> + ncs_sel_obj_ind(&lgs_cb->clm_init_sel_obj); > >> + } > >> + } > >> } > >> > >> done: > >> @@ -1334,6 +1352,24 @@ uint32_t lgs_mds_init(lgs_cb_t *cb, SaAm > >> return rc; > >> } > >> > >> + > >> + svc = NCSMDS_SVC_ID_AVD; > >> + /* Now subscribe for AVD events in MDS. This will be > >> + used for CLM registration.*/ > >> + memset(&mds_info, '\0', sizeof(NCSMDS_INFO)); > >> + mds_info.i_mds_hdl = cb->mds_hdl; > >> + mds_info.i_svc_id = NCSMDS_SVC_ID_LGS; > >> + mds_info.i_op = MDS_SUBSCRIBE; > >> + mds_info.info.svc_subscribe.i_scope = > NCSMDS_SCOPE_INTRANODE; > >> + mds_info.info.svc_subscribe.i_num_svcs = 1; > >> + mds_info.info.svc_subscribe.i_svc_ids = &svc; > >> + > >> + rc = ncsmds_api(&mds_info); > >> + if (rc != NCSCC_RC_SUCCESS) { > >> + LOG_ER("MDS for AVD subscribe FAILED"); > >> + return rc; > >> + } > >> + > >> TRACE_LEAVE(); > >> return rc; > >> } > >> diff --git a/osaf/services/saf/logsv/lgs/lgs_util.cc > >> b/osaf/services/saf/logsv/lgs/lgs_util.cc > >> --- a/osaf/services/saf/logsv/lgs/lgs_util.cc > >> +++ b/osaf/services/saf/logsv/lgs/lgs_util.cc > >> @@ -415,6 +415,89 @@ void lgs_send_write_log_ack(uint32_t cli > >> } > >> > >> /** > >> + * @brief Send Membership status of node to a lib on that node. > >> + * > >> + * @param SaClmClusterChangesT (CLM status of node) > >> + * @param client_id > >> + * @param mdsDest of client > >> + * > >> + * @return NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE. > >> + */ > >> +uint32_t send_clm_node_status_lib(SaClmClusterChangesT > >> cluster_change, unsigned int client_id, MDS_DEST mdsDest) > >> +{ > >> + uint32_t rc = NCSCC_RC_SUCCESS; > >> + NCSMDS_INFO mds_info = {0}; > >> + lgsv_msg_t msg; > >> + > >> + TRACE_ENTER(); > >> + TRACE_3("change:%u, client_id: %u", cluster_change, client_id); > >> + > >> + memset(&msg, 0, sizeof(lgsv_msg_t)); > >> + msg.type = LGSV_LGS_CBK_MSG; > >> + msg.info.cbk_info.type = LGSV_CLM_NODE_STATUS_CALLBACK; > >> + msg.info.cbk_info.lgs_client_id = client_id; > >> + msg.info.cbk_info.inv = 0; > >> + msg.info.cbk_info.clm_node_status_cbk.clm_node_status = > >> cluster_change; > >> + > >> + mds_info.i_mds_hdl = lgs_cb->mds_hdl; > >> + mds_info.i_svc_id = NCSMDS_SVC_ID_LGS; > >> + mds_info.i_op = MDS_SEND; > >> + mds_info.info.svc_send.i_msg = &msg; > >> + mds_info.info.svc_send.i_to_svc = NCSMDS_SVC_ID_LGA; > >> + mds_info.info.svc_send.i_priority = MDS_SEND_PRIORITY_HIGH; > >> + mds_info.info.svc_send.i_sendtype = MDS_SENDTYPE_SND; > >> + mds_info.info.svc_send.info.snd.i_to_dest = mdsDest; > >> + > >> + rc = ncsmds_api(&mds_info); > >> + if (rc != NCSCC_RC_SUCCESS) > >> + LOG_NO("Failed (%u) to send of WRITE ack to: %" PRIx64, rc, > >> mdsDest); > >> + > >> + TRACE_LEAVE(); > >> + return rc; > >> +} > >> + > >> +/** > >> + * @brief Checks if LGSV has already initialized with CLM service. > >> + * > >> + * @return true/false. > >> + */ > >> +bool is_clm_init() > >> +{ > >> + return (((lgs_cb->clm_hdl != 0) && (lgs_cb->clm_initialized == > >> true)) > ? > >> true : false); > >> +} > >> + > >> +/** > >> + * @brief Checks CLM membership status of a client. > >> + * A.02.01 clients are always CLM member. > >> + * @param Client MDS_DEST > >> + * @param Client saf version. > >> + * @return NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE. > >> + */ > >> +bool is_client_clm_member(NODE_ID node_id, SaVersionT *ver) { > >> + > >> + //Before CLM init all clients are clm member. > >> + if (is_clm_init() == false) > >> + return true; > >> + > >> + TRACE("client Version: %d.%d.%d", ver->releaseCode, ver- > >majorVersion, > >> ver->minorVersion); > >> + //CLM integration is supported from A.02.02. So old clients A.02.01 are > >> always clm member. > >> + if ((ver->releaseCode == LOG_RELEASE_CODE_0) && > >> + (ver->majorVersion == LOG_MAJOR_VERSION_0) && > >> + (ver->minorVersion == LOG_MINOR_VERSION_0)) > >> + return true; > >> + /* > >> + It means CLM initialization is successful and this is atleast a > >> A.02.02 > client. > >> + So check CLM membership status of client's node. > >> + */ > >> + if (lgs_clm_node_find(node_id) != NCSCC_RC_SUCCESS) > >> + return false; > >> + else > >> + return true; > >> +} > >> + > >> + > >> + > >> +/** > >> * Free all dynamically allocated memory for a WRITE > >> * @param param > >> */ ------------------------------------------------------------------------------ _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel