void saftest_daemon_handle_incoming_clm_message(void *data, void *key) { clm_session_t *clm_session = data; fd_set *fd_mask = (fd_set *)key; SaAisErrorT err; if (NULL == data) { return; } if (!FD_ISSET(clm_session->selection_object, fd_mask)) { return; } saftest_log("Incoming request on clm selection fd %d. " "Calling saClmDispatch\n", clm_session->selection_object); saftest_assert(SA_DISPATCH_BLOCKING != clm_session->dispatch_flags, "It will have its own dispatch thread\n"); err = saClmDispatch(clm_session->clm_handle, clm_session->dispatch_flags); if (SA_AIS_OK != err) { saftest_log("Error %s performing saClmDispatch\n", get_error_string(err)); /* !!! We may only want to do this for "short-lived" drivers */ exit(1); } }
void saftest_daemon_handle_dispatch_request( saftest_map_table_entry_t *map_entry, saftest_msg_t *request, saftest_msg_t **reply) { clm_session_t *clm_session = NULL; SaAisErrorT status; SaDispatchFlagsT dispatch_flags; clm_driver_thread_t *cdt = get_current_clm_thread_data(); saftest_log("Received a dispatch request for id %d\n", saftest_msg_get_ubit32_value(request, "CLM_SESSION_ID")); clm_session = lookup_clm_session_from_request(request); dispatch_flags = saftest_dispatch_flags_from_string( saftest_msg_get_str_value(request, "DISPATCH_FLAGS")); saftest_assert(SAFTEST_DISPATCH_NONE != dispatch_flags, "Can't use SA_DISPATCH_NONE for a dispatch request\n"); saftest_assert((SA_DISPATCH_BLOCKING != dispatch_flags) || (FALSE == cdt->main_thread), "You can't call DISPATCH_BLOCKING in the main thread\n"); status = saClmDispatch(clm_session->clm_handle, dispatch_flags); if (SA_DISPATCH_BLOCKING != dispatch_flags) { /* * The client is only expecting a reply in non dispatch blocking * cases. Otherwise the client would hang until we finalized. */ (*reply) = saftest_reply_msg_create(request, map_entry->reply_op, status); } }
void saClmClusterTrackStop_01(void) { trackFlags = SA_TRACK_CURRENT; nodeId = 131343; invocation = 600; safassert(saClmInitialize(&clmHandle, &clmCallback11, &clmVersion_1), SA_AIS_OK); rc = saClmClusterTrack(clmHandle, trackFlags, NULL); rc = saClmClusterTrack(clmHandle, trackFlags, NULL); rc = saClmClusterNodeGetAsync(clmHandle, invocation, nodeId); rc = saClmClusterTrack(clmHandle, trackFlags, NULL); rc = saClmClusterNodeGetAsync(clmHandle, invocation, nodeId); rc = saClmClusterNodeGetAsync(clmHandle, invocation, nodeId); rc = saClmClusterTrack(clmHandle, trackFlags, NULL); safassert(saClmClusterTrackStop(clmHandle), SA_AIS_OK); safassert(saClmDispatch(clmHandle,SA_DISPATCH_ALL), SA_AIS_OK); rc = saClmClusterTrack(clmHandle, trackFlags, NULL); safassert(saClmClusterTrackStop(clmHandle), SA_AIS_OK); safassert(saClmFinalize(clmHandle), SA_AIS_OK); test_validate(rc, SA_AIS_OK); }
int main(int argc, char* argv[]) { /* Use syslog for logging (/var/log/messages) */ openlog(basename(argv[0]), LOG_PID, LOG_USER); //setenv("CLMSV_TRACE_PATHNAME","/tmp/clma.log",1); //only work if export before run this program SaAisErrorT rc; SaClmHandleT clmHandle; SaClmCallbacksT_4 clmCallbacks = { 0 }; SaVersionT version = { 'B', 4, 1 }; clmCallbacks.saClmClusterTrackCallback = clmClusterTrackCallback; rc = saClmInitialize_4(&clmHandle, &clmCallbacks, &version); if (rc != SA_AIS_OK) { syslog(LOG_ERR,"saClmInitialize_4 FAILED %u", rc); return 1; } SaSelectionObjectT clmFd; rc = saClmSelectionObjectGet(clmHandle, &clmFd); if (rc != SA_AIS_OK) { syslog(LOG_ERR,"saClmSelectionObjectGet FAILED %u", rc); return 1; } int clusterSize = 4; size_t sizeOfNotificationBuffer = (clusterSize * sizeof(SaClmClusterNotificationT_4)); SaClmClusterNotificationBufferT_4 clmlusterNotificationBuffer; clmlusterNotificationBuffer.viewNumber = 0; clmlusterNotificationBuffer.numberOfItems = clusterSize; clmlusterNotificationBuffer.notification = (SaClmClusterNotificationT_4*) calloc(1, sizeOfNotificationBuffer); if (clmlusterNotificationBuffer.notification == NULL) { syslog(LOG_ERR,"FAILED to allocate resources"); return 1; } SaUint8T trackFlags = SA_TRACK_CURRENT | SA_TRACK_CHANGES | SA_TRACK_START_STEP; //SA_TRACK_VALIDATE_STEP is supported with PLM only rc = saClmClusterTrack_4(clmHandle, trackFlags, &clmlusterNotificationBuffer); if (rc != SA_AIS_OK) { syslog(LOG_ERR,"saClmClusterTrack_4 FAILED %u", rc); if (rc == SA_AIS_ERR_NO_SPACE) { syslog(LOG_ERR,"rc = SA_AIS_ERR_NO_SPACE, numberOfItems = %d", clmlusterNotificationBuffer.numberOfItems); } free(clmlusterNotificationBuffer.notification); clmlusterNotificationBuffer.notification = NULL; return 1; } struct pollfd fds; fds.fd = clmFd; fds.events = POLLIN; while(1){ int res = poll(&fds, 1, -1); if (res == -1) { if (errno == EINTR) continue; else { syslog(LOG_ERR,"poll FAILED - %s", strerror(errno)); return 1; } } if (fds.revents & POLLIN) { syslog(LOG_INFO,"========= CLM event ==========="); rc = saClmDispatch(clmHandle, SA_DISPATCH_ONE); if (SA_AIS_OK != rc) { syslog(LOG_ERR,"saClmDispatch FAILED %u", rc); return 1; } } } }
static void test_clm_during_cpg_test(void) { SaClmHandleT clmHandle = { 0 }; SaAisErrorT err; SaClmCallbacksT callbacks = { .saClmClusterNodeGetCallback = _clm_nodeget_callback, .saClmClusterTrackCallback = _clm_nodetrack_callback, }; SaVersionT version = { .releaseCode = 'B', .majorVersion = 1, .minorVersion = 1 }; SaClmClusterNodeT node; int status = 0; pid_t r; while ( (err = saClmInitialize(&clmHandle, &callbacks, &version)) == SA_AIS_ERR_TRY_AGAIN ); if ( err != SA_AIS_OK ) DIE("saClmInitialize(): %d", err); if ( (err = saClmClusterNodeGet(clmHandle, SA_CLM_LOCAL_NODE_ID, 1000000, &node)) != SA_AIS_OK ) DIE("saClmNodeGet(): %d", err); test_data.node_id = node.nodeId; DPRINTF("We are '%.*s', ID: %d", node.nodeName.length, node.nodeName.value, node.nodeId); if ( (err = saClmClusterTrack(clmHandle, SA_TRACK_CURRENT | SA_TRACK_CHANGES, NULL)) != SA_AIS_OK ) DIE("saClmClusterTrack(): %d", err); r = 0; status = 0; /* Note: The man pages of FreeBSD says that waitpid() should return 0 if no process has ended * but I get 1 instead. Weird. * TODO(Jflesch): Figure out what I did wrong. */ while ( test_data.keep_dispatching && (test_data.test_cpg_pid == -1 || ( (r = waitpid(test_data.test_cpg_pid, &status, WNOHANG) != -1) && (r == 0 || r == 1 || (!WIFEXITED(status) && !WIFSIGNALED(status))) ) ) ) { if ( (err = saClmDispatch(clmHandle, SA_DISPATCH_ALL)) != SA_AIS_OK ) DIE("saClmDispatch(): %d", err); if ( test_data.nmb_peers == test_data.max_nmb_peers ) { if ( test_data.master_id != test_data.node_id ) { DPRINTF("Synchronized."); /* -> we are a slave, the only thing we have to do is run CPG tests again */ test_data.keep_dispatching = 0; test_data.run_cpg_test = 1; } else if ( test_data.test_cpg_pid == -1 ) { DPRINTF("Synchronized."); test_data.nmb_clm_notifications = 0; DPRINTF("(master) Running CPG tests ..."); test_data.test_cpg_pid = start_cpg_tests(); /* // */ DPRINTF("(master) CPG tests started"); } } usleep(10 * 1000); /* 10ms */ } if ( test_data.keep_dispatching ) /* => end of test */ { if ( test_data.test_cpg_pid < 0 ) DIE("CPG tests not even started"); if ( r <= -1 ) DIE("waitpid() failed: %d, %s", errno, strerror(errno)); if ( WIFSIGNALED(status) ) DIE("CPG tests died because of signal %d", WTERMSIG(status)); if ( WEXITSTATUS(status) != 0 ) DIE("CPG tests died returning the value %d", WEXITSTATUS(status)); } #ifdef BE_NICE if ( (err = saClmClusterTrackStop(clmHandle)) != SA_AIS_OK ) DIE("saClmTrackStop(): %d", err); #endif if ( (err = saClmFinalize(clmHandle)) != SA_AIS_OK ) DIE("saClmFinalize(): %d", err); if ( test_data.nmb_clm_notifications <= 0 ) DIE("Got no CLM notifications"); if ( test_data.run_cpg_test ) { DPRINTF("(slave) Running CPG tests ..."); test_cpg_multiplayer(test_data.max_nmb_peers); DPRINTF("(slave) CPG test finished"); } } void test_clm(int nmb_peers) { if ( nmb_peers <= 1 ) DIE("Not enought peers"); test_data = TEST_DATA_START_VALUE; test_data.max_nmb_peers = nmb_peers; DPRINTF(" - Rerun of the CPG multiplayer test, keeping an eye on CLM behavior"); test_clm_during_cpg_test(); /* DPRINTF(" - Misuse of the API"); ? */ }
int main(void) { SaSelectionObjectT st; SaErrorT ret; SaClmNodeIdT nid; SaClmCallbacksT my_callbacks = { .saClmClusterTrackCallback = (SaClmClusterTrackCallbackT)track_callback, .saClmClusterNodeGetCallback = (SaClmClusterNodeGetCallbackT)getnode_callback }; if ((ret = saClmInitialize(&hd, &my_callbacks, NULL)) != SA_OK) { fprintf(stderr, "saClmInitialize error, errno [%d]\n",ret); return 1; } if ((ret = saClmSelectionObjectGet(&hd, &st)) != SA_OK) { fprintf(stderr, "saClmSelectionObjectGet error, errno [%d]\n" , ret); return 1; } nid = 0; /* Synchronously get nodeId information */ printf("-------------------------------------------------\n"); printf("Get nodeId [%lu] info by SaClmClusterNodeGet\n", nid); if ((ret = saClmClusterNodeGet(nid, 10, &cn)) != SA_OK) { if (ret == SA_ERR_INVALID_PARAM) { fprintf(stderr, "NodeId [%lu] record not found!\n",nid); } else { fprintf(stderr , "saClmClusterNodeGet error, errno [%d]\n" , ret); return 1; } } else { dump_nodeinfo(&cn); } /* Asynchronously get my nodeId information */ nid = 1; printf("-------------------------------------------------\n"); printf("Get nodeId [%lu] info by SaClmClusterNodeGetAsync\n", nid); if ((ret = saClmClusterNodeGetAsync(&hd, 1234, nid, &cn)) != SA_OK) { if (ret == SA_ERR_INVALID_PARAM) { fprintf(stderr, "NodeId [%lu] record not found!\n",nid); } else { fprintf(stderr , "saClmClusterNodeGet error, errno [%d]\n" , ret); return 1; } } /* Start to track cluster membership changes events */ track_start(SIGUSR1); signal(SIGUSR2, &track_stop); for (;;) { fd_set rset; FD_ZERO(&rset); FD_SET(st, &rset); if (select(st + 1, &rset, NULL, NULL, NULL) == -1) { /* TODO should we use pselect here? */ if (errno == EINTR) continue; else { perror("select"); return 1; } } if ((ret = saClmDispatch(&hd, SA_DISPATCH_ALL)) != SA_OK) { if (ret == SA_ERR_LIBRARY) { fprintf(stderr, "I am evicted!\n"); return 1; } fprintf(stderr, "saClmDispatch error, errno [%d]\n" , ret); return 1; } } return 0; }
/**************************************************************************** * Name : eds_main_process * * Description : This is the function which is given as a input to the * EDS task. * This function will be select of both the FD's (AMF FD and * Mail Box FD), depending on which FD has been selected, it * will call the corresponding routines. * * Arguments : mbx - This is the mail box pointer on which EDS is * going to block. * * Return Values : None. * * Notes : None. *****************************************************************************/ void eds_main_process(SYSF_MBX *mbx) { NCS_SEL_OBJ mbx_fd; SaAisErrorT error = SA_AIS_OK; EDS_CB *eds_cb = NULL; int term_fd; TRACE_ENTER(); if (NULL == (eds_cb = (EDS_CB *)ncshm_take_hdl(NCS_SERVICE_ID_EDS, gl_eds_hdl))) { LOG_ER("Global take handle failed"); return; } mbx_fd = m_NCS_IPC_GET_SEL_OBJ(&eds_cb->mbx); /* Give back the handle */ ncshm_give_hdl(gl_eds_hdl); /* Initialize with IMM */ if (eds_imm_init(eds_cb) != SA_AIS_OK) { LOG_ER("Imm Init Failed. Exiting"); exit(EXIT_FAILURE); } daemon_sigterm_install(&term_fd); /* Set up all file descriptors to listen to */ fds[FD_TERM].fd = term_fd; fds[FD_TERM].events = POLLIN; fds[FD_AMF].fd = eds_cb->amfSelectionObject; fds[FD_AMF].events = POLLIN; fds[FD_CLM].fd = eds_cb->clm_sel_obj; fds[FD_CLM].events = POLLIN; fds[FD_MBCSV].fd = eds_cb->mbcsv_sel_obj; fds[FD_MBCSV].events = POLLIN; fds[FD_MBX].fd = mbx_fd.rmv_obj; fds[FD_MBX].events = POLLIN; fds[FD_IMM].fd = eds_cb->imm_sel_obj; fds[FD_IMM].events = POLLIN; TRACE("Entering the forever loop"); while (1) { if ((eds_cb->immOiHandle != 0) && (eds_cb->is_impl_set == true)){ fds[FD_IMM].fd = eds_cb->imm_sel_obj; fds[FD_IMM].events = POLLIN; nfds = NUM_FD; } else { nfds = NUM_FD - 1; } int ret = poll(fds, nfds, -1); if (ret == -1) { if (errno == EINTR) continue; TRACE("poll failed - %s", strerror(errno)); break; } /* process the sigterm */ if (fds[FD_TERM].revents & POLLIN) { daemon_exit(); } /* process all the AMF messages */ if (fds[FD_AMF].revents & POLLIN) { /* dispatch all the AMF pending callbacks */ error = saAmfDispatch(eds_cb->amf_hdl, SA_DISPATCH_ALL); if (error != SA_AIS_OK) LOG_ER("AMF Dispatch failed with rc = %d",error); } /* process all mbcsv messages */ if (fds[FD_MBCSV].revents & POLLIN) { error = eds_mbcsv_dispatch(eds_cb->mbcsv_hdl); if (NCSCC_RC_SUCCESS != error) LOG_ER("MBCSv Dispatch failed with rc = %d",error); } /* Process the EDS Mail box, if eds is ACTIVE. */ if (fds[FD_MBX].revents & POLLIN) { /* now got the IPC mail box event */ eds_process_mbx(mbx); } /* process the CLM messages */ if (fds[FD_CLM].revents & POLLIN) { /* dispatch all the AMF pending callbacks */ error = saClmDispatch(eds_cb->clm_hdl, SA_DISPATCH_ALL); if (error != SA_AIS_OK) LOG_ER("CLM Dispatch failed with rc = %d",error); } /* process the IMM messages */ if (eds_cb->immOiHandle && fds[FD_IMM].revents & POLLIN) { /* dispatch the IMM event */ error = saImmOiDispatch(eds_cb->immOiHandle, SA_DISPATCH_ONE); /* ** BAD_HANDLE is interpreted as an IMM service restart. Try ** reinitialize the IMM OI API in a background thread and let ** this thread do business as usual especially handling write ** requests. ** ** All other errors are treated as non-recoverable (fatal) and will ** cause an exit of the process. */ if (error == SA_AIS_ERR_BAD_HANDLE) { TRACE("saImmOiDispatch returned BAD_HANDLE"); /* Invalidate the IMM OI handle. */ saImmOiFinalize(eds_cb->immOiHandle); eds_cb->immOiHandle = 0; eds_cb->is_impl_set = false; eds_imm_reinit_bg(eds_cb); } else if (error != SA_AIS_OK) { LOG_ER("saImmOiDispatch FAILED with rc = %d", error); break; } } } TRACE_LEAVE(); return; } /* End eds_main_process() */