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

Reply via email to