Streaming log record is packaged in RFC5424 format and they all carry a fixed
facility ID (16). Therefore, log record receiver i.e. rsyslogd is not able to
filter log records on their facility id such as which ones are regular logs
or which ones are security.

The ticket to have the facility ID configurable so that the receiver can
differentiate among types of log records based on that number.
Configure facility id via a new attribute `saLogStreamFacilityId` in class
`SaLogStreamConfig`. The valid range is [0-23]. The default value is 16 to keep
the streaming feature backward compatible. Always keep the value of attribute
`saLogStreamFacilityId` in sync with the standby. If user deletes value of the
attribute `saLogStreamFacilityId`, it will go back to the default value (16).
---
 src/log/Makefile.am               |   2 +
 src/log/config/logsv_classes.xml  |  14 ++
 src/log/logd/lgs_cache.cc         |   1 +
 src/log/logd/lgs_dest.cc          |   1 +
 src/log/logd/lgs_dest.h           |   6 +-
 src/log/logd/lgs_imm.cc           |  74 ++++++++-
 src/log/logd/lgs_mbcsv.cc         | 187 +++++++++++++++++++++--
 src/log/logd/lgs_mbcsv.h          |   5 +-
 src/log/logd/lgs_mbcsv_v9.cc      | 243 ++++++++++++++++++++++++++++++
 src/log/logd/lgs_mbcsv_v9.h       |  67 ++++++++
 src/log/logd/lgs_recov.cc         |  10 ++
 src/log/logd/lgs_stream.cc        |   9 ++
 src/log/logd/lgs_stream.h         |   1 +
 src/log/logd/lgs_unixsock_dest.cc |   7 +-
 14 files changed, 610 insertions(+), 17 deletions(-)
 create mode 100644 src/log/logd/lgs_mbcsv_v9.cc
 create mode 100644 src/log/logd/lgs_mbcsv_v9.h

diff --git a/src/log/Makefile.am b/src/log/Makefile.am
index 767e25369..a2a98baec 100644
--- a/src/log/Makefile.am
+++ b/src/log/Makefile.am
@@ -87,6 +87,7 @@ noinst_HEADERS += \
        src/log/logd/lgs_mbcsv_v3.h \
        src/log/logd/lgs_mbcsv_v5.h \
        src/log/logd/lgs_mbcsv_v6.h \
+       src/log/logd/lgs_mbcsv_v9.h \
        src/log/logd/lgs_oi_admin.h \
        src/log/logd/lgs_recov.h \
        src/log/logd/lgs_stream.h \
@@ -151,6 +152,7 @@ bin_osaflogd_SOURCES = \
        src/log/logd/lgs_mbcsv_v3.cc \
        src/log/logd/lgs_mbcsv_v5.cc \
        src/log/logd/lgs_mbcsv_v6.cc \
+       src/log/logd/lgs_mbcsv_v9.cc \
        src/log/logd/lgs_mds.cc \
        src/log/logd/lgs_oi_admin.cc \
        src/log/logd/lgs_recov.cc \
diff --git a/src/log/config/logsv_classes.xml b/src/log/config/logsv_classes.xml
index 084e8915d..8aa8e69c2 100644
--- a/src/log/config/logsv_classes.xml
+++ b/src/log/config/logsv_classes.xml
@@ -78,6 +78,12 @@
                        <type>SA_UINT64_T</type>
                        <category>SA_RUNTIME</category>
                </attr>
+               <attr>
+                       <name>saLogStreamFacilityId</name>
+                       <type>SA_UINT32_T</type>
+                       <category>SA_RUNTIME</category>
+                       <flag>SA_CACHED</flag>
+               </attr>
        </class>
        <class name="SaLogStreamConfig">
                <category>SA_CONFIG</category>
@@ -171,6 +177,14 @@
                        <type>SA_UINT64_T</type>
                        <category>SA_RUNTIME</category>
                </attr>
+               <attr>
+                       <name>saLogStreamFacilityId</name>
+                       <type>SA_UINT32_T</type>
+                       <category>SA_CONFIG</category>
+                       <flag>SA_WRITABLE</flag>
+                       <flag>SA_STRONG_DEFAULT</flag>
+                       <default-value>16</default-value>
+               </attr>
        </class>
        <class name="OpenSafLogConfig">
 <!-- Care is needed when changing to the default values for the attributes of 
this class
diff --git a/src/log/logd/lgs_cache.cc b/src/log/logd/lgs_cache.cc
index d94f4ea0d..81f64225d 100644
--- a/src/log/logd/lgs_cache.cc
+++ b/src/log/logd/lgs_cache.cc
@@ -161,6 +161,7 @@ void Cache::Data::Streaming() const {
   data.hostname    = param_->from_node;
   data.appname     = param_->svc_name;
   data.sev         = param_->severity;
+  data.facilityId  = stream->facilityId;
   time.tv_sec      = (param_->log_stamp / (SaTimeT)SA_TIME_ONE_SECOND);
   time.tv_nsec     = (param_->log_stamp % (SaTimeT)SA_TIME_ONE_SECOND);
   data.time        = time;
diff --git a/src/log/logd/lgs_dest.cc b/src/log/logd/lgs_dest.cc
index 0e70ddd12..71aecc92d 100644
--- a/src/log/logd/lgs_dest.cc
+++ b/src/log/logd/lgs_dest.cc
@@ -392,6 +392,7 @@ bool WriteToDestination(const RecordData& data, const 
VectorString& destnames) {
   info.stream_dn = data.name;
   info.app_name = data.appname;
   info.severity = data.sev;
+  info.facilityId = data.facilityId;
   info.time = data.time;
   info.origin = origin.c_str();
 
diff --git a/src/log/logd/lgs_dest.h b/src/log/logd/lgs_dest.h
index 6fe7c1782..c119de356 100644
--- a/src/log/logd/lgs_dest.h
+++ b/src/log/logd/lgs_dest.h
@@ -75,6 +75,7 @@ struct RecordData {
   bool isRtStream;
   uint32_t recordId;
   uint16_t sev;
+  uint32_t facilityId;
   timespec time;
 
   RecordData()
@@ -86,7 +87,8 @@ struct RecordData {
         msgid{nullptr},
         isRtStream{false},
         recordId{0},
-        sev{0} {
+        sev{0},
+        facilityId{16} {
     time = base::ReadRealtimeClock();
   }
 };
@@ -175,6 +177,7 @@ class DestinationHandler {
     const char* log_record;
     const char* app_name;
     uint16_t severity;
+    uint32_t facilityId;
     uint32_t record_id;
     struct timespec time;
 
@@ -186,6 +189,7 @@ class DestinationHandler {
           log_record{nullptr},
           app_name{nullptr},
           severity{0},
+          facilityId{16},
           record_id{0} {
       time = base::ReadRealtimeClock();
     }
diff --git a/src/log/logd/lgs_imm.cc b/src/log/logd/lgs_imm.cc
index 24318bf90..40551693d 100644
--- a/src/log/logd/lgs_imm.cc
+++ b/src/log/logd/lgs_imm.cc
@@ -56,6 +56,7 @@
 #include "log/logd/lgs_mbcsv_v3.h"
 #include "log/logd/lgs_mbcsv_v5.h"
 #include "log/logd/lgs_mbcsv_v6.h"
+#include "log/logd/lgs_mbcsv_v9.h"
 #include "base/saf_error.h"
 
 /* TYPE DEFINITIONS
@@ -245,12 +246,40 @@ static uint32_t ckpt_stream_config(log_stream_t *stream) {
   lgsv_ckpt_msg_v1_t ckpt_v1;
   lgsv_ckpt_msg_v2_t ckpt_v2;
   lgsv_ckpt_msg_v6_t ckpt_v3;
+  lgsv_ckpt_msg_v9_t ckpt_v4;
 
   void *ckpt_ptr;
 
   TRACE_ENTER();
 
-  if (lgs_is_peer_v6()) {
+  if (lgs_is_peer_v9()) {
+    memset(&ckpt_v4, 0, sizeof(ckpt_v4));
+    ckpt_v4.header.ckpt_rec_type = LGS_CKPT_CFG_STREAM;
+    ckpt_v4.header.num_ckpt_records = 1;
+    ckpt_v4.header.data_len = 1;
+
+    ckpt_v4.ckpt_rec.stream_cfg.name = const_cast<char 
*>(stream->name.c_str());
+    ckpt_v4.ckpt_rec.stream_cfg.fileName =
+        const_cast<char *>(stream->fileName.c_str());
+    ckpt_v4.ckpt_rec.stream_cfg.pathName =
+        const_cast<char *>(stream->pathName.c_str());
+    ckpt_v4.ckpt_rec.stream_cfg.maxLogFileSize = stream->maxLogFileSize;
+    ckpt_v4.ckpt_rec.stream_cfg.fixedLogRecordSize = 
stream->fixedLogRecordSize;
+    ckpt_v4.ckpt_rec.stream_cfg.logFullAction = stream->logFullAction;
+    ckpt_v4.ckpt_rec.stream_cfg.logFullHaltThreshold =
+        stream->logFullHaltThreshold;
+    ckpt_v4.ckpt_rec.stream_cfg.maxFilesRotated = stream->maxFilesRotated;
+    ckpt_v4.ckpt_rec.stream_cfg.logFileFormat = stream->logFileFormat;
+    ckpt_v4.ckpt_rec.stream_cfg.severityFilter = stream->severityFilter;
+    ckpt_v4.ckpt_rec.stream_cfg.logFileCurrent =
+        const_cast<char *>(stream->logFileCurrent.c_str());
+    ckpt_v4.ckpt_rec.stream_cfg.dest_names =
+        const_cast<char *>(stream->stb_dest_names.c_str());
+    ckpt_v4.ckpt_rec.stream_cfg.c_file_close_time_stamp =
+        stream->act_last_close_timestamp;
+    ckpt_v4.ckpt_rec.stream_cfg.facilityId = stream->facilityId;
+    ckpt_ptr = &ckpt_v4;
+  } else if (lgs_is_peer_v6()) {
     memset(&ckpt_v3, 0, sizeof(ckpt_v3));
     ckpt_v3.header.ckpt_rec_type = LGS_CKPT_CFG_STREAM;
     ckpt_v3.header.num_ckpt_records = 1;
@@ -1281,6 +1310,8 @@ static SaAisErrorT check_attr_validity(
   bool i_maxFilesRotated_mod = false;
   SaUint32T i_severityFilter = 0;
   bool i_severityFilter_mod = false;
+  SaUint32T i_facilityId = 0;
+  bool i_facilityId_mod = false;
 
   TRACE_ENTER();
 
@@ -1338,7 +1369,8 @@ static SaAisErrorT check_attr_validity(
     if (attribute->attrValuesNumber > 0) {
       value = attribute->attrValues[0];
     } else if (opdata->operationType == CCBUTIL_MODIFY) {
-      if (!strcmp(attribute->attrName, "saLogRecordDestination")) {
+      if (!strcmp(attribute->attrName, "saLogRecordDestination") ||
+          !strcmp(attribute->attrName, "saLogStreamFacilityId")) {
         // do nothing
       } else {
         /* An attribute without a value is never valid if modify */
@@ -1403,6 +1435,11 @@ static SaAisErrorT check_attr_validity(
       i_severityFilter_mod = true;
       TRACE("Saved attribute \"%s\" = %d", attribute->attrName,
             i_severityFilter);
+    } else if (!strcmp(attribute->attrName, "saLogStreamFacilityId") &&
+               attribute->attrValuesNumber > 0) {
+      i_facilityId = *(reinterpret_cast<SaUint32T *>(value));
+      i_facilityId_mod = true;
+      TRACE("Saved attribute \"%s\"", attribute->attrName);
     } else if (!strcmp(attribute->attrName, "saLogRecordDestination")) {
       std::vector<std::string> vstring{};
       for (unsigned i = 0; i < attribute->attrValuesNumber; i++) {
@@ -1641,6 +1678,20 @@ static SaAisErrorT check_attr_validity(
         goto done;
       }
     }
+
+    /* saLogStreamFacilityId
+     *     <= 23
+     */
+    if (i_facilityId_mod) {
+      TRACE("Checking saLogStreamFacilityId");
+      if (i_facilityId > 23) {
+        report_oi_error(immOiHandle, opdata->ccbId, "Invalid facility ID: %u",
+                        i_facilityId);
+        rc = SA_AIS_ERR_BAD_OPERATION;
+        TRACE("Invalid facility ID: %u", i_facilityId);
+        goto done;
+      }
+    }
   }
 
 done:
@@ -2268,6 +2319,10 @@ static SaAisErrorT stream_create_and_configure1(
                          "saLogStreamSeverityFilter")) {
         (*stream)->severityFilter = *((SaUint32T *)value);
         TRACE("severityFilter: %u", (*stream)->severityFilter);
+      } else if (!strcmp(ccb->param.create.attrValues[i]->attrName,
+                         "saLogStreamFacilityId")) {
+        (*stream)->facilityId = *(reinterpret_cast<SaUint32T *>(value));
+        TRACE("facilityId: %u", (*stream)->facilityId);
       } else if (!strcmp(ccb->param.create.attrValues[i]->attrName,
                          "saLogRecordDestination")) {
         std::vector<std::string> vstring{};
@@ -2403,6 +2458,12 @@ static void stream_ccb_apply_modify(const 
CcbUtilOperationData_t *opdata) {
         log_stream_delete_dest_name(stream, dname);
         attrMod = opdata->param.modify.attrMods[i++];
         continue;
+      } else if (!strcmp(attribute->attrName, "saLogStreamFacilityId")) {
+        LOG_NO("%s deleted", __func__);
+        stream->facilityId = 16;
+        new_cfg_file_needed = true;
+        attrMod = opdata->param.modify.attrMods[i++];
+        continue;
       }
     }
 
@@ -2464,6 +2525,11 @@ static void stream_ccb_apply_modify(const 
CcbUtilOperationData_t *opdata) {
         TRACE("%s: stream %s - msgid = %s", __func__, stream->name.c_str(),
               stream->rfc5424MsgId.c_str());
       }
+    } else if (!strcmp(attribute->attrName, "saLogStreamFacilityId")) {
+      if (value != nullptr) {
+        stream->facilityId = *(reinterpret_cast<SaUint32T *>(value));
+        new_cfg_file_needed = true;
+      }
     } else {
       LOG_ER("Error: Unknown attribute name");
       osafassert(0);
@@ -2795,6 +2861,9 @@ static SaAisErrorT stream_create_and_configure(
          */
         stream->creationTimeStamp = *(static_cast<SaTimeT *>(value));
       }
+    } else if (!strcmp(attribute->attrName, "saLogStreamFacilityId")) {
+      stream->facilityId = *(reinterpret_cast<SaUint32T *>(value));
+      TRACE("facilityId: %u", stream->facilityId);
     }
   }
 
@@ -3184,6 +3253,7 @@ int lgs_get_streamobj_attr(SaImmAttrValuesT_2 
***attrib_out,
       const_cast<char *>("saLogStreamLogFileFormat"),
       const_cast<char *>("saLogStreamSeverityFilter"),
       const_cast<char *>("saLogStreamCreationTimestamp"),
+      const_cast<char *>("saLogStreamFacilityId"),
       NULL};
 
   TRACE_ENTER2("object_name_in \"%s\"", object_name_in.c_str());
diff --git a/src/log/logd/lgs_mbcsv.cc b/src/log/logd/lgs_mbcsv.cc
index f83d9ec20..522d7fb6f 100644
--- a/src/log/logd/lgs_mbcsv.cc
+++ b/src/log/logd/lgs_mbcsv.cc
@@ -23,6 +23,7 @@
 
 #include "osaf/immutil/immutil.h"
 #include "log/logd/lgs_dest.h"
+#include "log/logd/lgs_mbcsv_v9.h"
 #include "log/logd/lgs_mbcsv_v6.h"
 #include "log/logd/lgs_mbcsv_v5.h"
 #include "log/logd/lgs_mbcsv_v3.h"
@@ -141,7 +142,96 @@ uint32_t edp_ed_open_stream_rec(EDU_HDL *edu_hdl, EDU_TKN 
*edu_tkn,
   uint32_t rc = NCSCC_RC_SUCCESS;
   lgs_ckpt_stream_open_t *ckpt_open_stream_msg_ptr = NULL,
                          **ckpt_open_stream_msg_dec_ptr;
-  if (lgs_is_peer_v6()) {
+  if (lgs_is_peer_v9()) {
+    EDU_INST_SET ckpt_open_stream_rec_ed_rules[] = {
+        {EDU_START, edp_ed_open_stream_rec, 0, 0, 0,
+         sizeof(lgs_ckpt_stream_open_t), 0, NULL},
+        {EDU_EXEC, ncs_edp_uns32, 0, 0, 0,
+         (int64_t) & (reinterpret_cast<lgs_ckpt_stream_open_t *>(0))->streamId,
+         0, NULL},
+        {EDU_EXEC, ncs_edp_uns32, 0, 0, 0,
+         (int64_t) & (reinterpret_cast<lgs_ckpt_stream_open_t *>(0))->clientId,
+         0, NULL},
+        {EDU_EXEC, ncs_edp_string, 0, 0, 0,
+         (int64_t) & (reinterpret_cast<lgs_ckpt_stream_open_t *>(0))->logFile,
+         0, NULL},
+        {EDU_EXEC, ncs_edp_string, 0, 0, 0,
+         (int64_t) & (reinterpret_cast<lgs_ckpt_stream_open_t *>(0))->logPath,
+         0, NULL},
+        {EDU_EXEC, ncs_edp_string, 0, 0, 0,
+         (int64_t) &
+             (reinterpret_cast<lgs_ckpt_stream_open_t *>(0))->logFileCurrent,
+         0, NULL},
+        {EDU_EXEC, ncs_edp_string, 0, 0, 0,
+         (int64_t) &
+             (reinterpret_cast<lgs_ckpt_stream_open_t *>(0))->dest_names,
+         0, NULL},
+        {EDU_EXEC, ncs_edp_uns64, 0, 0, 0,
+         (int64_t) &
+             (reinterpret_cast<lgs_ckpt_stream_open_t *>(0))->maxFileSize,
+         0, NULL},
+        {EDU_EXEC, ncs_edp_int32, 0, 0, 0,
+         (int64_t) &
+             (reinterpret_cast<lgs_ckpt_stream_open_t *>(0))->maxLogRecordSize,
+         0, NULL},
+        {EDU_EXEC, ncs_edp_int32, 0, 0, 0,
+         (int64_t) &
+             (reinterpret_cast<lgs_ckpt_stream_open_t 
*>(0))->logFileFullAction,
+         0, NULL},
+        {EDU_EXEC, ncs_edp_int32, 0, 0, 0,
+         (int64_t) &
+             (reinterpret_cast<lgs_ckpt_stream_open_t *>(0))->maxFilesRotated,
+         0, NULL},
+        {EDU_EXEC, ncs_edp_string, 0, 0, 0,
+         (int64_t) & (reinterpret_cast<lgs_ckpt_stream_open_t *>(0))->fileFmt,
+         0, NULL},
+        {EDU_EXEC, ncs_edp_string, 0, 0, 0,
+         (int64_t) &
+             (reinterpret_cast<lgs_ckpt_stream_open_t *>(0))->logStreamName,
+         0, NULL},
+        {EDU_EXEC, ncs_edp_uns64, 0, 0, 0,
+         (int64_t) &
+             (reinterpret_cast<lgs_ckpt_stream_open_t 
*>(0))->creationTimeStamp,
+         0, NULL},
+        {EDU_EXEC, ncs_edp_uns32, 0, 0, 0,
+         (int64_t) &
+             (reinterpret_cast<lgs_ckpt_stream_open_t *>(0))->numOpeners,
+         0, NULL},
+        {EDU_EXEC, ncs_edp_uns32, 0, 0, 0,
+         (int64_t) &
+             (reinterpret_cast<lgs_ckpt_stream_open_t *>(0))->streamType,
+         0, NULL},
+        {EDU_EXEC, ncs_edp_uns32, 0, 0, 0,
+         (int64_t) &
+             (reinterpret_cast<lgs_ckpt_stream_open_t *>(0))->logRecordId,
+         0, NULL},
+        {EDU_EXEC, ncs_edp_uns32, 0, 0, 0,
+         (int64_t) &
+             (reinterpret_cast<lgs_ckpt_stream_open_t *>(0))->facilityId,
+         0, NULL},
+        {EDU_END, 0, 0, 0, 0, 0, 0, NULL},
+    };
+
+    if (op == EDP_OP_TYPE_ENC) {
+      ckpt_open_stream_msg_ptr = static_cast<lgs_ckpt_stream_open_t *>(ptr);
+    } else if (op == EDP_OP_TYPE_DEC) {
+      ckpt_open_stream_msg_dec_ptr =
+          static_cast<lgs_ckpt_stream_open_t **>(ptr);
+      if (*ckpt_open_stream_msg_dec_ptr == NULL) {
+        *o_err = EDU_ERR_MEM_FAIL;
+        return NCSCC_RC_FAILURE;
+      }
+      memset(*ckpt_open_stream_msg_dec_ptr, '\0',
+             sizeof(lgs_ckpt_stream_open_t));
+      ckpt_open_stream_msg_ptr = *ckpt_open_stream_msg_dec_ptr;
+    } else {
+      ckpt_open_stream_msg_ptr = static_cast<lgs_ckpt_stream_open_t *>(ptr);
+    }
+
+    rc = m_NCS_EDU_RUN_RULES(edu_hdl, edu_tkn, ckpt_open_stream_rec_ed_rules,
+                             ckpt_open_stream_msg_ptr, ptr_data_len, buf_env,
+                             op, o_err);
+  } else if (lgs_is_peer_v6()) {
     EDU_INST_SET ckpt_open_stream_rec_ed_rules[] = {
         {EDU_START, edp_ed_open_stream_rec, 0, 0, 0,
          sizeof(lgs_ckpt_stream_open_t), 0, NULL},
@@ -491,6 +581,18 @@ bool lgs_is_peer_v8() {
   }
 }
 
+/**
+ * Check if peer is version 9 (or later)
+ * @return bool
+ */
+bool lgs_is_peer_v9() {
+  if (lgs_cb->mbcsv_peer_version >= LGS_MBCSV_VERSION_9) {
+    return true;
+  } else {
+    return false;
+  }
+}
+
 /**
  * Check if configured for split file system.
  * If other node is version 1 split file system mode is not applicable.
@@ -736,6 +838,7 @@ void lgs_ckpt_stream_open_set(log_stream_t *logStream,
   stream_open->maxFilesRotated = logStream->maxFilesRotated;
   stream_open->creationTimeStamp = logStream->creationTimeStamp;
   stream_open->numOpeners = logStream->numOpeners;
+  stream_open->facilityId = logStream->facilityId;
 
   if (lgs_is_peer_v7() == true) {
     stream_open->streamType = logStream->streamType;
@@ -908,6 +1011,7 @@ static uint32_t edu_enc_reg_list(lgs_cb_t *cb, NCS_UBAID 
*uba) {
 
 static uint32_t ckpt_encode_async_update(lgs_cb_t *lgs_cb, EDU_HDL edu_hdl,
                                          NCS_MBCSV_CB_ARG *cbk_arg) {
+  lgsv_ckpt_msg_v9_t *data_v9 = NULL;
   lgsv_ckpt_msg_v8_t *data_v8 = NULL;
   lgsv_ckpt_msg_v6_t *data_v6 = NULL;
   lgsv_ckpt_msg_v5_t *data_v5 = NULL;
@@ -921,7 +1025,12 @@ static uint32_t ckpt_encode_async_update(lgs_cb_t 
*lgs_cb, EDU_HDL edu_hdl,
 
   TRACE_ENTER();
   /* Set reo_hdl from callback arg to ckpt_rec */
-  if (lgs_is_peer_v8()) {
+  if (lgs_is_peer_v9()) {
+    data_v9 = reinterpret_cast<lgsv_ckpt_msg_v9_t *>(
+        static_cast<int64_t>(cbk_arg->info.encode.io_reo_hdl));
+    vdata = data_v9;
+    edp_function = edp_ed_ckpt_msg_v9;
+  } else if (lgs_is_peer_v8()) {
     data_v8 = reinterpret_cast<lgsv_ckpt_msg_v8_t *>(
         static_cast<long>(cbk_arg->info.encode.io_reo_hdl));
     vdata = data_v8;
@@ -1250,7 +1359,12 @@ static uint32_t ckpt_decode_log_cfg_stream(lgs_cb_t *cb, 
void *ckpt_msg,
   void *stream_cfg;
   EDU_PROG_HANDLER edp_function;
 
-  if (lgs_is_peer_v8()) {
+  if (lgs_is_peer_v9()) {
+    lgsv_ckpt_msg_v9_t *ckpt_msg_v9 =
+        static_cast<lgsv_ckpt_msg_v9_t *>(ckpt_msg);
+    stream_cfg = &ckpt_msg_v9->ckpt_rec.stream_cfg;
+    edp_function = edp_ed_cfg_stream_rec_v9;
+  } else if (lgs_is_peer_v8()) {
     lgsv_ckpt_msg_v8_t *ckpt_msg_v8 =
         static_cast<lgsv_ckpt_msg_v8_t *>(ckpt_msg);
     stream_cfg = &ckpt_msg_v8->ckpt_rec.stream_cfg;
@@ -1341,6 +1455,8 @@ static uint32_t ckpt_decode_async_update(lgs_cb_t *cb,
   lgsv_ckpt_msg_v6_t *ckpt_msg_v6 = &msg_v6;
   lgsv_ckpt_msg_v8_t msg_v8;
   lgsv_ckpt_msg_v8_t *ckpt_msg_v8 = &msg_v8;
+  lgsv_ckpt_msg_v9_t msg_v9;
+  lgsv_ckpt_msg_v9_t *ckpt_msg_v9 = &msg_v9;
   void *ckpt_msg;
   lgsv_ckpt_header_t hdr, *hdr_ptr = &hdr;
 
@@ -1361,7 +1477,10 @@ static uint32_t ckpt_decode_async_update(lgs_cb_t *cb,
 
   TRACE_2("\tckpt_rec_type: %d ", (int)hdr_ptr->ckpt_rec_type);
 
-  if (lgs_is_peer_v8()) {
+  if (lgs_is_peer_v9()) {
+    ckpt_msg_v9->header = hdr;
+    ckpt_msg = ckpt_msg_v9;
+  } else if (lgs_is_peer_v8()) {
     ckpt_msg_v8->header = hdr;
     ckpt_msg = ckpt_msg_v8;
   } else if (lgs_is_peer_v6()) {
@@ -1385,7 +1504,10 @@ static uint32_t ckpt_decode_async_update(lgs_cb_t *cb,
   switch (hdr_ptr->ckpt_rec_type) {
     case LGS_CKPT_CLIENT_INITIALIZE:
       TRACE_2("\tINITIALIZE REC: UPDATE");
-      if (lgs_is_peer_v8()) {
+      if (lgs_is_peer_v9()) {
+        reg_rec = &ckpt_msg_v9->ckpt_rec.initialize_client;
+        edp_function_reg = edp_ed_reg_rec_v6;
+      } else if (lgs_is_peer_v8()) {
         reg_rec = &ckpt_msg_v8->ckpt_rec.initialize_client;
         edp_function_reg = edp_ed_reg_rec_v6;
       } else if (lgs_is_peer_v6()) {
@@ -1421,7 +1543,9 @@ static uint32_t ckpt_decode_async_update(lgs_cb_t *cb,
 
     case LGS_CKPT_OPEN_STREAM: /* 4 */
       TRACE_2("\tSTREAM OPEN: UPDATE");
-      if (lgs_is_peer_v8()) {
+      if (lgs_is_peer_v9()) {
+        stream_open = &ckpt_msg_v9->ckpt_rec.stream_open;
+      } else if (lgs_is_peer_v8()) {
         stream_open = &ckpt_msg_v8->ckpt_rec.stream_open;
       } else if (lgs_is_peer_v6()) {
         stream_open = &ckpt_msg_v6->ckpt_rec.stream_open;
@@ -1542,6 +1666,7 @@ static uint32_t ckpt_decode_cold_sync(lgs_cb_t *cb, 
NCS_MBCSV_CB_ARG *cbk_arg) {
   lgsv_ckpt_msg_v2_t msg_v2;
   lgsv_ckpt_msg_v6_t msg_v6;
   lgsv_ckpt_msg_v8_t msg_v8;
+  lgsv_ckpt_msg_v9_t msg_v9;
   uint32_t num_rec = 0;
   void *reg_rec = NULL;
   lgs_ckpt_stream_open_t *stream_rec = NULL;
@@ -1563,7 +1688,16 @@ static uint32_t ckpt_decode_cold_sync(lgs_cb_t *cb, 
NCS_MBCSV_CB_ARG *cbk_arg) {
      | Header|RegRecords1..n|Header|streamRecords1..n|
      -------------------------------------------------
   */
-  if (lgs_is_peer_v8()) {
+  if (lgs_is_peer_v9()) {
+    lgsv_ckpt_msg_v9_t *data_v9 = &msg_v9;
+    header = &data_v9->header;
+    initialize_client_rec_ptr = &data_v9->ckpt_rec.initialize_client;
+    stream_open_rec_ptr = &data_v9->ckpt_rec.stream_open;
+    vdata = data_v9;
+    vckpt_rec = &data_v9->ckpt_rec;
+    ckpt_rec_size = sizeof(data_v9->ckpt_rec);
+    edp_function_reg = edp_ed_reg_rec_v6;
+  } else if (lgs_is_peer_v8()) {
     lgsv_ckpt_msg_v8_t *data_v8 = &msg_v8;
     header = &data_v8->header;
     initialize_client_rec_ptr = &data_v8->ckpt_rec.initialize_client;
@@ -1725,13 +1859,17 @@ uint32_t process_ckpt_data(lgs_cb_t *cb, void *data) {
   lgsv_ckpt_msg_v5_t *data_v5;
   lgsv_ckpt_msg_v6_t *data_v6;
   lgsv_ckpt_msg_v8_t *data_v8;
+  lgsv_ckpt_msg_v9_t *data_v9;
 
   if ((!cb) || (data == NULL)) {
     TRACE("%s - FAILED: (!cb) || (data == NULL)", __FUNCTION__);
     return (rc = NCSCC_RC_FAILURE);
   }
 
-  if (lgs_is_peer_v8()) {
+  if (lgs_is_peer_v9()) {
+    data_v9 = static_cast<lgsv_ckpt_msg_v9_t *>(data);
+    lgsv_ckpt_msg_type = data_v9->header.ckpt_rec_type;
+  } else if (lgs_is_peer_v8()) {
     data_v8 = static_cast<lgsv_ckpt_msg_v8_t *>(data);
     lgsv_ckpt_msg_type = data_v8->header.ckpt_rec_type;
   } else if (lgs_is_peer_v6()) {
@@ -2230,7 +2368,10 @@ uint32_t ckpt_proc_open_stream(lgs_cb_t *cb, void *data) 
{
 
   TRACE_ENTER();
 
-  if (lgs_is_peer_v8()) {
+  if (lgs_is_peer_v9()) {
+    lgsv_ckpt_msg_v9_t *data_v9 = static_cast<lgsv_ckpt_msg_v9_t *>(data);
+    param = &data_v9->ckpt_rec.stream_open;
+  } else if (lgs_is_peer_v8()) {
     lgsv_ckpt_msg_v8_t *data_v8 = static_cast<lgsv_ckpt_msg_v8_t *>(data);
     param = &data_v8->ckpt_rec.stream_open;
   } else if (lgs_is_peer_v6()) {
@@ -2289,6 +2430,7 @@ uint32_t ckpt_proc_open_stream(lgs_cb_t *cb, void *data) {
     stream->logFileCurrent = param->logFileCurrent;
     stream->stb_prev_actlogFileCurrent = param->logFileCurrent;
     stream->stb_logFileCurrent = param->logFileCurrent;
+    stream->facilityId = param->facilityId;
 
     if (stream->streamType == STREAM_TYPE_APPLICATION) {
       // Note: Previous handling for backwards compatibility
@@ -2497,10 +2639,27 @@ static uint32_t ckpt_proc_cfg_stream(lgs_cb_t *cb, void 
*data) {
   SaUint32T severityFilter;
   char *logFileCurrent;
   bool new_cfg_file_needed = false;
+  uint32_t facilityId = 16;
 
   TRACE_ENTER();
 
-  if (lgs_is_peer_v8()) {
+  if (lgs_is_peer_v9()) {
+    lgsv_ckpt_msg_v9_t *data_v9 = static_cast<lgsv_ckpt_msg_v9_t *>(data);
+    name = data_v9->ckpt_rec.stream_cfg.name;
+    fileName = data_v9->ckpt_rec.stream_cfg.fileName;
+    pathName = data_v9->ckpt_rec.stream_cfg.pathName;
+    maxLogFileSize = data_v9->ckpt_rec.stream_cfg.maxLogFileSize;
+    fixedLogRecordSize = data_v9->ckpt_rec.stream_cfg.fixedLogRecordSize;
+    logFullAction = data_v9->ckpt_rec.stream_cfg.logFullAction;
+    logFullHaltThreshold = data_v9->ckpt_rec.stream_cfg.logFullHaltThreshold;
+    maxFilesRotated = data_v9->ckpt_rec.stream_cfg.maxFilesRotated;
+    logFileFormat = data_v9->ckpt_rec.stream_cfg.logFileFormat;
+    severityFilter = data_v9->ckpt_rec.stream_cfg.severityFilter;
+    logFileCurrent = data_v9->ckpt_rec.stream_cfg.logFileCurrent;
+    dest_names = data_v9->ckpt_rec.stream_cfg.dest_names;
+    closetime = data_v9->ckpt_rec.stream_cfg.c_file_close_time_stamp;
+    facilityId = data_v9->ckpt_rec.stream_cfg.facilityId;
+  } else if (lgs_is_peer_v8()) {
     lgsv_ckpt_msg_v8_t *data_v8 = static_cast<lgsv_ckpt_msg_v8_t *>(data);
     name = data_v8->ckpt_rec.stream_cfg.name;
     fileName = data_v8->ckpt_rec.stream_cfg.fileName;
@@ -2571,6 +2730,7 @@ static uint32_t ckpt_proc_cfg_stream(lgs_cb_t *cb, void 
*data) {
       (stream->logFullAction != logFullAction) ||
       (stream->maxFilesRotated != maxFilesRotated) ||
       (strcmp(stream->logFileFormat, logFileFormat) != 0) ||
+      (stream->facilityId != facilityId) ||
       (stream->fileName != fileName))
     new_cfg_file_needed = true;
 
@@ -2581,6 +2741,7 @@ static uint32_t ckpt_proc_cfg_stream(lgs_cb_t *cb, void 
*data) {
   stream->logFullAction = logFullAction;
   stream->logFullHaltThreshold = logFullHaltThreshold;
   stream->maxFilesRotated = maxFilesRotated;
+  stream->facilityId = facilityId;
 
   if (stream->logFileFormat != NULL) {
     free(stream->logFileFormat);
@@ -2690,7 +2851,11 @@ uint32_t lgs_ckpt_send_async(lgs_cb_t *cb, void 
*ckpt_rec, uint32_t action) {
 
   TRACE_ENTER();
 
-  if (lgs_is_peer_v8()) {
+  if (lgs_is_peer_v9()) {
+    lgsv_ckpt_msg_v9_t *ckpt_rec_v9 =
+        static_cast<lgsv_ckpt_msg_v9_t *>(ckpt_rec);
+    ckpt_rec_type = ckpt_rec_v9->header.ckpt_rec_type;
+  } else if (lgs_is_peer_v8()) {
     lgsv_ckpt_msg_v8_t *ckpt_rec_v8 =
         static_cast<lgsv_ckpt_msg_v8_t *>(ckpt_rec);
     ckpt_rec_type = ckpt_rec_v8->header.ckpt_rec_type;
diff --git a/src/log/logd/lgs_mbcsv.h b/src/log/logd/lgs_mbcsv.h
index 998e843e4..02db433f2 100644
--- a/src/log/logd/lgs_mbcsv.h
+++ b/src/log/logd/lgs_mbcsv.h
@@ -43,9 +43,10 @@
 #define LGS_MBCSV_VERSION_6 6
 #define LGS_MBCSV_VERSION_7 7
 #define LGS_MBCSV_VERSION_8 8
+#define LGS_MBCSV_VERSION_9 9
 
 /* Current version */
-#define LGS_MBCSV_VERSION 8
+#define LGS_MBCSV_VERSION 9
 #define LGS_MBCSV_VERSION_MIN 1
 
 /* Checkpoint message types(Used as 'reotype' w.r.t mbcsv)  */
@@ -108,6 +109,7 @@ typedef struct {
   char *dest_names;
   logStreamTypeT streamType;
   uint32_t logRecordId; /* log record identifier increased for each record */
+  uint32_t facilityId;
 } lgs_ckpt_stream_open_t;
 
 uint32_t lgs_mbcsv_init(lgs_cb_t *lgs_cb, SaAmfHAStateT ha_state);
@@ -121,6 +123,7 @@ bool lgs_is_peer_v6();
 // lgs_ckpt_stream_open_t structure
 bool lgs_is_peer_v7();
 bool lgs_is_peer_v8();
+bool lgs_is_peer_v9();
 
 bool lgs_is_split_file_system();
 uint32_t lgs_mbcsv_dispatch(NCS_MBCSV_HDL mbcsv_hdl);
diff --git a/src/log/logd/lgs_mbcsv_v9.cc b/src/log/logd/lgs_mbcsv_v9.cc
new file mode 100644
index 000000000..61b5f431c
--- /dev/null
+++ b/src/log/logd/lgs_mbcsv_v9.cc
@@ -0,0 +1,243 @@
+/*      -*- OpenSAF  -*-
+ *
+ * (C) Copyright 2020 The OpenSAF Foundation
+ * Copyright Ericsson AB 2020 - All Rights Reserved.
+ *
+ * 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): Ericsson AB
+ *
+ */
+
+#include "log/logd/lgs_mbcsv_v9.h"
+#include "base/logtrace.h"
+
+/****************************************************************************
+ * Name          : edp_ed_cfg_stream_rec
+ *
+ * Description   : This function is an EDU program for encoding/decoding
+ *                 lgsv checkpoint cfg_update_stream log rec.
+ *
+ * Arguments     : EDU_HDL - pointer to edu handle,
+ *                 EDU_TKN - internal edu token to help encode/decode,
+ *                 POINTER to the structure to encode/decode from/to,
+ *                 data length specifying number of structures,
+ *                 EDU_BUF_ENV - pointer to buffer for encoding/decoding.
+ *                 op - operation type being encode/decode.
+ *                 EDU_ERR - out param to indicate errors in processing.
+ *
+ * Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
+ *
+ * Notes         : None.
+ *****************************************************************************/
+
+uint32_t edp_ed_cfg_stream_rec_v9(EDU_HDL *edu_hdl, EDU_TKN *edu_tkn,
+                                  NCSCONTEXT ptr, uint32_t *ptr_data_len,
+                                  EDU_BUF_ENV *buf_env, EDP_OP_TYPE op,
+                                  EDU_ERR *o_err) {
+  uint32_t rc = NCSCC_RC_SUCCESS;
+  lgs_ckpt_stream_cfg_v4_t *ckpt_stream_cfg_msg_ptr = NULL,
+                           **ckpt_stream_cfg_msg_dec_ptr;
+  TRACE_ENTER();
+  EDU_INST_SET ckpt_stream_cfg_rec_ed_rules[] = {
+      {EDU_START, edp_ed_cfg_stream_rec_v9, 0, 0, 0,
+       sizeof(lgs_ckpt_stream_cfg_v4_t), 0, NULL},
+      {EDU_EXEC, ncs_edp_string, 0, 0, 0,
+       (int64_t) & (reinterpret_cast<lgs_ckpt_stream_cfg_v4_t *>(0))->name, 0,
+       NULL},
+      {EDU_EXEC, ncs_edp_string, 0, 0, 0,
+       (int64_t) & (reinterpret_cast<lgs_ckpt_stream_cfg_v4_t *>(0))->fileName,
+       0, NULL},
+      {EDU_EXEC, ncs_edp_string, 0, 0, 0,
+       (int64_t) & (reinterpret_cast<lgs_ckpt_stream_cfg_v4_t *>(0))->pathName,
+       0, NULL},
+      {EDU_EXEC, ncs_edp_uns64, 0, 0, 0,
+       (int64_t) &
+           (reinterpret_cast<lgs_ckpt_stream_cfg_v4_t *>(0))->maxLogFileSize,
+       0, NULL},
+      {EDU_EXEC, ncs_edp_uns32, 0, 0, 0,
+       (int64_t) & (reinterpret_cast<lgs_ckpt_stream_cfg_v4_t *>(0))
+                       ->fixedLogRecordSize,
+       0, NULL},
+      {EDU_EXEC, ncs_edp_uns32, 0, 0, 0,
+       (int64_t) &
+           (reinterpret_cast<lgs_ckpt_stream_cfg_v4_t *>(0))->haProperty,
+       0, NULL},
+      {EDU_EXEC, ncs_edp_uns32, 0, 0, 0,
+       (int64_t) &
+           (reinterpret_cast<lgs_ckpt_stream_cfg_v4_t *>(0))->logFullAction,
+       0, NULL},
+      {EDU_EXEC, ncs_edp_uns32, 0, 0, 0,
+       (int64_t) & (reinterpret_cast<lgs_ckpt_stream_cfg_v4_t *>(0))
+                       ->logFullHaltThreshold,
+       0, NULL},
+      {EDU_EXEC, ncs_edp_uns32, 0, 0, 0,
+       (int64_t) &
+           (reinterpret_cast<lgs_ckpt_stream_cfg_v4_t *>(0))->maxFilesRotated,
+       0, NULL},
+      {EDU_EXEC, ncs_edp_string, 0, 0, 0,
+       (int64_t) &
+           (reinterpret_cast<lgs_ckpt_stream_cfg_v4_t *>(0))->logFileFormat,
+       0, NULL},
+      {EDU_EXEC, ncs_edp_uns32, 0, 0, 0,
+       (int64_t) &
+           (reinterpret_cast<lgs_ckpt_stream_cfg_v4_t *>(0))->severityFilter,
+       0, NULL},
+      {EDU_EXEC, ncs_edp_string, 0, 0, 0,
+       (int64_t) &
+           (reinterpret_cast<lgs_ckpt_stream_cfg_v4_t *>(0))->logFileCurrent,
+       0, NULL},
+      {EDU_EXEC, ncs_edp_string, 0, 0, 0,
+       (int64_t) &
+           (reinterpret_cast<lgs_ckpt_stream_cfg_v4_t *>(0))->dest_names,
+       0, NULL},
+      {EDU_EXEC, ncs_edp_uns64, 0, 0, 0,
+       (int64_t) & (reinterpret_cast<lgs_ckpt_stream_cfg_v4_t *>(0))
+                       ->c_file_close_time_stamp,
+       0, NULL},
+      {EDU_EXEC, ncs_edp_uns32, 0, 0, 0,
+       (int64_t) &
+           (reinterpret_cast<lgs_ckpt_stream_cfg_v4_t *>(0))->facilityId,
+       0, NULL},
+      {EDU_END, 0, 0, 0, 0, 0, 0, NULL},
+  };
+
+  if (op == EDP_OP_TYPE_ENC) {
+    ckpt_stream_cfg_msg_ptr = static_cast<lgs_ckpt_stream_cfg_v4_t *>(ptr);
+  } else if (op == EDP_OP_TYPE_DEC) {
+    ckpt_stream_cfg_msg_dec_ptr = static_cast<lgs_ckpt_stream_cfg_v4_t 
**>(ptr);
+    if (*ckpt_stream_cfg_msg_dec_ptr == NULL) {
+      *o_err = EDU_ERR_MEM_FAIL;
+      return NCSCC_RC_FAILURE;
+    }
+    memset(*ckpt_stream_cfg_msg_dec_ptr, '\0',
+           sizeof(lgs_ckpt_stream_cfg_v4_t));
+    ckpt_stream_cfg_msg_ptr = *ckpt_stream_cfg_msg_dec_ptr;
+  } else {
+    ckpt_stream_cfg_msg_ptr = static_cast<lgs_ckpt_stream_cfg_v4_t *>(ptr);
+  }
+
+  rc = m_NCS_EDU_RUN_RULES(edu_hdl, edu_tkn, ckpt_stream_cfg_rec_ed_rules,
+                           ckpt_stream_cfg_msg_ptr, ptr_data_len, buf_env, op,
+                           o_err);
+  TRACE_LEAVE();
+  return rc;
+}
+
+/****************************************************************************
+ * Name          : edp_ed_ckpt_msg_v9
+ *
+ * Description   : This function is an EDU program for encoding/decoding
+ *                 lgsv checkpoint messages. This program runs the
+ *                 edp_ed_hdr_rec program first to decide the
+ *                 checkpoint message type based on which it will call the
+ *                 appropriate EDU programs for the different checkpoint
+ *                 messages.
+ *
+ * Arguments     : EDU_HDL - pointer to edu handle,
+ *                 EDU_TKN - internal edu token to help encode/decode,
+ *                 POINTER to the structure to encode/decode from/to,
+ *                 data length specifying number of structures,
+ *                 EDU_BUF_ENV - pointer to buffer for encoding/decoding.
+ *                 op - operation type being encode/decode.
+ *                 EDU_ERR - out param to indicate errors in processing.
+ *
+ * Return Values : NCSCC_RC_SUCCESS/NCSCC_RC_FAILURE
+ *
+ * Notes         : None.
+ *****************************************************************************/
+
+uint32_t edp_ed_ckpt_msg_v9(EDU_HDL *edu_hdl, EDU_TKN *edu_tkn, NCSCONTEXT ptr,
+                            uint32_t *ptr_data_len, EDU_BUF_ENV *buf_env,
+                            EDP_OP_TYPE op, EDU_ERR *o_err) {
+  uint32_t rc = NCSCC_RC_SUCCESS;
+  lgsv_ckpt_msg_v9_t *ckpt_msg_ptr = NULL, **ckpt_msg_dec_ptr;
+  TRACE_ENTER();
+  EDU_INST_SET ckpt_msg_ed_rules[] = {
+      {EDU_START, edp_ed_ckpt_msg_v9, 0, 0, 0, sizeof(lgsv_ckpt_msg_v9_t), 0,
+       NULL},
+      {EDU_EXEC, edp_ed_header_rec, 0, 0, 0,
+       (int64_t) & (reinterpret_cast<lgsv_ckpt_msg_v9_t *>(0))->header, 0,
+       NULL},
+
+      {EDU_TEST, ncs_edp_uns32, 0, 0, 0,
+       (int64_t) & (reinterpret_cast<lgsv_ckpt_msg_v9_t *>(0))->header, 0,
+       (EDU_EXEC_RTINE)ckpt_msg_test_type},
+
+      /* Reg Record */
+      {EDU_EXEC, edp_ed_reg_rec_v6, 0, 0, static_cast<int>(EDU_EXIT),
+       (int64_t) & (reinterpret_cast<lgsv_ckpt_msg_v9_t *>(0))
+                       ->ckpt_rec.initialize_client,
+       0, NULL},
+
+      /* Finalize record */
+      {EDU_EXEC, edp_ed_finalize_rec_v2, 0, 0, static_cast<int>(EDU_EXIT),
+       (int64_t) & (reinterpret_cast<lgsv_ckpt_msg_v9_t *>(0))
+                       ->ckpt_rec.finalize_client,
+       0, NULL},
+
+      /* write log Record */
+      {EDU_EXEC, edp_ed_write_rec_v2, 0, 0, static_cast<int>(EDU_EXIT),
+       (int64_t) &
+           (reinterpret_cast<lgsv_ckpt_msg_v9_t *>(0))->ckpt_rec.write_log,
+       0, NULL},
+
+      /* Open stream */
+      {EDU_EXEC, edp_ed_open_stream_rec, 0, 0, static_cast<int>(EDU_EXIT),
+       (int64_t) &
+           (reinterpret_cast<lgsv_ckpt_msg_v9_t *>(0))->ckpt_rec.stream_open,
+       0, NULL},
+
+      /* Close stream */
+      {EDU_EXEC, edp_ed_close_stream_rec_v2, 0, 0, static_cast<int>(EDU_EXIT),
+       (int64_t) &
+           (reinterpret_cast<lgsv_ckpt_msg_v9_t *>(0))->ckpt_rec.stream_close,
+       0, NULL},
+
+      /* Agent dest */
+      {EDU_EXEC, edp_ed_agent_down_rec_v2, 0, 0, static_cast<int>(EDU_EXIT),
+       (int64_t) &
+           (reinterpret_cast<lgsv_ckpt_msg_v9_t *>(0))->ckpt_rec.stream_cfg,
+       0, NULL},
+
+      /* Cfg stream */
+      {EDU_EXEC, edp_ed_cfg_stream_rec_v9, 0, 0, static_cast<int>(EDU_EXIT),
+       (int64_t) &
+           (reinterpret_cast<lgsv_ckpt_msg_v9_t *>(0))->ckpt_rec.stream_cfg,
+       0, NULL},
+
+      /* Lgs cfg */
+      {EDU_EXEC, edp_ed_lgs_cfg_rec_v5, 0, 0, static_cast<int>(EDU_EXIT),
+       (int64_t) &
+           (reinterpret_cast<lgsv_ckpt_msg_v9_t *>(0))->ckpt_rec.lgs_cfg,
+       0, NULL},
+
+      {EDU_END, 0, 0, 0, 0, 0, 0, NULL},
+  };
+
+  if (op == EDP_OP_TYPE_ENC) {
+    ckpt_msg_ptr = static_cast<lgsv_ckpt_msg_v9_t *>(ptr);
+  } else if (op == EDP_OP_TYPE_DEC) {
+    ckpt_msg_dec_ptr = static_cast<lgsv_ckpt_msg_v9_t **>(ptr);
+    if (*ckpt_msg_dec_ptr == NULL) {
+      *o_err = EDU_ERR_MEM_FAIL;
+      return NCSCC_RC_FAILURE;
+    }
+    memset(*ckpt_msg_dec_ptr, '\0', sizeof(lgsv_ckpt_msg_v9_t));
+    ckpt_msg_ptr = *ckpt_msg_dec_ptr;
+  } else {
+    ckpt_msg_ptr = static_cast<lgsv_ckpt_msg_v9_t *>(ptr);
+  }
+
+  rc = m_NCS_EDU_RUN_RULES(edu_hdl, edu_tkn, ckpt_msg_ed_rules, ckpt_msg_ptr,
+                           ptr_data_len, buf_env, op, o_err);
+  TRACE_LEAVE();
+  return rc;
+}
diff --git a/src/log/logd/lgs_mbcsv_v9.h b/src/log/logd/lgs_mbcsv_v9.h
new file mode 100644
index 000000000..7c3ef9722
--- /dev/null
+++ b/src/log/logd/lgs_mbcsv_v9.h
@@ -0,0 +1,67 @@
+/*      -*- OpenSAF  -*-
+ *
+ * Copyright Ericsson AB 2020 - All Rights Reserved.
+ *
+ * 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): Ericsson AB
+ *
+ */
+
+#ifndef LOG_LOGD_LGS_MBCSV_V9_H_
+#define LOG_LOGD_LGS_MBCSV_V9_H_
+
+#include "log/logd/lgs.h"
+#include "log/logd/lgs_config.h"
+#include "log/logd/lgs_mbcsv_v2.h"
+#include "log/logd/lgs_mbcsv_v5.h"
+#include "log/logd/lgs_mbcsv_v6.h"
+
+typedef struct {
+  char *name;
+  char *fileName;
+  char *pathName;
+  SaUint64T maxLogFileSize;
+  SaUint32T fixedLogRecordSize;
+  SaBoolT haProperty; /* app log stream only */
+  SaLogFileFullActionT logFullAction;
+  SaUint32T logFullHaltThreshold; /* !app log stream */
+  SaUint32T maxFilesRotated;
+  char *logFileFormat;
+  SaUint32T severityFilter;
+  char *logFileCurrent;
+  char *dest_names;
+  uint64_t c_file_close_time_stamp; /* Time in sec for file rename on Active */
+  uint32_t facilityId;
+} lgs_ckpt_stream_cfg_v4_t;
+
+typedef struct {
+  lgsv_ckpt_header_t header;
+  union {
+    lgs_ckpt_initialize_msg_v6_t initialize_client;
+    lgs_ckpt_finalize_msg_v2_t finalize_client;
+    lgs_ckpt_write_log_v2_t write_log;
+    lgs_ckpt_agent_down_v2_t agent_down;
+    lgs_ckpt_stream_open_t stream_open;
+    lgs_ckpt_stream_close_v2_t stream_close;
+    lgs_ckpt_stream_cfg_v4_t stream_cfg;
+    lgs_ckpt_lgs_cfg_v5_t lgs_cfg;
+  } ckpt_rec;
+} lgsv_ckpt_msg_v9_t;
+
+uint32_t edp_ed_cfg_stream_rec_v9(EDU_HDL *edu_hdl, EDU_TKN *edu_tkn,
+                                  NCSCONTEXT ptr, uint32_t *ptr_data_len,
+                                  EDU_BUF_ENV *buf_env, EDP_OP_TYPE op,
+                                  EDU_ERR *o_err);
+uint32_t edp_ed_ckpt_msg_v9(EDU_HDL *edu_hdl, EDU_TKN *edu_tkn, NCSCONTEXT ptr,
+                            uint32_t *ptr_data_len, EDU_BUF_ENV *buf_env,
+                            EDP_OP_TYPE op, EDU_ERR *o_err);
+
+#endif  // LOG_LOGD_LGS_MBCSV_V9_H_
diff --git a/src/log/logd/lgs_recov.cc b/src/log/logd/lgs_recov.cc
index 7c0197b7f..c5f35885c 100644
--- a/src/log/logd/lgs_recov.cc
+++ b/src/log/logd/lgs_recov.cc
@@ -320,6 +320,7 @@ int lgs_restore_one_app_stream(const std::string 
&stream_name,
   log_stream_t *log_stream = nullptr;
   SaTimeT restored_creationTimeStamp = 0;
   SaUint32T restored_severityFilter = 0;
+  SaUint32T restored_facilityId = 16;
 
   std::string fileName;
   std::string pathName, fullPathName;
@@ -501,6 +502,14 @@ int lgs_restore_one_app_stream(const std::string 
&stream_name,
       }
       restored_severityFilter = *(static_cast<SaUint32T *>(value));
       TRACE("\t saLogStreamSeverityFilter=%d", restored_severityFilter);
+    } else if (!strcmp(name, "saLogStreamFacilityId")) {
+      if (value == nullptr) {
+        TRACE("%s: Fail, has empty value", name);
+        rc_out = -1;
+        goto done_free_attr;
+      }
+      restored_facilityId = *(static_cast<SaUint32T *>(value));
+      TRACE("\t saLogStreamFacilityId=%d", restored_facilityId);
     }
   }
 
@@ -567,6 +576,7 @@ int lgs_restore_one_app_stream(const std::string 
&stream_name,
   log_stream->severityFilter = restored_severityFilter;
   log_stream->filtered = 0;
   log_stream->isRtStream = SA_TRUE;
+  log_stream->facilityId = restored_facilityId;
 
   TRACE("\t Stream obj attributes handled and stream is created");
 
diff --git a/src/log/logd/lgs_stream.cc b/src/log/logd/lgs_stream.cc
index f2f7df940..71782f7ea 100644
--- a/src/log/logd/lgs_stream.cc
+++ b/src/log/logd/lgs_stream.cc
@@ -418,6 +418,7 @@ void log_stream_print(log_stream_t *stream) {
   TRACE_2("  filtered:             %llu", stream->filtered);
   TRACE_2("  stb_dest_names:       %s", stream->stb_dest_names.c_str());
   TRACE_2("  isRtStream:           %d", stream->isRtStream);
+  TRACE_2("  facilityId:           %u", stream->facilityId);
 }
 
 /**
@@ -665,6 +666,12 @@ SaAisErrorT lgs_create_appstream_rt_object(log_stream_t 
*const stream) {
         .attrValueType = SA_IMM_ATTR_SATIMET,
         .attrValuesNumber = 1,
         .attrValues = arr11};
+    void *arr12[] = {&stream->facilityId};
+    const SaImmAttrValuesT_2 attr_saLogStreamFacilityId = {
+        .attrName = const_cast<SaImmAttrNameT>("saLogStreamFacilityId"),
+        .attrValueType = SA_IMM_ATTR_SAUINT32T,
+        .attrValuesNumber = 1,
+        .attrValues = arr12};
     const SaImmAttrValuesT_2 *attrValues[] = {
         &attr_safLgStr,
         &attr_safLogStreamFileName,
@@ -677,6 +684,7 @@ SaAisErrorT lgs_create_appstream_rt_object(log_stream_t 
*const stream) {
         &attr_saLogStreamLogFileFormat,
         &attr_saLogStreamSeverityFilter,
         &attr_saLogStreamCreationTimestamp,
+        &attr_saLogStreamFacilityId,
         NULL};
 
     SaNameT object_name;
@@ -723,6 +731,7 @@ log_stream_t *log_stream_new(const std::string &name, int 
stream_id) {
   stream->severityFilter = 0x7f; /* by default all levels are allowed */
   stream->isRtStream = SA_FALSE;
   stream->dest_names.clear();
+  stream->facilityId = 16;
 
   /* Initiate local or shared stream file descriptor dependant on shared or
    * split file system
diff --git a/src/log/logd/lgs_stream.h b/src/log/logd/lgs_stream.h
index 8fdb5693d..a9659582b 100644
--- a/src/log/logd/lgs_stream.h
+++ b/src/log/logd/lgs_stream.h
@@ -53,6 +53,7 @@ typedef struct log_stream {
   SaUint32T numOpeners;
   SaUint64T filtered; /* discarded by server due to filtering */
   std::string rfc5424MsgId;
+  uint32_t facilityId;
   /* --- end correspond to IMM Class --- */
 
   uint32_t streamId; /* The unique stream id for this stream */
diff --git a/src/log/logd/lgs_unixsock_dest.cc 
b/src/log/logd/lgs_unixsock_dest.cc
index a48250063..cee3abbf5 100644
--- a/src/log/logd/lgs_unixsock_dest.cc
+++ b/src/log/logd/lgs_unixsock_dest.cc
@@ -70,13 +70,16 @@ void UnixSocketHandler::Open() { FlushStatus(); }
 
 void UnixSocketHandler::FormRfc5424(const DestinationHandler::RecordInfo& msg,
                                     RfcBuffer* buf) {
+  base::LogMessage::Facility facilityId =
+      (msg.facilityId < 24)
+          ? static_cast<base::LogMessage::Facility>(msg.facilityId)
+          : base::LogMessage::Facility::kLocal0;
   base::LogMessage::Severity sev{Sev(msg.severity)};
   base::LogMessage::HostName hostname{msg.origin};
   base::LogMessage::ProcId procid{""};
   base::LogMessage::AppName appname{msg.app_name};
 
-  base::LogMessage::Write(base::LogMessage::Facility::kLocal0, sev, msg.time,
-                          hostname, appname, procid,
+  base::LogMessage::Write(facilityId, sev, msg.time, hostname, appname, procid,
                           base::LogMessage::MsgId{msg.msgid}, {},
                           std::string{msg.log_record}, buf);
 }
-- 
2.17.1




_______________________________________________
Opensaf-devel mailing list
Opensaf-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to