src/log/agent/lga.h | 3 + src/log/agent/lga_api.c | 2 +- src/log/agent/lga_mds.c | 70 +++++ src/log/agent/lga_util.c | 60 ++++- src/log/apitest/logtest.c | 2 +- src/log/apitest/logtestfr.c | 2 +- src/log/apitest/saflogtest.c | 2 +- src/log/apitest/tet_LogOiOps.c | 71 +++++ src/log/apitest/tet_log_longDN.c | 2 +- src/log/apitest/tet_saLogFilterSetCallbackT.c | 364 +++++++++++++++++++++++++- src/log/apitest/tet_saLogStreamOpen_2.c | 2 - src/log/common/lgsv_defs.h | 2 +- src/log/common/lgsv_msg.h | 7 + src/log/logd/lgs_imm.cc | 7 + src/log/logd/lgs_mds.cc | 57 ++- src/log/logd/lgs_util.cc | 80 +++++ src/log/logd/lgs_util.h | 2 + src/log/tools/saf_logger.c | 2 +- src/osaf/saflog/saflog.c | 4 +- 19 files changed, 707 insertions(+), 34 deletions(-)
Implement SaLogFilterSetCallbackT which is mentioned at section 3.6.5 SaLogFilterSetCallbackT @ AIS LOG document. LGS: - Whenever severity filter is changed for app and systerm streams, lgs will find which clients that associate with the stream. Then lgs sends message callback to clients. - Encoding callback message for severity filter callback LGA: - Decoding callback message for severity callback from lgs and send the message to the client which setting filter callback. - Dispatching severity filter callback - Encrease version of log service to A.02.03 diff --git a/src/log/agent/lga.h b/src/log/agent/lga.h --- a/src/log/agent/lga.h +++ b/src/log/agent/lga.h @@ -155,5 +155,8 @@ extern bool lga_validate_lga_client_hdl( extern lga_client_hdl_rec_t *lga_find_hdl_rec_by_regid(lga_cb_t *lga_cb, uint32_t client_id); extern void lga_msg_destroy(lgsv_msg_t *msg); extern bool lga_is_extended_name_valid(const SaNameT* name); +extern lga_log_stream_hdl_rec_t *lga_find_stream_hdl_rec_by_regid(lga_cb_t *lga_cb, + uint32_t client_id, + uint32_t stream_id); #endif // LOG_AGENT_LGA_H_ diff --git a/src/log/agent/lga_api.c b/src/log/agent/lga_api.c --- a/src/log/agent/lga_api.c +++ b/src/log/agent/lga_api.c @@ -406,11 +406,11 @@ SaAisErrorT saLogDispatch(SaLogHandleT l rc = SA_AIS_ERR_UNAVAILABLE; goto done; } - osaf_mutex_unlock_ordie(&lga_cb.cb_lock); if ((rc = lga_hdl_cbk_dispatch(&lga_cb, hdl_rec, dispatchFlags)) != SA_AIS_OK) TRACE("LGA_DISPATCH_FAILURE"); + osaf_mutex_unlock_ordie(&lga_cb.cb_lock); ncshm_give_hdl(logHandle); done: diff --git a/src/log/agent/lga_mds.c b/src/log/agent/lga_mds.c --- a/src/log/agent/lga_mds.c +++ b/src/log/agent/lga_mds.c @@ -559,6 +559,39 @@ static uint32_t lga_lgs_msg_proc(lga_cb_ } break; + case LGSV_SEVERITY_FILTER_CALLBACK: + { + lga_client_hdl_rec_t *lga_hdl_rec; + /** Lookup the hdl rec by client_id **/ + lga_hdl_rec = lga_find_hdl_rec_by_regid(cb, lgsv_msg->info.cbk_info.lgs_client_id); + if (lga_hdl_rec == NULL) { + TRACE("regid not found"); + lga_msg_destroy(lgsv_msg); + TRACE_LEAVE(); + return NCSCC_RC_FAILURE; + } + + /* Check if client did not set filter callback */ + if(lga_hdl_rec->reg_cbk.saLogFilterSetCallback == NULL) { + lga_msg_destroy(lgsv_msg); + break; + } + + TRACE_2("LGSV_SEVERITY_FILTER_CALLBACK: client_id = %d, stream_id %d, severity=%d", + (int)lgsv_msg->info.cbk_info.lgs_client_id, + (int)lgsv_msg->info.cbk_info.lgs_stream_id, + (int)lgsv_msg->info.cbk_info.serverity_filter_cbk.log_severity); + + /** enqueue this message **/ + if (NCSCC_RC_SUCCESS != m_NCS_IPC_SEND(&lga_hdl_rec->mbx, lgsv_msg, prio)) { + TRACE("IPC SEND FAILED"); + lga_msg_destroy(lgsv_msg); + TRACE_LEAVE(); + return NCSCC_RC_FAILURE; + } + } + break; + default: TRACE("unknown type %d", lgsv_msg->info.cbk_info.type); lga_msg_destroy(lgsv_msg); @@ -932,6 +965,36 @@ static uint32_t lga_dec_clm_node_status_ } /**************************************************************************** +Name : lga_dec_serverity_cbk_msg + +Description : This routine decodes message + +Arguments : NCS_UBAID *uba, + LGSV_MSG *msg + +Return Values : uint32_t + +Notes : None. +******************************************************************************/ +static uint32_t lga_dec_serverity_cbk_msg(NCS_UBAID *uba, lgsv_msg_t *msg) +{ + uint8_t *p8; + uint32_t total_bytes = 0; + lgsv_cbk_info_t *cbk_infos = &msg->info.cbk_info; + uint8_t local_data[100]; + + osafassert(uba != NULL); + + p8 = ncs_dec_flatten_space(uba, local_data, 6); + cbk_infos->lgs_stream_id = ncs_decode_32bit(&p8); + cbk_infos->serverity_filter_cbk.log_severity = ncs_decode_16bit(&p8); + ncs_dec_skip_space(uba, 6); + total_bytes += 6; + + return total_bytes; +} + +/**************************************************************************** Name : lga_dec_lstr_open_sync_rsp_msg Description : This routine decodes a log stream open sync response message @@ -1053,6 +1116,13 @@ static uint32_t lga_mds_dec(struct ncsmd msg->info.cbk_info.lgs_client_id); total_bytes += lga_dec_clm_node_status_cbk_msg(uba, msg); break; + case LGSV_SEVERITY_FILTER_CALLBACK: + total_bytes += lga_dec_serverity_cbk_msg(uba, msg); + TRACE_2("decode severity filter message, lgs_client_id=%d" + " lgs_stream_id=%d", + msg->info.cbk_info.lgs_client_id, + msg->info.cbk_info.lgs_stream_id); + break; default: TRACE_2("Unknown callback type = %d!", msg->info.cbk_info.type); break; diff --git a/src/log/agent/lga_util.c b/src/log/agent/lga_util.c --- a/src/log/agent/lga_util.c +++ b/src/log/agent/lga_util.c @@ -171,6 +171,19 @@ static void lga_hdl_cbk_rec_prc(lga_cb_t reg_cbk->saLogWriteLogCallback(cbk_info->inv, cbk_info->write_cbk.error); } break; + + case LGSV_SEVERITY_FILTER_CALLBACK: + { + if (reg_cbk->saLogFilterSetCallback) { + lga_log_stream_hdl_rec_t *lga_str_hdl_rec = + lga_find_stream_hdl_rec_by_regid(cb, cbk_info->lgs_client_id, + cbk_info->lgs_stream_id); + reg_cbk->saLogFilterSetCallback(lga_str_hdl_rec->log_stream_hdl, + cbk_info->serverity_filter_cbk.log_severity); + } + } + break; + default: TRACE("unknown callback type: %d", cbk_info->type); break; @@ -197,7 +210,8 @@ static SaAisErrorT lga_hdl_cbk_dispatch_ /* Nonblk receive to obtain the message from priority queue */ while (NULL != (cbk_msg = (lgsv_msg_t *) m_NCS_IPC_NON_BLK_RECEIVE(&hdl_rec->mbx, cbk_msg))) { - if (cbk_msg->info.cbk_info.type == LGSV_WRITE_LOG_CALLBACK_IND) { + if (cbk_msg->info.cbk_info.type == LGSV_WRITE_LOG_CALLBACK_IND || + cbk_msg->info.cbk_info.type == LGSV_SEVERITY_FILTER_CALLBACK) { lga_hdl_cbk_rec_prc(cb, cbk_msg, &hdl_rec->reg_cbk); lga_msg_destroy(cbk_msg); break; @@ -232,7 +246,8 @@ static uint32_t lga_hdl_cbk_dispatch_all do { if (NULL == (cbk_msg = (lgsv_msg_t *)m_NCS_IPC_NON_BLK_RECEIVE(&hdl_rec->mbx, cbk_msg))) break; - if (cbk_msg->info.cbk_info.type == LGSV_WRITE_LOG_CALLBACK_IND) { + if (cbk_msg->info.cbk_info.type == LGSV_WRITE_LOG_CALLBACK_IND || + cbk_msg->info.cbk_info.type == LGSV_SEVERITY_FILTER_CALLBACK) { TRACE_2("LGSV_LGS_DELIVER_EVENT"); lga_hdl_cbk_rec_prc(cb, cbk_msg, &hdl_rec->reg_cbk); } else { @@ -268,7 +283,8 @@ static uint32_t lga_hdl_cbk_dispatch_blo if (NULL != (cbk_msg = (lgsv_msg_t *) m_NCS_IPC_RECEIVE(&hdl_rec->mbx, cbk_msg))) { - if (cbk_msg->info.cbk_info.type == LGSV_WRITE_LOG_CALLBACK_IND) { + if (cbk_msg->info.cbk_info.type == LGSV_WRITE_LOG_CALLBACK_IND || + cbk_msg->info.cbk_info.type == LGSV_SEVERITY_FILTER_CALLBACK) { TRACE_2("LGSV_LGS_DELIVER_EVENT"); lga_hdl_cbk_rec_prc(cb, cbk_msg, &hdl_rec->reg_cbk); } else { @@ -461,6 +477,44 @@ lga_client_hdl_rec_t *lga_find_hdl_rec_b } /**************************************************************************** + Name : lga_find_stream_hdl_rec_by_regid + + Description : This routine looks up a lga_log_stream_hdl_rec by client_id + and stream_id + + Arguments : cb + client_id + stream_id + + Return Values : LGA_LOG_STREAM_HDL_REC * or NULL + + Notes : The lga_cb in-parameter is most likely pointing to the global + lga_cb structure and that is not thread safe. If that is the + case the lga_cb data must be protected by a mutex before + calling this function. + +******************************************************************************/ +lga_log_stream_hdl_rec_t *lga_find_stream_hdl_rec_by_regid(lga_cb_t *lga_cb, + uint32_t client_id, uint32_t stream_id) +{ + TRACE_ENTER(); + lga_client_hdl_rec_t *lga_hdl_rec = lga_find_hdl_rec_by_regid(lga_cb, client_id); + + if (lga_hdl_rec != NULL) { + lga_log_stream_hdl_rec_t *lga_str_hdl_rec = lga_hdl_rec->stream_list; + + while (lga_str_hdl_rec != NULL) { + if (lga_str_hdl_rec->lgs_log_stream_id == stream_id) + return lga_str_hdl_rec; + lga_str_hdl_rec = lga_str_hdl_rec->next; + } + } + + TRACE_LEAVE(); + return NULL; +} + +/**************************************************************************** Name : lga_hdl_list_del Description : This routine deletes all handles for this library. diff --git a/src/log/apitest/logtest.c b/src/log/apitest/logtest.c --- a/src/log/apitest/logtest.c +++ b/src/log/apitest/logtest.c @@ -93,7 +93,7 @@ SaLogRecordT genLogRecord = .logBuffer = &genLogBuffer }; -SaVersionT logVersion = {'A', 0x02, 0x02}; +SaVersionT logVersion = {'A', 0x02, 0x03}; SaVersionT immVersion = {'A', 2, 11}; SaAisErrorT rc; SaLogHandleT logHandle; diff --git a/src/log/apitest/logtestfr.c b/src/log/apitest/logtestfr.c --- a/src/log/apitest/logtestfr.c +++ b/src/log/apitest/logtestfr.c @@ -40,7 +40,7 @@ /******************************************************************************* * Global variables and defines */ -static SaVersionT logVersion = {'A', 0x02, 0x02}; +static SaVersionT logVersion = {'A', 0x02, 0x03}; static SaVersionT immVersion = {'A', 2, 11}; static SaLogHandleT logHandle; diff --git a/src/log/apitest/saflogtest.c b/src/log/apitest/saflogtest.c --- a/src/log/apitest/saflogtest.c +++ b/src/log/apitest/saflogtest.c @@ -86,7 +86,7 @@ static inline void time_meas_log(time_me static void logWriteLogCallbackT(SaInvocationT invocation, SaAisErrorT error); static SaLogCallbacksT logCallbacks = { 0, 0, logWriteLogCallbackT }; -static SaVersionT logVersion = { 'A', 0x02, 0x02 }; +static SaVersionT logVersion = { 'A', 0x02, 0x03 }; static char *progname = "saflogtest"; static SaInvocationT cb_invocation; diff --git a/src/log/apitest/tet_LogOiOps.c b/src/log/apitest/tet_LogOiOps.c --- a/src/log/apitest/tet_LogOiOps.c +++ b/src/log/apitest/tet_LogOiOps.c @@ -1383,6 +1383,76 @@ done: logFinalize(); } +void verFilterOut(void) +{ + int ret; + SaAisErrorT rc; + char command[MAX_DATA]; + const unsigned int serverity_filter = 31; + FILE *fp = NULL; + char fileSize_c[10]; + int fileSize = 0; + + rc = logInitialize(); + if (rc != SA_AIS_OK) { + test_validate(rc, SA_AIS_OK); + return; + } + + rc = logAppStreamOpen(&app1StreamName, &appStreamLogFileCreateAttributes); + if (rc != SA_AIS_OK) { + test_validate(rc, SA_AIS_OK); + goto done; + } + + /* Set severity filter to enable log records have sev: emerg, alert, crit, error, warn */ + sprintf(command, "immadm -o 1 -p saLogStreamSeverityFilter:SA_UINT32_T:%d %s", + serverity_filter, SA_LOG_STREAM_APPLICATION1); + ret = systemCall(command); + if (ret != 0) { + test_validate(ret, 0); + goto done; + } + + /* saflogtest sends messages */ + sprintf(command, "saflogtest -a saLogApplication1 --count=2 --interval=20 --severity=notice" + " \"Test filter out, log records are not writen to log file\""); + rc = system(command); + if (rc == -1) { + test_validate(rc, 0); + goto done; + } + + /* Check if log file is empty or not*/ + sprintf(command, "find %s/saflogtest -type f -mmin -1 " + "| egrep \"%s_([0-9]{8}_[0-9]{6}\\.log$)\" " + "| xargs wc -c | awk '{printf $1}'", + log_root_path, DEFAULT_APP_FILE_NAME); + + fp = popen(command, "r"); + + if (fp == NULL) { + /* Fail to read size of log file. Report test failed. */ + fprintf(stderr, "Failed to run command = %s\n", command); + test_validate(1, 0); + goto done; + } + /* Get file size in chars */ + while (fgets(fileSize_c, sizeof(fileSize_c) - 1, fp) != NULL) {}; + pclose(fp); + + /* Convert chars to number */ + fileSize = atoi(fileSize_c); + + if (fileSize != 0) { + fprintf(stderr, "Log file has log records\n"); + } + rc_validate(fileSize, 0); + +done: + logFinalize(); +} + /* ============================================================================= * Test log service configuration object, suite 5 * ============================================================================= @@ -4298,6 +4368,7 @@ done: test_case_add(4, verNetworkName_01, "CCB Object Modify, saLogStreamLogFileFormat, network name token (@Cp)"); test_case_add(4, verDefaultLogFileFmt, "Application stream with default log file format"); test_case_add(4, verLogFileName, "CCB Object Modify, saLogStreamFileName with special character. ER"); + test_case_add(4, verFilterOut, "CCB Object Modify, saLogStreamSeverityFilter, filtering out log record that aren't written to log file"); /* Configuration object */ test_suite_add(5, "LOG OI tests, Service configuration object"); diff --git a/src/log/apitest/tet_log_longDN.c b/src/log/apitest/tet_log_longDN.c --- a/src/log/apitest/tet_log_longDN.c +++ b/src/log/apitest/tet_log_longDN.c @@ -87,7 +87,7 @@ static SaNameT notifyingObjLd; static SaNameT logStreamNameLd; static SaLogBufferT logBufferLd; static SaNtfClassIdT notificationClassIdLd = { 1, 2, 3 }; -static SaVersionT logVersionLd = { 'A', 2, 2 }; +static SaVersionT logVersionLd = { 'A', 2, 3 }; static SaInvocationT invocationLd; static SaAisErrorT errorLd; diff --git a/src/log/apitest/tet_saLogFilterSetCallbackT.c b/src/log/apitest/tet_saLogFilterSetCallbackT.c --- a/src/log/apitest/tet_saLogFilterSetCallbackT.c +++ b/src/log/apitest/tet_saLogFilterSetCallbackT.c @@ -15,10 +15,372 @@ * */ +#include <poll.h> #include "logtest.h" +#define MAX_DATA 256 +#define MAX_CLIENTS 2 +static SaLogSeverityFlagsT log_severity[8]; +static SaLogStreamHandleT log_streamHandle[8]; +static int cb_index; + +static void logFilterSetCallbackT(SaLogStreamHandleT logStreamHandle, SaLogSeverityFlagsT logSeverity) +{ + log_streamHandle[cb_index] = logStreamHandle; + log_severity[cb_index] = logSeverity; + cb_index++; +} + +static SaLogFileCreateAttributesT_2 appStreamLogFileCreateAttributes = +{ + .logFilePathName = DEFAULT_APP_FILE_PATH_NAME, + .logFileName = DEFAULT_APP_FILE_NAME, + .maxLogFileSize = DEFAULT_APP_LOG_FILE_SIZE, + .maxLogRecordSize = DEFAULT_APP_LOG_REC_SIZE, + .haProperty = SA_TRUE, + .logFileFullAction = SA_LOG_FILE_FULL_ACTION_ROTATE, + .maxFilesRotated = DEFAULT_MAX_FILE_ROTATED, + .logFileFmt = DEFAULT_FORMAT_EXPRESSION +}; + void saLogFilterSetCallbackT_01(void) { - test_validate(SA_AIS_ERR_NOT_SUPPORTED, SA_AIS_ERR_NOT_SUPPORTED); + int ret; + SaAisErrorT rc; + struct pollfd fds[1]; + char command[MAX_DATA]; + const unsigned int serverity_filter = 7; + SaUint32T v_saLogStreamSeverityFilter = 127; + + logCallbacks.saLogFilterSetCallback = logFilterSetCallbackT; + rc = logInitialize(); + if (rc != SA_AIS_OK) { + test_validate(rc, SA_AIS_OK); + return; + } + rc = saLogSelectionObjectGet(logHandle, &selectionObject); + if (rc != SA_AIS_OK) { + test_validate(rc, SA_AIS_OK); + goto done; + } + rc = logStreamOpen(&systemStreamName); + if (rc != SA_AIS_OK) { + test_validate(rc, SA_AIS_OK); + goto done; + } + + cb_index = 0; + /* Backup saLogStreamSeverityFilter value */ + get_attr_value(&systemStreamName, "saLogStreamSeverityFilter", + &v_saLogStreamSeverityFilter); + + sprintf(command, "immcfg %s -a saLogStreamSeverityFilter=%d 2> /dev/null", + SA_LOG_STREAM_SYSTEM, serverity_filter); + ret = systemCall(command); + if (ret != 0) { + test_validate(ret, 0); + goto done; + } + + fds[0].fd = (int) selectionObject; + fds[0].events = POLLIN; + ret = poll(fds, 1, 1000); + if (ret != 1) { + fprintf(stderr, " poll log callback failed: %d \n", ret); + test_validate(ret, 1); + goto done; + } + + rc = saLogDispatch(logHandle, SA_DISPATCH_ONE); + if (rc != SA_AIS_OK) { + fprintf(stderr, " saLogDispatch failed: %d \n", (int)rc); + test_validate(rc, SA_AIS_OK); + goto done; + } + + if (log_streamHandle[0] == logStreamHandle && log_severity[0] == serverity_filter) { + test_validate(SA_AIS_OK, SA_AIS_OK); + } else { + test_validate(0, SA_AIS_OK); + } + +done: + logCallbacks.saLogFilterSetCallback = NULL; + logFinalize(); + /* Restore saLogStreamSeverityFilter attribute */ + sprintf(command, "immcfg %s -a saLogStreamSeverityFilter=%d 2> /dev/null", + SA_LOG_STREAM_SYSTEM, v_saLogStreamSeverityFilter); + systemCall(command); } +void saLogFilterSetCallbackT_02(void) +{ + int ret; + SaAisErrorT rc; + struct pollfd fds[1]; + char command[MAX_DATA]; + const unsigned int serverity_filter = 7; + + logCallbacks.saLogFilterSetCallback = logFilterSetCallbackT; + rc = logInitialize(); + if (rc != SA_AIS_OK) { + test_validate(rc, SA_AIS_OK); + return; + } + rc = saLogSelectionObjectGet(logHandle, &selectionObject); + if (rc != SA_AIS_OK) { + test_validate(rc, SA_AIS_OK); + goto done; + } + + rc = logAppStreamOpen(&app1StreamName, &appStreamLogFileCreateAttributes); + if (rc != SA_AIS_OK) { + test_validate(rc, SA_AIS_OK); + goto done; + } + + cb_index = 0; + sprintf(command, "immadm -o 1 -p saLogStreamSeverityFilter:SA_UINT32_T:%d %s 2> /dev/null", + serverity_filter, SA_LOG_STREAM_APPLICATION1); + ret = systemCall(command); + if (ret != 0) { + test_validate(ret, 0); + goto done; + } + + fds[0].fd = (int) selectionObject; + fds[0].events = POLLIN; + ret = poll(fds, 1, 1000); + if (ret != 1) { + fprintf(stderr, " poll log callback failed: %d \n", ret); + test_validate(ret, 1); + goto done; + } + + rc = saLogDispatch(logHandle, SA_DISPATCH_ONE); + if (rc != SA_AIS_OK) { + fprintf(stderr, " saLogDispatch failed: %d \n", (int)rc); + test_validate(rc, SA_AIS_OK); + goto done; + } + + if (log_streamHandle[0] == logStreamHandle && log_severity[0] == serverity_filter) { + test_validate(SA_AIS_OK, SA_AIS_OK); + } else { + test_validate(0, SA_AIS_OK); + } + +done: + logCallbacks.saLogFilterSetCallback = NULL; + logFinalize(); +} + +void saLogFilterSetCallbackT_03(void) +{ + int ret; + SaAisErrorT rc; + struct pollfd fds[1]; + char command[MAX_DATA]; + const unsigned int serverity_filter[2] = {7, 15}; + SaUint32T v_saLogStreamSeverityFilter = 127; + SaLogStreamHandleT logStreamHandle[2]; + + logCallbacks.saLogFilterSetCallback = logFilterSetCallbackT; + rc = saLogInitialize(&logHandle, &logCallbacks, &logVersion); + if (rc != SA_AIS_OK) { + test_validate(rc, SA_AIS_OK); + return; + } + rc = saLogSelectionObjectGet(logHandle, &selectionObject); + if (rc != SA_AIS_OK) { + test_validate(rc, SA_AIS_OK); + goto done; + } + + rc = saLogStreamOpen_2(logHandle, &systemStreamName, NULL, 0, + SA_TIME_ONE_SECOND, &logStreamHandle[0]); + if (rc != SA_AIS_OK) { + fprintf(stderr, " saLogStreamOpen_2 for system stream failed: %d \n", (int)rc); + test_validate(rc, SA_AIS_OK); + goto done; + } + + rc = saLogStreamOpen_2(logHandle, &app1StreamName, &appStreamLogFileCreateAttributes, + SA_LOG_STREAM_CREATE, SA_TIME_ONE_SECOND, &logStreamHandle[1]); + if (rc != SA_AIS_OK) { + fprintf(stderr, " saLogStreamOpen_2 app stream failed: %d \n", (int)rc); + test_validate(rc, SA_AIS_OK); + goto done; + } + + cb_index = 0; + /* Backup saLogStreamSeverityFilter value */ + get_attr_value(&systemStreamName, "saLogStreamSeverityFilter", + &v_saLogStreamSeverityFilter); + /* Changing severity filter for system and app1 stream */ + sprintf(command, "immcfg %s -a saLogStreamSeverityFilter=%d 2> /dev/null", + SA_LOG_STREAM_SYSTEM, serverity_filter[0]); + ret = systemCall(command); + if (ret != 0) { + test_validate(ret, 0); + goto done; + } + sleep(1); + sprintf(command, "immadm -o 1 -p saLogStreamSeverityFilter:SA_UINT32_T:%d %s 2> /dev/null", + serverity_filter[1], SA_LOG_STREAM_APPLICATION1); + ret = systemCall(command); + if (ret != 0) { + test_validate(ret, 0); + goto done; + } + + fds[0].fd = (int) selectionObject; + fds[0].events = POLLIN; + ret = poll(fds, 1, 1000); + if (ret != 1) { + fprintf(stderr, " poll log callback failed: %d \n", ret); + test_validate(ret, 1); + goto done; + } + + rc = saLogDispatch(logHandle, SA_DISPATCH_ALL); + if (rc != SA_AIS_OK) { + fprintf(stderr, " saLogDispatch failed: %d \n", (int)rc); + test_validate(rc, SA_AIS_OK); + goto done; + } + + if (cb_index != 2) { + printf("cb_index = %u\n", cb_index); + test_validate(SA_AIS_ERR_LIBRARY, SA_AIS_OK); + goto done; + } + + for (int i = 0; i < 2; i++) { + if ((log_streamHandle[i] != logStreamHandle[i]) || (log_severity[i] != serverity_filter[i])) { + printf("log streamHandle: %llu, expected %llu \n", log_streamHandle[i], logStreamHandle[i]); + printf("log severity filter: %d, expected %d \n", log_severity[i], serverity_filter[i]); + test_validate(0, SA_AIS_OK); + goto done; + } + } + + test_validate(SA_AIS_OK, SA_AIS_OK); + +done: + logCallbacks.saLogFilterSetCallback = NULL; + logFinalize(); + /* Restore saLogStreamSeverityFilter attribute */ + sprintf(command, "immcfg %s -a saLogStreamSeverityFilter=%d 2> /dev/null", + SA_LOG_STREAM_SYSTEM, v_saLogStreamSeverityFilter); + systemCall(command); +} + + +void saLogFilterSetCallbackT_04(void) +{ + int ret; + SaAisErrorT rc; + struct pollfd fds[MAX_CLIENTS]; + char command[MAX_DATA]; + const unsigned int serverity_filter[MAX_CLIENTS] = {7, 15}; + SaUint32T v_saLogStreamSeverityFilter = 127; + SaLogStreamHandleT logStreamHandle[MAX_CLIENTS]; + SaLogHandleT logHandle[MAX_CLIENTS]; + SaSelectionObjectT selectionObject[MAX_CLIENTS]; + + logCallbacks.saLogFilterSetCallback = logFilterSetCallbackT; + for (int i = 0; i < MAX_CLIENTS; i++) { + rc = saLogInitialize(&logHandle[i], &logCallbacks, &logVersion); + if (rc != SA_AIS_OK) { + test_validate(rc, SA_AIS_OK); + return; + } + + rc = saLogSelectionObjectGet(logHandle[i], &selectionObject[i]); + if (rc != SA_AIS_OK) { + test_validate(rc, SA_AIS_OK); + goto done; + } + + fds[i].fd = (int) selectionObject[i]; + fds[i].events = POLLIN; + + rc = saLogStreamOpen_2(logHandle[i], &systemStreamName, NULL, 0, + SA_TIME_ONE_SECOND, &logStreamHandle[i]); + if (rc != SA_AIS_OK) { + test_validate(rc, SA_AIS_OK); + goto done; + } + } + + /* Close stream handle 1 */ + saLogStreamClose(logStreamHandle[1]); + + cb_index = 0; + /* Backup saLogStreamSeverityFilter value */ + get_attr_value(&systemStreamName, "saLogStreamSeverityFilter", + &v_saLogStreamSeverityFilter); + /* Changing severity filter for system and app1 stream */ + sprintf(command, "immcfg %s -a saLogStreamSeverityFilter=%d 2> /dev/null", + SA_LOG_STREAM_SYSTEM, serverity_filter[0]); + ret = systemCall(command); + if (ret != 0) { + test_validate(ret, 0); + goto done; + } + + ret = poll(fds, 2, 1000); + if (ret <= 0) { + fprintf(stderr, " poll log callback failed: %d \n", ret); + test_validate(ret, 1); + goto done; + } + + if (fds[1].revents & POLLIN) { + fprintf(stderr, " ERROR, get callback while handle closed stream\n"); + test_validate(0, SA_AIS_OK); + } + + if (fds[0].revents & POLLIN) { + rc = saLogDispatch(logHandle[0], SA_DISPATCH_ALL); + if (rc != SA_AIS_OK) { + fprintf(stderr, " saLogDispatch failed: %d \n", (int)rc); + test_validate(rc, SA_AIS_OK); + goto done; + } + + if (cb_index != 1) { + fprintf(stderr, "cb_index = %u\n", cb_index); + test_validate(SA_AIS_ERR_LIBRARY, SA_AIS_OK); + goto done; + } + + if (log_streamHandle[0] == logStreamHandle[0] && log_severity[0] == serverity_filter[0]) { + test_validate(SA_AIS_OK, SA_AIS_OK); + } else { + test_validate(0, SA_AIS_OK); + } + } else { + fprintf(stderr, " ERROR, Can not receive any callback\n"); + test_validate(0, SA_AIS_OK); + } + +done: + logCallbacks.saLogFilterSetCallback = NULL; + logFinalize(); + /* Restore saLogStreamSeverityFilter attribute */ + sprintf(command, "immcfg %s -a saLogStreamSeverityFilter=%d 2> /dev/null", + SA_LOG_STREAM_SYSTEM, v_saLogStreamSeverityFilter); + systemCall(command); +} + + +__attribute__ ((constructor)) static void saLibraryLifeCycle_constructor(void) +{ + test_suite_add(17, "Log Severity filter Callback"); + test_case_add(17, saLogFilterSetCallbackT_01, "saLogFilterSetCallbackT, severity filter is changed for cfg stream"); + test_case_add(17, saLogFilterSetCallbackT_02, "saLogFilterSetCallbackT, severity filter is changed for runtime stream"); + test_case_add(17, saLogFilterSetCallbackT_03, "saLogFilterSetCallbackT, severity filter is changed for runtime & cfg streams"); + test_case_add(17, saLogFilterSetCallbackT_04, "saLogFilterSetCallbackT, after closing stream"); +} diff --git a/src/log/apitest/tet_saLogStreamOpen_2.c b/src/log/apitest/tet_saLogStreamOpen_2.c --- a/src/log/apitest/tet_saLogStreamOpen_2.c +++ b/src/log/apitest/tet_saLogStreamOpen_2.c @@ -1052,7 +1052,6 @@ extern void saLogWriteLogAsync_19(void); extern void saLogWriteLogCallbackT_01(void); extern void saLogWriteLogCallbackT_02(void); extern void saLogWriteLogCallbackT_03(void); -extern void saLogFilterSetCallbackT_01(void); extern void saLogStreamClose_01(void); __attribute__ ((constructor)) static void saLibraryLifeCycle_constructor(void) @@ -1105,7 +1104,6 @@ extern void saLogStreamClose_01(void); test_case_add(2, saLogWriteLogAsync_19, "saLogWriteLogAsync() logBufSize > SA_LOG_MAX_RECORD_SIZE"); test_case_add(2, saLogWriteLogCallbackT_01, "saLogWriteLogCallbackT() SA_DISPATCH_ONE"); test_case_add(2, saLogWriteLogCallbackT_02, "saLogWriteLogCallbackT() SA_DISPATCH_ALL"); - test_case_add(2, saLogFilterSetCallbackT_01, "saLogFilterSetCallbackT OK"); test_case_add(2, saLogStreamClose_01, "saLogStreamClose OK"); test_case_add(2, saLogStreamOpen_2_46, "saLogStreamOpen_2 with maxFilesRotated = 0, ERR"); test_case_add(2, saLogStreamOpen_2_47, "saLogStreamOpen_2 with maxFilesRotated = 128, ERR"); diff --git a/src/log/common/lgsv_defs.h b/src/log/common/lgsv_defs.h --- a/src/log/common/lgsv_defs.h +++ b/src/log/common/lgsv_defs.h @@ -20,7 +20,7 @@ #define LOG_RELEASE_CODE 'A' #define LOG_MAJOR_VERSION 2 -#define LOG_MINOR_VERSION 2 +#define LOG_MINOR_VERSION 3 #define LOG_RELEASE_CODE_0 'A' #define LOG_MAJOR_VERSION_0 2 diff --git a/src/log/common/lgsv_msg.h b/src/log/common/lgsv_msg.h --- a/src/log/common/lgsv_msg.h +++ b/src/log/common/lgsv_msg.h @@ -46,6 +46,7 @@ typedef enum { typedef enum { LGSV_WRITE_LOG_CALLBACK_IND = 0, LGSV_CLM_NODE_STATUS_CALLBACK = 1, + LGSV_SEVERITY_FILTER_CALLBACK = 2, LGSV_LGS_CBK_MAX } lgsv_cbk_msg_type_t; @@ -127,12 +128,18 @@ typedef struct logsv_loga_clm_status_par uint32_t clm_node_status; } logsv_lga_clm_status_cbk_t; +typedef struct { +SaLogSeverityFlagsT log_severity; +} lgsv_severity_filter_callback_t; + /* wrapper structure for all the callbacks */ typedef struct { lgsv_cbk_msg_type_t type; /* callback type */ uint32_t lgs_client_id; /* lgs client_id */ + uint32_t lgs_stream_id; SaInvocationT inv; /* invocation value */ /* union {*/ + lgsv_severity_filter_callback_t serverity_filter_cbk; lgsv_write_log_callback_ind_t write_cbk; logsv_lga_clm_status_cbk_t clm_node_status_cbk; /* } param; */ diff --git a/src/log/logd/lgs_imm.cc b/src/log/logd/lgs_imm.cc --- a/src/log/logd/lgs_imm.cc +++ b/src/log/logd/lgs_imm.cc @@ -472,6 +472,8 @@ static void adminOperationCallback(SaImm osaf_abort(0); } + /* Send changed severity filter to clients */ + lgs_send_severity_filter_to_clients(stream->streamId, severityFilter); /* Checkpoint to standby LOG server */ ckpt_stream_config(stream); @@ -2307,6 +2309,11 @@ static void stream_ccb_apply_modify(cons } else if (!strcmp(attribute->attrName, "saLogStreamSeverityFilter")) { SaUint32T severityFilter = *((SaUint32T *)value); stream->severityFilter = severityFilter; + + /* Send changed severity filter to clients */ + if (stream->streamType != STREAM_TYPE_ALARM && + stream->streamType != STREAM_TYPE_NOTIFICATION) + lgs_send_severity_filter_to_clients(stream->streamId, severityFilter); } else { LOG_ER("Error: Unknown attribute name"); osafassert(0); diff --git a/src/log/logd/lgs_mds.cc b/src/log/logd/lgs_mds.cc --- a/src/log/logd/lgs_mds.cc +++ b/src/log/logd/lgs_mds.cc @@ -807,6 +807,7 @@ static uint32_t mds_enc(struct ncsmds_ca rc = enc_lstr_close_rsp_msg(uba, msg); break; default: + rc = NCSCC_RC_FAILURE; TRACE("Unknown API RSP type = %d", msg->info.api_resp_info.type); break; } @@ -824,26 +825,44 @@ static uint32_t mds_enc(struct ncsmds_ca ncs_encode_32bit(&p8, msg->info.cbk_info.lgs_client_id); ncs_encode_64bit(&p8, msg->info.cbk_info.inv); ncs_enc_claim_space(uba, 16); - if (msg->info.cbk_info.type == LGSV_WRITE_LOG_CALLBACK_IND) { - 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.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); + + switch (msg->info.cbk_info.type) { + case LGSV_WRITE_LOG_CALLBACK_IND: + 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.write_cbk.error); + TRACE_8("LGSV_WRITE_LOG_CALLBACK_IND"); + break; + case 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"); + break; + case LGSV_SEVERITY_FILTER_CALLBACK: + p8 = ncs_enc_reserve_space(uba, 6); + if (!p8) { + TRACE("ncs_enc_reserve_space failed"); + goto err; + } + ncs_encode_32bit(&p8, msg->info.cbk_info.lgs_stream_id); + ncs_encode_16bit(&p8, msg->info.cbk_info.serverity_filter_cbk.log_severity); + TRACE_8("LGSV_SEVERITY_FILTER_CALLBACK"); + break; + default: + rc = NCSCC_RC_FAILURE; + TRACE("unknown callback type %d", msg->info.cbk_info.type); + break; + } + if (rc == NCSCC_RC_FAILURE) goto err; - } + } else { TRACE("unknown msg type %d", msg->type); goto err; diff --git a/src/log/logd/lgs_util.cc b/src/log/logd/lgs_util.cc --- a/src/log/logd/lgs_util.cc +++ b/src/log/logd/lgs_util.cc @@ -834,3 +834,83 @@ bool lgs_is_extended_name_valid(const Sa return true; } + + +/** + * Send a severity callback callback message to a client + * + * @param client_id + * @param stream_id + * @param severityFilter + * @param mds_dest + */ +static void lgs_send_filter_msg(uint32_t client_id, uint32_t stream_id, + SaLogSeverityFlagsT severity_filter, MDS_DEST mds_dest) { + uint32_t rc; + NCSMDS_INFO mds_info = {0}; + lgsv_msg_t msg; + + TRACE_ENTER(); + TRACE_3("client_id: %u, stream_id: %u, modified severity filter: %u", + client_id, stream_id, severity_filter); + + msg.type = LGSV_LGS_CBK_MSG; + msg.info.cbk_info.type = LGSV_SEVERITY_FILTER_CALLBACK; + msg.info.cbk_info.lgs_client_id = client_id; + msg.info.cbk_info.lgs_stream_id = stream_id; + msg.info.cbk_info.inv = 0; + msg.info.cbk_info.serverity_filter_cbk.log_severity = severity_filter; + + 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 = mds_dest; + + rc = ncsmds_api(&mds_info); + if (rc != NCSCC_RC_SUCCESS) + LOG_NO("Failed (%u) to send of severity filter callback to: %" PRIx64, rc, mds_dest); + + TRACE_LEAVE(); +} + +/** + * Send a changed severity filter to a client + * + * @param stream_id + * @param severityFilter + */ +void lgs_send_severity_filter_to_clients(uint32_t stream_id, + SaLogSeverityFlagsT severity_filter) { + log_client_t *rp = NULL; + uint32_t client_id_net; + lgs_stream_list_t *stream; + + TRACE_ENTER(); + TRACE_3("stream_id: %u, severity filter:%u", stream_id, severity_filter); + + rp = reinterpret_cast<log_client_t *> + (ncs_patricia_tree_getnext(&lgs_cb->client_tree, NULL)); + + while (rp != NULL) { + /* Store the client_id_net for getting next */ + client_id_net = rp->client_id_net; + /* Do not send to all client. Send to clients that need filter + callback and associate with this stream */ + stream = rp->stream_list_root; + while (stream != NULL) { + if (stream->stream_id == stream_id) { + lgs_send_filter_msg(rp->client_id, stream_id, severity_filter, rp->mds_dest); + break; + } + stream = stream->next; + } + rp = reinterpret_cast<log_client_t *>(ncs_patricia_tree_getnext( + &lgs_cb->client_tree, reinterpret_cast<uint8_t *>(&client_id_net))); + } + + TRACE_LEAVE(); +} diff --git a/src/log/logd/lgs_util.h b/src/log/logd/lgs_util.h --- a/src/log/logd/lgs_util.h +++ b/src/log/logd/lgs_util.h @@ -82,5 +82,7 @@ int lgs_init_timer(time_t timeout_s); void lgs_close_timer(int ufd); bool lgs_is_extended_name_valid(const SaNameT* name); +void lgs_send_severity_filter_to_clients(uint32_t stream_id, + SaLogSeverityFlagsT serverity); #endif // LOG_LOGD_LGS_UTIL_H_ diff --git a/src/log/tools/saf_logger.c b/src/log/tools/saf_logger.c --- a/src/log/tools/saf_logger.c +++ b/src/log/tools/saf_logger.c @@ -58,7 +58,7 @@ static void logWriteLogCallbackT(SaInvocationT invocation, SaAisErrorT error); static SaLogCallbacksT logCallbacks = { 0, 0, logWriteLogCallbackT }; -static SaVersionT logVersion = { 'A', 2, 1 }; +static SaVersionT logVersion = { 'A', 2, 3 }; static char *progname = "saflogger"; static SaInvocationT cb_invocation; diff --git a/src/osaf/saflog/saflog.c b/src/osaf/saflog/saflog.c --- a/src/osaf/saflog/saflog.c +++ b/src/osaf/saflog/saflog.c @@ -31,7 +31,7 @@ void saflog_init(void) SaAisErrorT error; if (!initialized) { - SaVersionT logVersion = { 'A', 2, 1 }; + SaVersionT logVersion = { 'A', 2, 3 }; SaNameT stream_name; saAisNameLend(SA_LOG_STREAM_SYSTEM, &stream_name); @@ -65,7 +65,7 @@ void saflog(int priority, const SaNameT va_end(ap); if (!initialized) { - SaVersionT logVersion = { 'A', 2, 1 }; + SaVersionT logVersion = { 'A', 2, 3 }; SaNameT stream_name; saAisNameLend(SA_LOG_STREAM_SYSTEM, &stream_name); ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel