osaf/libs/common/cpsv/include/cpnd_cb.h | 6 +- osaf/libs/common/cpsv/include/cpnd_init.h | 14 +- osaf/libs/common/cpsv/include/cpsv_evt.h | 2 +- osaf/services/saf/cpsv/cpnd/Makefile.am | 3 +- osaf/services/saf/cpsv/cpnd/cpnd_db.c | 246 +---------------- osaf/services/saf/cpsv/cpnd/cpnd_evt.c | 115 ++++--- osaf/services/saf/cpsv/cpnd/cpnd_proc.c | 26 +- osaf/services/saf/cpsv/cpnd/cpnd_res.c | 15 +- osaf/services/saf/cpsv/cpnd/cpnd_sec.cc | 424 ++++++++++++++++++++++++++++++ 9 files changed, 531 insertions(+), 320 deletions(-)
Jan 7 21:32:32.772347 <1789648919> ERR |MDTM: Frag recd is not next frag so dropping adest=<0x010010023922604c> Jan 7 21:32:32.772399 <1789648919> ERR |MDTM: Message is dropped as msg is out of seq TRANSPOR-ID=<0x010010023922604c> With large numbers of sections (>5k) on the standby the CPU is pegged and all ckpt API functions return with SA_AIS_ERR_TIMEOUT, including ActiveReplicaSet, and CheckpointClose! The section id database is implemented as a linked list. Each write to a section must traverse the list in order to find the section. With 1000's of sections this takes a looong time. Also, sync data being sent over is too large for one packet (30M). This causes the transport layer (in this case TIPC), to drop packets. Lastly, the SectionCreate message is not asynchronous when ACTIVE_REPLICA is specified. Solution is in 3 parts: (1) make the section id database a C++ STL map for fast access. (2) make MAX_SYNC_TRANSFER_SIZE much smaller: 3M instead of 30M. (3) SectionCreate message should be asynchronous when ACTIVE_REPLICA is specified. diff --git a/osaf/libs/common/cpsv/include/cpnd_cb.h b/osaf/libs/common/cpsv/include/cpnd_cb.h --- a/osaf/libs/common/cpsv/include/cpnd_cb.h +++ b/osaf/libs/common/cpsv/include/cpnd_cb.h @@ -23,7 +23,7 @@ #include "ncs_queue.h" /* global variables */ -uint32_t gl_cpnd_cb_hdl; +extern uint32_t gl_cpnd_cb_hdl; /* macros for the CB handle */ #define m_CPND_TAKE_CPND_CB ncshm_take_hdl(NCS_SERVICE_ID_CPND, gl_cpnd_cb_hdl) @@ -131,7 +131,6 @@ typedef struct cpnd_ckpt_section_info { SaSizeT sec_size; SaTimeT exp_tmr; SaTimeT lastUpdate; - struct cpnd_ckpt_section_info *prev, *next; } CPND_CKPT_SECTION_INFO; #define CPND_CKPT_SECTION_INFO_NULL ((CPND_CKPT_SECTION_INFO *)0) @@ -144,7 +143,8 @@ typedef struct cpnd_ckpt_replica_info_ta SaUint32T mem_used; /* Used for status */ NCS_OS_POSIX_SHM_REQ_INFO open; /* for shm open */ uint32_t *shm_sec_mapping; /* for validity of sec */ - CPND_CKPT_SECTION_INFO *section_info; /* Sections in the shared memory */ + void *section_db; /* used for C++ STL map */ + void *local_section_db; /* used for C++ STL map */ } CPND_CKPT_REPLICA_INFO; /*Structure to store info for ALL_REPL_WRITE EVT processing*/ diff --git a/osaf/libs/common/cpsv/include/cpnd_init.h b/osaf/libs/common/cpsv/include/cpnd_init.h --- a/osaf/libs/common/cpsv/include/cpnd_init.h +++ b/osaf/libs/common/cpsv/include/cpnd_init.h @@ -157,15 +157,21 @@ void cpnd_evt_node_getnext(CPND_CB *cb, uint32_t cpnd_evt_node_add(CPND_CB *cb, CPSV_CPND_ALL_REPL_EVT_NODE *evt_node); uint32_t cpnd_evt_node_del(CPND_CB *cb, CPSV_CPND_ALL_REPL_EVT_NODE *evt_node); CPND_CKPT_NODE *cpnd_ckpt_node_find_by_name(CPND_CB *cpnd_cb, SaNameT ckpt_name); -CPND_CKPT_SECTION_INFO *cpnd_ckpt_sec_get(CPND_CKPT_NODE *cp_node, SaCkptSectionIdT *id); -CPND_CKPT_SECTION_INFO *cpnd_ckpt_sec_get_create(CPND_CKPT_NODE *cp_node, SaCkptSectionIdT *id); -uint32_t cpnd_ckpt_sec_find(CPND_CKPT_NODE *cp_node, SaCkptSectionIdT *id); +void cpnd_ckpt_sec_map_init(CPND_CKPT_REPLICA_INFO *replica_info); +void cpnd_ckpt_sec_map_destroy(CPND_CKPT_REPLICA_INFO *replica_info); +CPND_CKPT_SECTION_INFO *cpnd_ckpt_sec_get_first(const CPND_CKPT_REPLICA_INFO *replicaInfo); +CPND_CKPT_SECTION_INFO *cpnd_ckpt_sec_get_next(const CPND_CKPT_REPLICA_INFO *replicaInfo, const CPND_CKPT_SECTION_INFO *section); +CPND_CKPT_SECTION_INFO *cpnd_ckpt_sec_get(const CPND_CKPT_NODE *cp_node, const SaCkptSectionIdT *id); +CPND_CKPT_SECTION_INFO *cpnd_ckpt_sec_get_create(const CPND_CKPT_NODE *cp_node, const SaCkptSectionIdT *id); +uint32_t cpnd_ckpt_sec_find(const CPND_CKPT_NODE *cp_node, const SaCkptSectionIdT *id); CPND_CKPT_SECTION_INFO *cpnd_ckpt_sec_del(CPND_CKPT_NODE *cp_node, SaCkptSectionIdT *id); CPND_CKPT_SECTION_INFO *cpnd_ckpt_sec_add(CPND_CKPT_NODE *cp_node, SaCkptSectionIdT *id, SaTimeT exp_time, uint32_t gen_flag); +uint32_t cpnd_ckpt_sec_add_db(CPND_CKPT_REPLICA_INFO *replicaInfo, CPND_CKPT_SECTION_INFO *sectionInfo); void cpnd_ckpt_delete_all_sect(CPND_CKPT_NODE *cp_node); +bool cpnd_ckpt_sec_empty(const CPND_CKPT_REPLICA_INFO *replicaInfo); void cpnd_evt_backup_queue_add(CPND_CKPT_NODE *cp_node, CPND_EVT *evt); -CPND_CKPT_SECTION_INFO *cpnd_get_sect_with_id(CPND_CKPT_NODE *cp_node, uint32_t lcl_sec_id); +CPND_CKPT_SECTION_INFO *cpnd_get_sect_with_id(const CPND_CKPT_NODE *cp_node, uint32_t lcl_sec_id); uint32_t cpnd_ckpt_node_tree_init(CPND_CB *cb); uint32_t cpnd_allrepl_write_evt_node_tree_init(CPND_CB *cb); uint32_t cpnd_client_node_tree_init(CPND_CB *cb); diff --git a/osaf/libs/common/cpsv/include/cpsv_evt.h b/osaf/libs/common/cpsv/include/cpsv_evt.h --- a/osaf/libs/common/cpsv/include/cpsv_evt.h +++ b/osaf/libs/common/cpsv/include/cpsv_evt.h @@ -429,7 +429,7 @@ typedef struct cpsv_a2nd_ckpt_list_updat #define CPSV_CKPT_ACCESS_READ 0x2 #define CPSV_CKPT_ACCESS_SYNC 0x3 -#define MAX_SYNC_TRANSFER_SIZE (30 * 1024 * 1024) +#define MAX_SYNC_TRANSFER_SIZE (3 * 1024 * 1024) typedef struct cpsv_ckpt_access { SaUint32T type; /* --- 0-write/1-overwrite/2-read/3-sync ----- */ diff --git a/osaf/services/saf/cpsv/cpnd/Makefile.am b/osaf/services/saf/cpsv/cpnd/Makefile.am --- a/osaf/services/saf/cpsv/cpnd/Makefile.am +++ b/osaf/services/saf/cpsv/cpnd/Makefile.am @@ -38,7 +38,8 @@ osafckptnd_SOURCES = \ cpnd_mds.c \ cpnd_proc.c \ cpnd_res.c \ - cpnd_tmr.c + cpnd_tmr.c \ + cpnd_sec.cc osafckptnd_LDADD = \ $(top_builddir)/osaf/libs/core/libopensaf_core.la \ diff --git a/osaf/services/saf/cpsv/cpnd/cpnd_db.c b/osaf/services/saf/cpsv/cpnd/cpnd_db.c --- a/osaf/services/saf/cpsv/cpnd/cpnd_db.c +++ b/osaf/services/saf/cpsv/cpnd/cpnd_db.c @@ -156,6 +156,8 @@ void cpnd_ckpt_node_destroy(CPND_CB *cb, if (cp_node->ret_tmr.is_active) cpnd_tmr_stop(&cp_node->ret_tmr); + cpnd_ckpt_sec_map_destroy(&cp_node->replica_info); + m_MMGR_FREE_CPND_CKPT_NODE(cp_node); TRACE_LEAVE(); @@ -353,163 +355,6 @@ uint32_t cpnd_evt_node_del(CPND_CB *cb, } /**************************************************************************** - * Name : cpnd_ckpt_sec_get - * - * Description : Function to Find the section in a checkpoint. - * - * Arguments : CPND_CKPT_NODE *cp_node - Check point node. - * : SaCkptSectionIdT id - Section Identifier - * - * Return Values : NULL/CPND_CKPT_SECTION_INFO - * - * Notes : None. - *****************************************************************************/ -CPND_CKPT_SECTION_INFO *cpnd_ckpt_sec_get(CPND_CKPT_NODE *cp_node, SaCkptSectionIdT *id) -{ - - CPND_CKPT_SECTION_INFO *pSecPtr = NULL; - - TRACE_ENTER(); - if (cp_node->replica_info.n_secs == 0) { - TRACE_4("cpnd replica has no section for ckpt_id:%llx",cp_node->ckpt_id); - TRACE_LEAVE(); - return NULL; - } - - pSecPtr = cp_node->replica_info.section_info; - while (pSecPtr != NULL) { - if ((pSecPtr->sec_id.idLen == id->idLen) && (memcmp(pSecPtr->sec_id.id, id->id, id->idLen) == 0)) { - return pSecPtr; - } - pSecPtr = pSecPtr->next; - } - TRACE_LEAVE(); - return NULL; -} - -/**************************************************************************** - * Name : cpnd_ckpt_sec_get_create - * - * Description : Function to Find the section in a checkpoint before create. - * - * Arguments : CPND_CKPT_NODE *cp_node - Check point node. - * : SaCkptSectionIdT id - Section Identifier - * - * Return Values : NULL/CPND_CKPT_SECTION_INFO - * - * Notes : None. - *****************************************************************************/ -CPND_CKPT_SECTION_INFO *cpnd_ckpt_sec_get_create(CPND_CKPT_NODE *cp_node, SaCkptSectionIdT *id) -{ - CPND_CKPT_SECTION_INFO *pSecPtr = NULL; - TRACE_ENTER(); - if (cp_node->replica_info.n_secs == 0) { - TRACE_2("cpnd replica has no sections for ckpt_id:%llx",cp_node->ckpt_id); - TRACE_LEAVE(); - return NULL; - } - pSecPtr = cp_node->replica_info.section_info; - while (pSecPtr != NULL) { - if ((pSecPtr->sec_id.idLen == id->idLen) && (memcmp(pSecPtr->sec_id.id, id->id, id->idLen) == 0)) { - TRACE_LEAVE(); - return pSecPtr; - } - pSecPtr = pSecPtr->next; - } - TRACE_LEAVE(); - return NULL; -} - -/**************************************************************************** - * Name : cpnd_ckpt_sec_find - * - * Description : Function to Find the section in a checkpoint. - * - * Arguments : CPND_CKPT_NODE *cp_node - Check point node. - * : SaCkptSectionIdT id - Section Identifier - * - * Return Values : NCSCC_RC_FAILURE/NCSCC_RC_SUCCESS - * - * Notes : None. - *****************************************************************************/ -uint32_t cpnd_ckpt_sec_find(CPND_CKPT_NODE *cp_node, SaCkptSectionIdT *id) -{ - - uint32_t rc = NCSCC_RC_SUCCESS; - CPND_CKPT_SECTION_INFO *pSecPtr = NULL; - - TRACE_ENTER(); - if (cp_node->replica_info.n_secs == 0) { - TRACE_LEAVE(); - return NCSCC_RC_FAILURE; - } - - pSecPtr = cp_node->replica_info.section_info; - while (pSecPtr != NULL) { - if ((pSecPtr->sec_id.idLen == id->idLen) && (memcmp(pSecPtr->sec_id.id, id->id, id->idLen) == 0)) { - TRACE_LEAVE(); - return rc; - } - pSecPtr = pSecPtr->next; - } - - TRACE_LEAVE(); - return NCSCC_RC_FAILURE; - -} - -/**************************************************************************** - * Name : cpnd_ckpt_sec_del - * - * Description : Function to remove the section from a checkpoint. - * - * Arguments : CPND_CKPT_NODE *cp_node - Check point node. - * : SaCkptSectionIdT id - Section Identifier - * - * Return Values : ptr to CPND_CKPT_SECTION_INFO/NULL; - * - * Notes : None. - *****************************************************************************/ -CPND_CKPT_SECTION_INFO *cpnd_ckpt_sec_del(CPND_CKPT_NODE *cp_node, SaCkptSectionIdT *id) -{ - CPND_CKPT_SECTION_INFO *pSecPtr = NULL; - uint32_t rc = NCSCC_RC_SUCCESS; - - TRACE_ENTER(); - pSecPtr = cp_node->replica_info.section_info; - while (pSecPtr != NULL) { - if ((pSecPtr->sec_id.idLen == id->idLen) && (memcmp(pSecPtr->sec_id.id, id->id, id->idLen) == 0)) { - /* delete it from the list and return the pointer */ - if (cp_node->replica_info.section_info == pSecPtr) - cp_node->replica_info.section_info = cp_node->replica_info.section_info->next; - if (pSecPtr->prev) - pSecPtr->prev->next = pSecPtr->next; - if (pSecPtr->next) - pSecPtr->next->prev = pSecPtr->prev; - - cp_node->replica_info.n_secs--; - cp_node->replica_info.mem_used = cp_node->replica_info.mem_used - (pSecPtr->sec_size); - - /* UPDATE THE SECTION HEADER */ - rc = cpnd_sec_hdr_update(pSecPtr, cp_node); - if (rc == NCSCC_RC_FAILURE) { - TRACE_4("cpnd sect hdr update failed"); - } - /* UPDATE THE CHECKPOINT HEADER */ - rc = cpnd_ckpt_hdr_update(cp_node); - if (rc == NCSCC_RC_FAILURE) { - TRACE_4("cpnd ckpt hdr update failed"); - } - TRACE_LEAVE(); - return pSecPtr; - } - pSecPtr = pSecPtr->next; - } - TRACE_LEAVE(); - return NULL; -} - -/**************************************************************************** * Name : cpnd_ckpt_sec_add * * Description : Function to add the section to a checkpoint. @@ -581,13 +426,9 @@ CPND_CKPT_SECTION_INFO *cpnd_ckpt_sec_ad pSecPtr->sec_state = SA_CKPT_SECTION_VALID; /* add the structure */ - - if (cp_node->replica_info.section_info != NULL) { - pSecPtr->next = cp_node->replica_info.section_info; - cp_node->replica_info.section_info->prev = pSecPtr; - cp_node->replica_info.section_info = pSecPtr; - } else { - cp_node->replica_info.section_info = pSecPtr; + rc = cpnd_ckpt_sec_add_db(&cp_node->replica_info, pSecPtr); + if (rc == NCSCC_RC_FAILURE) { + LOG_ER("unable to add section to database"); } cp_node->replica_info.n_secs++; @@ -607,46 +448,6 @@ CPND_CKPT_SECTION_INFO *cpnd_ckpt_sec_ad } /**************************************************************************** - * Name : cpnd_ckpt_delete_all_sect - * - * Description : Function to add the section to a checkpoint. - * - * Arguments : CPND_CKPT_NODE *cp_node - Check point node. - * - * Return Values : NCSCC_RC_FAILURE/NCSCC_RC_SUCCESS - * - * Notes : None. - *****************************************************************************/ -void cpnd_ckpt_delete_all_sect(CPND_CKPT_NODE *cp_node) -{ - CPND_CKPT_SECTION_INFO *pSecPtr = NULL; - - TRACE_ENTER(); - /* delete it from the list and return the pointer */ - do { - pSecPtr = cp_node->replica_info.section_info; - if (pSecPtr != NULL) { - cp_node->replica_info.section_info = cp_node->replica_info.section_info->next; - if (pSecPtr->prev) - pSecPtr->prev->next = pSecPtr->next; - if (pSecPtr->next) - pSecPtr->next->prev = pSecPtr->prev; - - cp_node->replica_info.n_secs--; - if (pSecPtr->ckpt_sec_exptmr.is_active) - cpnd_tmr_stop(&pSecPtr->ckpt_sec_exptmr); - - m_CPND_FREE_CKPT_SECTION(pSecPtr); - - } - - } while (cp_node->replica_info.section_info != NULL); - - TRACE_LEAVE(); - return; -} - -/**************************************************************************** * Name : cpnd_evt_backup_queue_add * * Description : Function to add write event into back up queue @@ -687,40 +488,6 @@ void cpnd_evt_backup_queue_add(CPND_CKPT } /**************************************************************************** - * Name : cpnd_get_sect_with_id - * - * Description : Function to Find the section in a checkpoint. - * - * Arguments : CPND_CKPT_NODE *cp_node - Check point node. - * : lck_sec_id - lcl Section Identifier - * - * Return Values : NULL/ pointer to CPND_CKPT_SECTION_INFO - * - * Notes : None. - *****************************************************************************/ -CPND_CKPT_SECTION_INFO *cpnd_get_sect_with_id(CPND_CKPT_NODE *cp_node, uint32_t lcl_sec_id) -{ - - CPND_CKPT_SECTION_INFO *pSecPtr = NULL; - - if (cp_node->replica_info.n_secs == 0) { - TRACE_4("cpnd replica has no sections for ckpt_id:%llx",cp_node->ckpt_id); - return NULL; - } - - pSecPtr = cp_node->replica_info.section_info; - while (pSecPtr != NULL) { - if (pSecPtr->lcl_sec_id == lcl_sec_id) { - return pSecPtr; - } - pSecPtr = pSecPtr->next; - } - - return NULL; - -} - -/**************************************************************************** * Name : cpnd_ckpt_node_tree_init * * Description : Function to Initialise ckpt tree @@ -805,6 +572,9 @@ void cpnd_ckpt_node_tree_cleanup(CPND_CB ncs_patricia_tree_del(&cb->ckpt_info_db, (NCS_PATRICIA_NODE *)&cp_node->patnode); if (cp_node->ret_tmr.is_active) cpnd_tmr_stop(&cp_node->ret_tmr); + + cpnd_ckpt_sec_map_destroy(&cp_node->replica_info); + m_MMGR_FREE_CPND_CKPT_NODE(cp_node); } TRACE_LEAVE(); diff --git a/osaf/services/saf/cpsv/cpnd/cpnd_evt.c b/osaf/services/saf/cpsv/cpnd/cpnd_evt.c --- a/osaf/services/saf/cpsv/cpnd/cpnd_evt.c +++ b/osaf/services/saf/cpsv/cpnd/cpnd_evt.c @@ -79,7 +79,6 @@ static uint32_t cpnd_evt_proc_ckpt_refcn static uint32_t cpnd_proc_cpd_new_active(CPND_CB *cb); static uint32_t cpnd_is_cpd_up(CPND_CB *cb); - static uint32_t cpnd_transfer_replica(CPND_CB *cb, CPND_CKPT_NODE *cp_node, SaCkptCheckpointHandleT ckpt_id, CPSV_CPND_DEST_INFO *dest_list, CPSV_A2ND_CKPT_SYNC sync); static uint32_t cpnd_evt_proc_ckpt_ckpt_list_update(CPND_CB *cb, CPND_EVT *evt, CPSV_SEND_INFO *sinfo); @@ -774,6 +773,8 @@ static uint32_t cpnd_evt_proc_ckpt_open( cp_node->create_attrib = out_evt->info.cpnd.info.ckpt_info.attributes; cp_node->open_flags = SA_CKPT_CHECKPOINT_CREATE; + cpnd_ckpt_sec_map_init(&cp_node->replica_info); + if (evt->info.openReq.ckpt_flags & SA_CKPT_CHECKPOINT_READ) cl_node->open_reader_flags_cnt++; if (evt->info.openReq.ckpt_flags & SA_CKPT_CHECKPOINT_WRITE) @@ -978,6 +979,7 @@ static uint32_t cpnd_evt_proc_ckpt_open( } if (cp_node->ret_tmr.is_active) cpnd_tmr_stop(&cp_node->ret_tmr); + cpnd_ckpt_sec_map_destroy(&cp_node->replica_info); m_MMGR_FREE_CPND_CKPT_NODE(cp_node); agent_rsp: @@ -2294,55 +2296,69 @@ static uint32_t cpnd_evt_proc_ckpt_sect_ evt->info.sec_creatReq.init_data; send_evt.info.cpnd.info.active_sec_creat.init_size = evt->info.sec_creatReq.init_size; - rc = cpnd_mds_msg_sync_send(cb, NCSMDS_SVC_ID_CPND, tmp->dest, + + if (m_CPND_IS_ALL_REPLICA_ATTR_SET(cp_node->create_attrib.creationFlags) == true) { + rc = cpnd_mds_msg_sync_send(cb, NCSMDS_SVC_ID_CPND, tmp->dest, &send_evt, &out_evt, CPND_WAIT_TIME(evt->info. sec_creatReq.init_size)); - if (rc != NCSCC_RC_SUCCESS) { - if (rc == NCSCC_RC_REQ_TIMOUT) { - TRACE_4("cpnd active to remote mds send fail for cpnd_mdest_id:%"PRIu64" \ - dest:%"PRIu64",ckpt_id:%llx,return val:%d", - cb->cpnd_mdest_id, tmp->dest, - cp_node->ckpt_id, rc); + if (rc != NCSCC_RC_SUCCESS) { + if (rc == NCSCC_RC_REQ_TIMOUT) { + TRACE_4("cpnd active to remote mds send fail for cpnd_mdest_id:%"PRIu64" \ + dest:%"PRIu64",ckpt_id:%llx,return val:%d", + cb->cpnd_mdest_id, tmp->dest, + cp_node->ckpt_id, rc); + } + } + + if (out_evt + && out_evt->info.cpnd.info.active_sec_creat_rsp.error != + SA_AIS_OK) { + CPND_CKPT_SECTION_INFO *tmp_sec_info = NULL; + memset(&send_evt, '\0', sizeof(CPSV_EVT)); + send_evt.type = CPSV_EVT_TYPE_CPA; + send_evt.info.cpa.type = CPA_EVT_ND2A_SEC_CREATE_RSP; + /* TBD: Don't know what to do, revisit this. Ideally send the request to + other CPNDs to delete */ + /* Section Create fails with SA_AIS_NOT_VALID */ + send_evt.info.cpa.info.sec_creat_rsp.error = + out_evt->info.cpnd.info.active_sec_creat_rsp.error; + TRACE_4("cpnd ckpt sect creqte failed for ckpt_id:%llx,error value:%d", + cp_node->ckpt_id,send_evt.info.cpa.info.sec_creat_rsp.error); + + /* delete the section */ + if (gen_sec_id) + tmp_sec_info = + cpnd_ckpt_sec_del(cp_node, &sec_info->sec_id); + else + tmp_sec_info = + cpnd_ckpt_sec_del(cp_node, + evt->info.sec_creatReq. + sec_attri.sectionId); + + if (tmp_sec_info == sec_info) { + cp_node->replica_info. + shm_sec_mapping[sec_info->lcl_sec_id] = 1; + m_CPND_FREE_CKPT_SECTION(sec_info); + } else { + TRACE_4("cpnd ckpt sect del failed "); + } + cpnd_evt_destroy(out_evt); + out_evt = NULL; + goto agent_rsp; } } - - if (out_evt - && out_evt->info.cpnd.info.active_sec_creat_rsp.error != - SA_AIS_OK) { - CPND_CKPT_SECTION_INFO *tmp_sec_info = NULL; - memset(&send_evt, '\0', sizeof(CPSV_EVT)); - send_evt.type = CPSV_EVT_TYPE_CPA; - send_evt.info.cpa.type = CPA_EVT_ND2A_SEC_CREATE_RSP; - /* TBD: Don't know what to do, revisit this. Ideally send the request to - other CPNDs to delete */ - /* Section Create fails with SA_AIS_NOT_VALID */ - send_evt.info.cpa.info.sec_creat_rsp.error = - out_evt->info.cpnd.info.active_sec_creat_rsp.error; - TRACE_4("cpnd ckpt sect creqte failed for ckpt_id:%llx,error value:%d", - cp_node->ckpt_id,send_evt.info.cpa.info.sec_creat_rsp.error); - - /* delete the section */ - if (gen_sec_id) - tmp_sec_info = - cpnd_ckpt_sec_del(cp_node, &sec_info->sec_id); - else - tmp_sec_info = - cpnd_ckpt_sec_del(cp_node, - evt->info.sec_creatReq. - sec_attri.sectionId); - - if (tmp_sec_info == sec_info) { - cp_node->replica_info. - shm_sec_mapping[sec_info->lcl_sec_id] = 1; - m_CPND_FREE_CKPT_SECTION(sec_info); - } else { - TRACE_4("cpnd ckpt sect del failed "); - } - cpnd_evt_destroy(out_evt); - out_evt = NULL; - goto agent_rsp; + else if ((m_CPND_IS_ACTIVE_REPLICA_ATTR_SET(cp_node->create_attrib.creationFlags) == true) || + (m_CPND_IS_ACTIVE_REPLICA_WEAK_ATTR_SET(cp_node->create_attrib.creationFlags) == true)) { + rc = cpnd_mds_msg_send(cb, NCSMDS_SVC_ID_CPND, tmp->dest, &send_evt); + if (rc == NCSCC_RC_FAILURE) { + if (rc == NCSCC_RC_REQ_TIMOUT) { + LOG_ER("CPND - MDS send failed from Active Dest to Remote Dest cpnd_mdest_id:%"PRIu64",\ + dest:%"PRIu64",ckpt_id:%llx:rc:%d for replica sect create",cb->cpnd_mdest_id, tmp->dest,cp_node->ckpt_id, rc); + } + } } + tmp = tmp->next; if (out_evt) { cpnd_evt_destroy(out_evt); @@ -3264,7 +3280,7 @@ static uint32_t cpnd_evt_proc_ckpt_sync( goto agent_rsp; } - if (cp_node->replica_info.section_info == NULL) { + if (cpnd_ckpt_sec_empty(&cp_node->replica_info)) { send_evt.info.cpa.info.sync_rsp.error = SA_AIS_ERR_NOT_EXIST; goto agent_rsp; } @@ -3399,7 +3415,7 @@ static uint32_t cpnd_evt_proc_nd2nd_ckpt rc = cpnd_mds_send_rsp(cb, sinfo, &send_evt); } - if ((cp_node->replica_info.n_secs > 0) && (cp_node->replica_info.section_info)) { + if ((cp_node->replica_info.n_secs > 0) && !cpnd_ckpt_sec_empty(&cp_node->replica_info)) { if (evt->info.sync_req.is_ckpt_open) { dest_list.dest = sinfo->dest; @@ -3977,6 +3993,8 @@ static uint32_t cpnd_evt_proc_ckpt_creat cp_node->create_attrib = evt->info.ckpt_create.ckpt_info.attributes; cp_node->ckpt_id = evt->info.ckpt_create.ckpt_info.ckpt_id; + cpnd_ckpt_sec_map_init(&cp_node->replica_info); + if (evt->info.ckpt_create.ckpt_info.is_active_exists == true) { cp_node->active_mds_dest = evt->info.ckpt_create.ckpt_info.active_dest; cp_node->is_active_exist = true; @@ -3998,6 +4016,7 @@ static uint32_t cpnd_evt_proc_ckpt_creat rc = NCSCC_RC_FAILURE; if (cp_node->ret_tmr.is_active) cpnd_tmr_stop(&cp_node->ret_tmr); + cpnd_ckpt_sec_map_destroy(&cp_node->replica_info); m_MMGR_FREE_CPND_CKPT_NODE(cp_node); return rc; } @@ -4536,7 +4555,7 @@ static uint32_t cpnd_transfer_replica(CP send_evt.info.cpnd.info.ckpt_nd2nd_sync.ckpt_id = ckpt_id; send_evt.info.cpnd.info.ckpt_nd2nd_sync.ckpt_sync = sync; - tmp_sec_info = cp_node->replica_info.section_info; + tmp_sec_info = cpnd_ckpt_sec_get_first(&cp_node->replica_info); if (tmp_sec_info == NULL) { rc = NCSCC_RC_FAILURE; TRACE_4("cpnd ckpt memory allocation failed"); @@ -4604,7 +4623,7 @@ static uint32_t cpnd_transfer_replica(CP num++; total_num++; - tmp_sec_info = tmp_sec_info->next; + tmp_sec_info = cpnd_ckpt_sec_get_next(&cp_node->replica_info, tmp_sec_info); } TRACE_LEAVE(); diff --git a/osaf/services/saf/cpsv/cpnd/cpnd_proc.c b/osaf/services/saf/cpsv/cpnd/cpnd_proc.c --- a/osaf/services/saf/cpsv/cpnd/cpnd_proc.c +++ b/osaf/services/saf/cpsv/cpnd/cpnd_proc.c @@ -1095,7 +1095,7 @@ CPSV_CKPT_DATA *cpnd_ckpt_generate_cpsv_ CPND_CKPT_SECTION_INFO *tmp_sec_info = NULL; uint32_t i; - tmp_sec_info = cp_node->replica_info.section_info; + tmp_sec_info = cpnd_ckpt_sec_get_first(&cp_node->replica_info); for (i = 0; i < cp_node->replica_info.n_secs; i++) { tmp_sec_data = m_MMGR_ALLOC_CPSV_CKPT_DATA; @@ -1111,7 +1111,7 @@ CPSV_CKPT_DATA *cpnd_ckpt_generate_cpsv_ tmp_sec_data->next = sec_data; sec_data = tmp_sec_data; - tmp_sec_info = tmp_sec_info->next; + tmp_sec_info = cpnd_ckpt_sec_get_next(&cp_node->replica_info, tmp_sec_info); } return sec_data; @@ -1653,7 +1653,7 @@ cpnd_proc_getnext_section(CPND_CKPT_NODE { CPND_CKPT_SECTION_INFO *pSecPtr = NULL, *pTmpSecPtr = NULL; - pSecPtr = cp_node->replica_info.section_info; + pSecPtr = cpnd_ckpt_sec_get_first(&cp_node->replica_info); TRACE_ENTER(); if (cp_node->replica_info.n_secs == 0 || (cp_node->replica_info.n_secs <= get_next->n_secs_trav)) { @@ -1679,12 +1679,8 @@ cpnd_proc_getnext_section(CPND_CKPT_NODE /* search the existing section id */ *n_secs_trav = get_next->n_secs_trav; - while (pSecPtr != NULL && *n_secs_trav != 0) { - if ((pSecPtr->sec_id.idLen == get_next->section_id.idLen) && - (memcmp(pSecPtr->sec_id.id, get_next->section_id.id, get_next->section_id.idLen) == 0)) { - break; - } - pSecPtr = pSecPtr->next; + if (pSecPtr != NULL && *n_secs_trav != 0) { + pSecPtr = cpnd_ckpt_sec_get(cp_node, &get_next->section_id); } /* if next is NULL then return no more sections */ if (pSecPtr == NULL) { @@ -1696,7 +1692,7 @@ cpnd_proc_getnext_section(CPND_CKPT_NODE if (*n_secs_trav == 0) pTmpSecPtr = pSecPtr; else - pTmpSecPtr = pSecPtr->next; + pTmpSecPtr = cpnd_ckpt_sec_get_next(&cp_node->replica_info, pSecPtr); switch (get_next->filter) { case SA_CKPT_SECTIONS_ANY: @@ -1714,7 +1710,7 @@ cpnd_proc_getnext_section(CPND_CKPT_NODE (*n_secs_trav)++; break; } else - pTmpSecPtr = pTmpSecPtr->next; + pTmpSecPtr = cpnd_ckpt_sec_get_next(&cp_node->replica_info, pTmpSecPtr); } if (pTmpSecPtr == NULL) { TRACE_4("cpnd replica has no sections "); @@ -1729,7 +1725,7 @@ cpnd_proc_getnext_section(CPND_CKPT_NODE (*n_secs_trav)++; break; } else - pTmpSecPtr = pTmpSecPtr->next; + pTmpSecPtr = cpnd_ckpt_sec_get_next(&cp_node->replica_info, pTmpSecPtr); } if (pTmpSecPtr == NULL) { TRACE_4("cpnd replica has no sections in lEQ expiration time"); @@ -1744,7 +1740,7 @@ cpnd_proc_getnext_section(CPND_CKPT_NODE (*n_secs_trav)++; break; } else - pTmpSecPtr = pTmpSecPtr->next; + pTmpSecPtr = cpnd_ckpt_sec_get_next(&cp_node->replica_info, pTmpSecPtr); } if (pTmpSecPtr == NULL) { TRACE_4("cpnd replica has no sections in GEQ expiration time"); @@ -2048,10 +2044,10 @@ void cpnd_dump_replica_info(CPND_CKPT_RE if (ckpt_replica_node->n_secs) { CPND_CKPT_SECTION_INFO *sec_info = NULL; - sec_info = ckpt_replica_node->section_info; + sec_info = cpnd_ckpt_sec_get_first(ckpt_replica_node); while (sec_info != NULL) { cpnd_dump_section_info(sec_info); - sec_info = sec_info->next; + sec_info = cpnd_ckpt_sec_get_next(ckpt_replica_node, sec_info); } } } diff --git a/osaf/services/saf/cpsv/cpnd/cpnd_res.c b/osaf/services/saf/cpsv/cpnd/cpnd_res.c --- a/osaf/services/saf/cpsv/cpnd/cpnd_res.c +++ b/osaf/services/saf/cpsv/cpnd/cpnd_res.c @@ -93,14 +93,7 @@ uint32_t cpnd_client_extract_bits(uint32 uint32_t cpnd_res_ckpt_sec_add(CPND_CKPT_SECTION_INFO *pSecPtr, CPND_CKPT_NODE *cp_node) { - if (cp_node->replica_info.section_info != NULL) { - pSecPtr->next = cp_node->replica_info.section_info; - cp_node->replica_info.section_info->prev = pSecPtr; - cp_node->replica_info.section_info = pSecPtr; - } else { - cp_node->replica_info.section_info = pSecPtr; - } - return NCSCC_RC_SUCCESS; + return cpnd_ckpt_sec_add_db(&cp_node->replica_info, pSecPtr); } @@ -118,10 +111,10 @@ uint32_t cpnd_res_ckpt_sec_del(CPND_CKPT { CPND_CKPT_SECTION_INFO *pSecPtr = NULL, *nextPtr = NULL; - pSecPtr = cp_node->replica_info.section_info; + pSecPtr = cpnd_ckpt_sec_get_first(&cp_node->replica_info); while (pSecPtr != NULL) { nextPtr = pSecPtr; - pSecPtr = pSecPtr->next; + pSecPtr = cpnd_ckpt_sec_get_next(&cp_node->replica_info, pSecPtr); if ((nextPtr->sec_id.id != NULL) && (nextPtr->sec_id.idLen != 0)) { m_MMGR_FREE_CPSV_DEFAULT_VAL(nextPtr->sec_id.id, NCS_SERVICE_ID_CPND); } @@ -466,6 +459,8 @@ void *cpnd_restart_shm_create(NCS_OS_POS cp_node->is_unlink = cp_info.is_unlink; cp_node->close_time = cp_info.close_time; cp_node->cpnd_rep_create = cp_info.cpnd_rep_create; + cpnd_ckpt_sec_map_init(&cp_node->replica_info); + /* Non-collocated Differentiator flag */ if (cp_info.cpnd_rep_create) { /* OPEN THE SHARED MEMORY ALREADY CREATED FOR CHECKPOINT REPLICA */ diff --git a/osaf/services/saf/cpsv/cpnd/cpnd_sec.cc b/osaf/services/saf/cpsv/cpnd/cpnd_sec.cc new file mode 100644 --- /dev/null +++ b/osaf/services/saf/cpsv/cpnd/cpnd_sec.cc @@ -0,0 +1,424 @@ +/* -*- OpenSAF -*- + * + * (C) Copyright 2008 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): Emerson Network Power + * + */ + +/***************************************************************************** + * FILE NAME: cpnd_sec.cc + * + * DESCRIPTION: C++ implementation of section id map + * + ****************************************************************************/ + +#include <cassert> +#include <map> +extern "C" { + #include "cpnd.h" +} + +struct ltSectionIdT { + bool operator()(const SaCkptSectionIdT *s1, const SaCkptSectionIdT *s2) const + { + bool status(false); + + if (s1->idLen < s2->idLen) + status = true; + else if (s1->idLen > s2->idLen) + status = false; + else + status = (memcmp(s1->id, s2->id, s1->idLen) < 0); + + return status; + } +}; + +typedef std::map<const SaCkptSectionIdT *, + CPND_CKPT_SECTION_INFO *, + ltSectionIdT> SectionMap; + +typedef std::map<uint32_t, CPND_CKPT_SECTION_INFO *> LocalSectionIdMap; + +void +cpnd_ckpt_sec_map_init(CPND_CKPT_REPLICA_INFO *replicaInfo) +{ + if (replicaInfo->section_db) { + LOG_ER("section map already exists"); + assert(false); + } + + if (replicaInfo->local_section_db) { + LOG_ER("section map for local section id already exists"); + assert(false); + } + + replicaInfo->section_db = new SectionMap; + replicaInfo->local_section_db = new LocalSectionIdMap; +} + +void +cpnd_ckpt_sec_map_destroy(CPND_CKPT_REPLICA_INFO *replicaInfo) +{ + delete static_cast<SectionMap *>(replicaInfo->section_db); + delete static_cast<LocalSectionIdMap *>(replicaInfo->local_section_db); + + replicaInfo->section_db = 0; + replicaInfo->local_section_db = 0; +} + +/**************************************************************************** + * Name : cpnd_ckpt_sec_get + * + * Description : Function to Find the section in a checkpoint. + * + * Arguments : CPND_CKPT_NODE *cp_node - Check point node. + * : SaCkptSectionIdT id - Section Identifier + * + * Return Values : NULL/CPND_CKPT_SECTION_INFO + * + * Notes : None. + *****************************************************************************/ +CPND_CKPT_SECTION_INFO * +cpnd_ckpt_sec_get(const CPND_CKPT_NODE *cp_node, const SaCkptSectionIdT *id) +{ + CPND_CKPT_SECTION_INFO *sectionInfo(0); + + TRACE_ENTER(); + + if (cp_node->replica_info.n_secs) { + SectionMap *map(static_cast<SectionMap *> + (cp_node->replica_info.section_db)); + + if (map) { + SectionMap::iterator it(map->find(id)); + + if (it != map->end()) + sectionInfo = it->second; + } + else { + LOG_ER("can't find map in cpnd_ckpt_sec_get"); + assert(false); + } + } + else { + TRACE_4("cpnd replica has no section for ckpt_id:%llx",cp_node->ckpt_id); + } + + TRACE_LEAVE(); + return sectionInfo; +} + +/**************************************************************************** + * Name : cpnd_ckpt_sec_get_create + * + * Description : Function to Find the section in a checkpoint before create. + * + * Arguments : CPND_CKPT_NODE *cp_node - Check point node. + * : SaCkptSectionIdT id - Section Identifier + * + * Return Values : NULL/CPND_CKPT_SECTION_INFO + * + * Notes : None. + *****************************************************************************/ +CPND_CKPT_SECTION_INFO * +cpnd_ckpt_sec_get_create(const CPND_CKPT_NODE *cp_node, + const SaCkptSectionIdT *id) +{ + return cpnd_ckpt_sec_get(cp_node, id); +} + +/**************************************************************************** + * Name : cpnd_ckpt_sec_find + * + * Description : Function to Find the section in a checkpoint. + * + * Arguments : CPND_CKPT_NODE *cp_node - Check point node. + * : SaCkptSectionIdT id - Section Identifier + * + * Return Values : NCSCC_RC_FAILURE/NCSCC_RC_SUCCESS + * + * Notes : None. + *****************************************************************************/ +uint32_t +cpnd_ckpt_sec_find(const CPND_CKPT_NODE *cp_node, const SaCkptSectionIdT *id) +{ + return (cpnd_ckpt_sec_get(cp_node, id)) ? NCSCC_RC_SUCCESS : NCSCC_RC_FAILURE; +} + +/**************************************************************************** + * Name : cpnd_ckpt_sec_del + * + * Description : Function to remove the section from a checkpoint. + * + * Arguments : CPND_CKPT_NODE *cp_node - Check point node. + * : SaCkptSectionIdT id - Section Identifier + * + * Return Values : ptr to CPND_CKPT_SECTION_INFO/NULL; + * + * Notes : None. + *****************************************************************************/ +CPND_CKPT_SECTION_INFO * +cpnd_ckpt_sec_del(CPND_CKPT_NODE *cp_node, SaCkptSectionIdT *id) +{ + CPND_CKPT_SECTION_INFO *sectionInfo(0); + + TRACE_ENTER(); + + SectionMap *map(static_cast<SectionMap *>(cp_node->replica_info.section_db)); + + if (map) { + SectionMap::iterator it(map->find(id)); + + if (it != map->end()) { + sectionInfo = it->second; + map->erase(it); + } + } + else { + LOG_ER("can't find map in cpnd_ckpt_sec_del"); + assert(false); + } + + LocalSectionIdMap *localSecMap(static_cast<LocalSectionIdMap *> + (cp_node->replica_info.local_section_db)); + + if (localSecMap) { + if (sectionInfo) { + LocalSectionIdMap::iterator it(localSecMap->find(sectionInfo->lcl_sec_id)); + + if (it != localSecMap->end()) + localSecMap->erase(it); + } + } + else { + LOG_ER("can't find local sec map in cpnd_ckpt_sec_del"); + assert(false); + } + + if (sectionInfo) { + cp_node->replica_info.n_secs--; + cp_node->replica_info.mem_used = cp_node->replica_info.mem_used - (sectionInfo->sec_size); + + // UPDATE THE SECTION HEADER + uint32_t rc(cpnd_sec_hdr_update(sectionInfo, cp_node)); + if (rc == NCSCC_RC_FAILURE) { + TRACE_4("cpnd sect hdr update failed"); + } + + // UPDATE THE CHECKPOINT HEADER + rc = cpnd_ckpt_hdr_update(cp_node); + if (rc == NCSCC_RC_FAILURE) { + TRACE_4("cpnd ckpt hdr update failed"); + } + } + + TRACE_LEAVE(); + + return sectionInfo; +} + +/**************************************************************************** + * Name : cpnd_ckpt_sec_add_db + * + * Description : Function to add the section to a checkpoint. + * + * Arguments : CPND_CKPT_REPLICA_INFO *replicaInfo - Check point replica. + * : CPND_CKPT_SECTION_INFO sectionInfo - Section Info + * + * Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE + * + * Notes : None. + *****************************************************************************/ +uint32_t +cpnd_ckpt_sec_add_db(CPND_CKPT_REPLICA_INFO *replicaInfo, + CPND_CKPT_SECTION_INFO *sectionInfo) +{ + uint32_t rc(NCSCC_RC_SUCCESS); + + SectionMap *map(static_cast<SectionMap *>(replicaInfo->section_db)); + + if (map) { + std::pair<SectionMap::iterator, bool> p(map->insert( + std::make_pair(§ionInfo->sec_id, sectionInfo))); + + if (!p.second) { + LOG_ER("unable to add section info to map"); + rc = NCSCC_RC_FAILURE; + } + } + else { + LOG_ER("can't find map in cpnd_ckpt_sec_add_db"); + assert(false); + } + + LocalSectionIdMap *localSecMap( + static_cast<LocalSectionIdMap *>(replicaInfo->local_section_db)); + + if (localSecMap) { + std::pair<LocalSectionIdMap::iterator, bool> p(localSecMap->insert( + std::make_pair(sectionInfo->lcl_sec_id, sectionInfo))); + + if (!p.second) { + LOG_ER("unable to add section info to local section id map"); + rc = NCSCC_RC_FAILURE; + } + } + else { + LOG_ER("can't find local sec map in cpnd_ckpt_sec_add_db"); + assert(false); + } + + return rc; +} + +/**************************************************************************** + * Name : cpnd_ckpt_delete_all_sect + * + * Description : Function to add the section to a checkpoint. + * + * Arguments : CPND_CKPT_NODE *cp_node - Check point node. + * + * Return Values : NCSCC_RC_FAILURE/NCSCC_RC_SUCCESS + * + * Notes : None. + *****************************************************************************/ +void +cpnd_ckpt_delete_all_sect(CPND_CKPT_NODE *cp_node) +{ + LocalSectionIdMap *localSecMap(static_cast<LocalSectionIdMap *> + (cp_node->replica_info.local_section_db)); + + if (localSecMap) + localSecMap->erase(localSecMap->begin(), localSecMap->end()); + else { + LOG_ER("can't find local sec map in cpnd_ckpt_delete_all_sect"); + assert(false); + } + + SectionMap *map(static_cast<SectionMap *>(cp_node->replica_info.section_db)); + + if (map) { + SectionMap::iterator it(map->begin()); + + while (it != map->end()) { + cp_node->replica_info.n_secs--; + + CPND_CKPT_SECTION_INFO *section(it->second); + + if (section->ckpt_sec_exptmr.is_active) + cpnd_tmr_stop(§ion->ckpt_sec_exptmr); + + m_CPND_FREE_CKPT_SECTION(section); + + SectionMap::iterator tmpIt(it); + ++it; + + map->erase(tmpIt); + } + } + else { + LOG_ER("can't find sec map in cpnd_ckpt_delete_all_sect"); + assert(false); + } +} + +/**************************************************************************** + * Name : cpnd_get_sect_with_id + * + * Description : Function to Find the section in a checkpoint. + * + * Arguments : CPND_CKPT_NODE *cp_node - Check point node. + * : lck_sec_id - lcl Section Identifier + * + * Return Values : NULL/ pointer to CPND_CKPT_SECTION_INFO + * + * Notes : None. + *****************************************************************************/ +CPND_CKPT_SECTION_INFO * +cpnd_get_sect_with_id(const CPND_CKPT_NODE *cp_node, uint32_t lcl_sec_id) +{ + CPND_CKPT_SECTION_INFO *sectionInfo(0); + + if (cp_node->replica_info.n_secs) { + LocalSectionIdMap *map(static_cast<LocalSectionIdMap *> + (cp_node->replica_info.local_section_db)); + + if (map) { + LocalSectionIdMap::iterator it(map->find(lcl_sec_id)); + + if (it != map->end()) + sectionInfo = it->second; + } + else { + LOG_ER("can't find sec map in cpnd_get_sect_with_id"); + assert(false); + } + } + else { + TRACE_4("cpnd replica has no sections for ckpt_id:%llx",cp_node->ckpt_id); + } + + return sectionInfo; +} + +bool +cpnd_ckpt_sec_empty(const CPND_CKPT_REPLICA_INFO *replicaInfo) +{ + SectionMap *map(static_cast<SectionMap *>(replicaInfo->section_db)); + + return map ? map->empty() : true; +} + +CPND_CKPT_SECTION_INFO * +cpnd_ckpt_sec_get_first(const CPND_CKPT_REPLICA_INFO *replicaInfo) +{ + CPND_CKPT_SECTION_INFO *sectionInfo(0); + + SectionMap *map(static_cast<SectionMap *>(replicaInfo->section_db)); + + if (map) { + SectionMap::iterator it(map->begin()); + + if (it != map->end()) + sectionInfo = it->second; + } + else { + LOG_ER("can't find sec map in cpnd_ckpt_sec_get_first"); + } + + return sectionInfo; +} + +CPND_CKPT_SECTION_INFO * +cpnd_ckpt_sec_get_next(const CPND_CKPT_REPLICA_INFO *replicaInfo, + const CPND_CKPT_SECTION_INFO *section) +{ + CPND_CKPT_SECTION_INFO *sectionInfo(0); + + SectionMap *map(static_cast<SectionMap *>(replicaInfo->section_db)); + + if (map) { + SectionMap::iterator it(map->find(§ion->sec_id)); + + if (it != map->end()) { + if (++it != map->end()) + sectionInfo = it->second; + } + } + else { + LOG_ER("can't find sec map in cpnd_ckpt_sec_get_next"); + } + + return sectionInfo; +} ------------------------------------------------------------------------------ "Accelerate Dev Cycles with Automated Cross-Browser Testing - For FREE Instantly run your Selenium tests across 300+ browser/OS combos. Get unparalleled scalability from the best Selenium testing platform available Simple to use. Nothing to install. Get started now for free." http://p.sf.net/sfu/SauceLabs _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel