osaf/services/saf/logsv/lgs/Makefile.am | 4 +- osaf/services/saf/logsv/lgs/lgs.h | 5 + osaf/services/saf/logsv/lgs/lgs_cb.h | 15 +++ osaf/services/saf/logsv/lgs/lgs_evt.cc | 142 ++++++++++++++++++++++++++++++++ osaf/services/saf/logsv/lgs/lgs_evt.h | 1 + osaf/services/saf/logsv/lgs/lgs_main.cc | 29 ++++++ osaf/services/saf/logsv/lgs/lgs_mds.cc | 41 ++++++++- osaf/services/saf/logsv/lgs/lgs_util.cc | 83 ++++++++++++++++++ 8 files changed, 317 insertions(+), 3 deletions(-)
Description: Form CLM integration is supported from Log Service A.02.02. At-least a A.02.02 LGA client will check CLM membership status of client's node. old LGA clients A.02.01 are always clm member. This patch enhanced the log service for Unavailability of the Log Service API on a Non-Member Node which will fail with SA_AIS_ERR_UNAVAILABLE. After this patch the Log Service does not provide service to processes on cluster nodes that are not in the cluster membership. If the node rejoins the cluster membership, processes executing on the node will be able to reinitialize new library handles and use the entire set of Log Service APIs that operate on these new handles; however, invocation of APIs that operate on handles acquired by any process before the node left the membership will continue to fail with SA_AIS_ERR_UNAVAILABLE (or with the special treatment described above for asynchronous calls) with the exception of saLogFinalize(), which is used to free the library handles and all resources associated with these handles. Hence, it is recommended for the processes to finalize the library handles as soon as the processes detect that the node left the membership. Detailed README will be provide soon. Following are expected Log Service API behavior : Case1: On Non-Member Node, Log Service API will fail with code SA_AIS_ERR_UNAVAILABLE (31) Case2: On Member Node after recovered from Non-Member Node, Log Service API will fail with code SA_AIS_ERR_UNAVAILABLE (31) Case3: Non-Member Node + (Headless) Log Service API will fail with code SA_AIS_ERR_UNAVAILABLE (31) Case4: On Non-Member Node + (Headless) + (Head Joined) Log Service API will fail with code SA_AIS_ERR_UNAVAILABLE (31) 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 @@ -67,7 +67,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 +76,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.h b/osaf/services/saf/logsv/lgs/lgs.h --- a/osaf/services/saf/logsv/lgs/lgs.h +++ b/osaf/services/saf/logsv/lgs/lgs.h @@ -33,6 +33,7 @@ #include <saAis.h> #include <saf_error.h> #include <saImmOm.h> +#include <saClm.h> #include "saAmf.h" /* LGS files */ @@ -78,6 +79,7 @@ #define LGS_LOG_SHARED_FILESYSTEM 1 /* Use shared filesystem. Default */ #define LGS_LOG_SPLIT_FILESYSTEM 2 /* Store logs on local file system on each node */ +#define m_LGS_GET_NODE_ID_FROM_ADEST(adest) (NODE_ID) ((uint64_t)adest >> 32) /* ======================================================================== * DATA DECLARATIONS @@ -131,4 +133,7 @@ int lgs_get_streamobj_attr(SaImmAttrValu SaImmHandleT *immOmHandle); int lgs_free_streamobj_attr(SaImmHandleT immHandle); +extern uint32_t send_clm_node_status_change(SaClmClusterChangesT cluster_change, NODE_ID node_id); +extern void lgs_init_with_clm(void); + #endif /* ifndef __LGS_H */ 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; + +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; 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 usr2_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); #endif 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 @@ -56,6 +56,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_get + * 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 +671,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 +689,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 +734,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 +1554,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,7 @@ 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); 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 @@ -49,6 +49,7 @@ enum { FD_MBCSV, FD_MBX, FD_CLTIMER, + FD_CLM, FD_IMM, /* Must be the last in the fds array */ FD_NUM }; @@ -332,6 +333,14 @@ static uint32_t log_initialize(void) goto done; } + /* Create a CLM selection object */ + if (lgs_cb->nid_started && + (rc = ncs_sel_obj_create(&lgs_cb->usr2_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,9 @@ int main(int argc, char *argv[]) fds[FD_IMM].fd = lgs_cb->immSelectionObject; fds[FD_IMM].events = POLLIN; + lgs_cb->clmSelectionObject = lgs_cb->nid_started ? + lgs_cb->usr2_sel_obj.rmv_obj : -1; + while (1) { if (cltimer_fd < 0 && log_rtobj_list_no() != 0) { /* Needed only if any "lost" objects are found @@ -513,6 +525,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 +581,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("SIGUSR2 event rec"); + ncs_sel_obj_rmv_ind(&lgs_cb->usr2_sel_obj, true, true); + ncs_sel_obj_destroy(&lgs_cb->usr2_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,7 +1175,18 @@ 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->usr2_sel_obj); + } + + } + } done: return rc; @@ -1334,6 +1353,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 */ ------------------------------------------------------------------------------ What NetFlow Analyzer can do for you? Monitors network bandwidth and traffic patterns at an interface-level. Reveals which users, apps, and protocols are consuming the most bandwidth. Provides multi-vendor support for NetFlow, J-Flow, sFlow and other flows. Make informed decisions using capacity planning reports.http://sdm.link/zohodev2dev _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel