osaf/services/saf/logsv/README | 16 +
osaf/services/saf/logsv/config/Makefile.am | 4 +-
osaf/services/saf/logsv/config/gcfg_classes.xml | 18 +
osaf/services/saf/logsv/config/gcfg_objects.xml | 6 +
osaf/services/saf/logsv/lgs/Makefile.am | 6 +-
osaf/services/saf/logsv/lgs/lgs.h | 1 +
osaf/services/saf/logsv/lgs/lgs_amf.cc | 9 +-
osaf/services/saf/logsv/lgs/lgs_evt.cc | 11 +-
osaf/services/saf/logsv/lgs/lgs_evt.h | 1 +
osaf/services/saf/logsv/lgs/lgs_fmt.cc | 52 +-
osaf/services/saf/logsv/lgs/lgs_fmt.h | 20 +-
osaf/services/saf/logsv/lgs/lgs_imm_gcfg.cc | 1082 +++++++++++++++++++++++
osaf/services/saf/logsv/lgs/lgs_imm_gcfg.h | 28 +
osaf/services/saf/logsv/lgs/lgs_main.cc | 1 +
osaf/services/saf/logsv/lgs/lgs_mbcsv.cc | 50 +-
osaf/services/saf/logsv/lgs/lgs_mbcsv.h | 1 +
osaf/services/saf/logsv/lgs/lgs_mds.cc | 13 +-
tests/logsv/logtest.c | 7 +
tests/logsv/logtest.h | 2 +
tests/logsv/tet_LogOiOps.c | 205 ++++
20 files changed, 1498 insertions(+), 35 deletions(-)
Add new tokens (@Cq and @Cp) to represent node name and network name.
diff --git a/osaf/services/saf/logsv/README b/osaf/services/saf/logsv/README
--- a/osaf/services/saf/logsv/README
+++ b/osaf/services/saf/logsv/README
@@ -732,3 +732,19 @@ for file handling thread complete file I
If user suffers the timeout when sending a big record size (e.g: 65535 bytes),
the user can adjust the waiting time by updating logFileIoTimeout attribute
value up to 5000ms.
+
+3. New tokens are added (#1480)
+-------------------------------
+- @Cp: for showing the network name
+- @Cq: for showing node name where the log record comes from.
+
+a) The network name comes from an configurable attribute `opensafNetworkName`
+ which belongs to global configurable class `OpensafConfig`.
+ The attribute can be accessed via DN
`opensafConfigId=opensafGlobalConfig,safApp=OpenSAF`.
+
+ LOG service is an applier to this object class, so that whenever there is
change in
+ network name attribute `opensafNetworkName`, LOG service will be notified.
+
+b) Regarding node name, LOG service gets this information when decoding
messages at MDS layer.
+
+
diff --git a/osaf/services/saf/logsv/config/Makefile.am
b/osaf/services/saf/logsv/config/Makefile.am
--- a/osaf/services/saf/logsv/config/Makefile.am
+++ b/osaf/services/saf/logsv/config/Makefile.am
@@ -26,6 +26,8 @@ if ENABLE_IMMXML
dist_pkgimmxml_svc_DATA = \
logsv_sc_template.xml \
logsv_classes.xml \
- logsv_objects.xml
+ logsv_objects.xml \
+ gcfg_classes.xml \
+ gcfg_objects.xml
endif
diff --git a/osaf/services/saf/logsv/config/gcfg_classes.xml
b/osaf/services/saf/logsv/config/gcfg_classes.xml
new file mode 100644
--- /dev/null
+++ b/osaf/services/saf/logsv/config/gcfg_classes.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="utf-8"?>
+<imm:IMM-contents xmlns:imm="http://www.saforum.org/IMMSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="SAI-AIS-IMM-XSD-A.02.13.xsd">
+ <class name="OpensafConfig">
+ <category>SA_CONFIG</category>
+ <rdn>
+ <name>opensafConfigId</name>
+ <type>SA_STRING_T</type>
+ <category>SA_CONFIG</category>
+ <flag>SA_INITIALIZED</flag>
+ </rdn>
+ <attr>
+ <name>opensafNetworkName</name>
+ <type>SA_STRING_T</type>
+ <category>SA_CONFIG</category>
+ <flag>SA_WRITABLE</flag>
+ </attr>
+ </class>
+</imm:IMM-contents>
diff --git a/osaf/services/saf/logsv/config/gcfg_objects.xml
b/osaf/services/saf/logsv/config/gcfg_objects.xml
new file mode 100644
--- /dev/null
+++ b/osaf/services/saf/logsv/config/gcfg_objects.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<imm:IMM-contents xmlns:imm="http://www.saforum.org/IMMSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="SAI-AIS-IMM-XSD-A.02.13.xsd">
+ <object class="OpensafConfig">
+ <dn>opensafConfigId=opensafGlobalConfig,safApp=OpenSAF</dn>
+ </object>
+</imm:IMM-contents>
diff --git a/osaf/services/saf/logsv/lgs/Makefile.am
b/osaf/services/saf/logsv/lgs/Makefile.am
--- a/osaf/services/saf/logsv/lgs/Makefile.am
+++ b/osaf/services/saf/logsv/lgs/Makefile.am
@@ -36,7 +36,8 @@ noinst_HEADERS = \
lgs_mbcsv_v2.h \
lgs_mbcsv_v3.h \
lgs_mbcsv_v5.h \
- lgs_recov.h
+ lgs_recov.h \
+ lgs_imm_gcfg.h
osaf_execbindir = $(pkglibdir)
osaf_execbin_PROGRAMS = osaflogd
@@ -65,7 +66,8 @@ osaflogd_SOURCES = \
lgs_mbcsv_v2.cc \
lgs_mbcsv_v3.cc \
lgs_mbcsv_v5.cc \
- lgs_recov.cc
+ lgs_recov.cc \
+ lgs_imm_gcfg.cc
osaflogd_LDADD = \
$(top_builddir)/osaf/tools/safimm/src/libimmutil.la \
diff --git a/osaf/services/saf/logsv/lgs/lgs.h
b/osaf/services/saf/logsv/lgs/lgs.h
--- a/osaf/services/saf/logsv/lgs/lgs.h
+++ b/osaf/services/saf/logsv/lgs/lgs.h
@@ -42,6 +42,7 @@
#include "lgs_util.h"
#include "lgs_stream.h"
#include "lgs_config.h"
+#include "lgs_imm_gcfg.h"
/* ========================================================================
* DEFINITIONS
diff --git a/osaf/services/saf/logsv/lgs/lgs_amf.cc
b/osaf/services/saf/logsv/lgs/lgs_amf.cc
--- a/osaf/services/saf/logsv/lgs/lgs_amf.cc
+++ b/osaf/services/saf/logsv/lgs/lgs_amf.cc
@@ -66,6 +66,7 @@ static SaAisErrorT amf_active_state_hand
lgs_imm_impl_set(cb->immOiHandle);
conf_runtime_obj_create(cb->immOiHandle);
+ lgs_start_gcfg_applier();
/* check existing streams */
stream = log_stream_getnext_by_name(NULL);
@@ -75,8 +76,8 @@ static SaAisErrorT amf_active_state_hand
*stream->p_fd = -1; /* First Initialize fd */
stream = log_stream_getnext_by_name(stream->name);
}
-
- done:
+
+done:
immutilWrapperProfile.nTries = 20; /* Reset retry time to more normal
value. */
immutilWrapperProfile.errorsAreFatal = 1;
/* Update role independent of stream processing */
@@ -134,6 +135,8 @@ static SaAisErrorT amf_quiescing_state_h
(void)immutil_saImmOiImplementerClear(cb->immOiHandle);
immutilWrapperProfile.errorsAreFatal = 1;
+ lgs_stop_gcfg_applier();
+
return saAmfCSIQuiescingComplete(cb->amf_hdl, invocation, SA_AIS_OK);
}
@@ -163,6 +166,8 @@ static SaAisErrorT amf_quiesced_state_ha
(void)immutil_saImmOiImplementerClear(cb->immOiHandle);
immutilWrapperProfile.errorsAreFatal = 1;
+ lgs_stop_gcfg_applier();
+
/*
** Change the MDS VDSET role to Quiesced. Wait for MDS callback with
type
** MDS_CALLBACK_QUIESCED_ACK. Then change MBCSv role. Don't change
diff --git a/osaf/services/saf/logsv/lgs/lgs_evt.cc
b/osaf/services/saf/logsv/lgs/lgs_evt.cc
--- a/osaf/services/saf/logsv/lgs/lgs_evt.cc
+++ b/osaf/services/saf/logsv/lgs/lgs_evt.cc
@@ -22,6 +22,7 @@
#include "lgs_mbcsv_v1.h"
#include "lgs_mbcsv_v2.h"
#include "lgs_recov.h"
+#include "lgs_imm_gcfg.h"
/* Macro to validate the version */
#define m_LOG_VER_IS_VALID(ver) \
@@ -527,6 +528,7 @@ static uint32_t proc_rda_cb_msg(lgsv_lgs
/* fail over, become implementer */
lgs_imm_impl_set(lgs_cb->immOiHandle);
+ lgs_start_gcfg_applier();
/* Agent down list has to be processed first */
lgs_process_lga_down_list();
@@ -1199,8 +1201,13 @@ static uint32_t proc_write_log_async_msg
lgsv_ckpt_msg_v2_t ckpt_v2;
void *ckpt_ptr;
uint32_t max_logrecsize = 0;
+ char node_name[_POSIX_HOST_NAME_MAX];
- TRACE_ENTER2("client_id %u, stream ID %u", param->client_id,
param->lstr_id);
+ memset(node_name, 0, _POSIX_HOST_NAME_MAX);
+ strncpy(node_name, evt->node_name, _POSIX_HOST_NAME_MAX);
+
+ TRACE_ENTER2("client_id %u, stream ID %u, node_name = %s",
+ param->client_id, param->lstr_id, node_name);
if (lgs_client_get_by_id(param->client_id) == NULL) {
TRACE("Bad client ID: %u", param->client_id);
@@ -1235,7 +1242,7 @@ static uint32_t proc_write_log_async_msg
}
if ((n = lgs_format_log_record(param->logRecord, stream->logFileFormat,
stream->maxLogFileSize,
- stream->fixedLogRecordSize, buf_size, logOutputString,
++stream->logRecordId)) == 0) {
+ stream->fixedLogRecordSize, buf_size, logOutputString,
++stream->logRecordId, node_name)) == 0) {
error = SA_AIS_ERR_INVALID_PARAM;
goto done;
}
diff --git a/osaf/services/saf/logsv/lgs/lgs_evt.h
b/osaf/services/saf/logsv/lgs/lgs_evt.h
--- a/osaf/services/saf/logsv/lgs/lgs_evt.h
+++ b/osaf/services/saf/logsv/lgs/lgs_evt.h
@@ -52,6 +52,7 @@ typedef struct lgsv_lgs_evt {
*/
MDS_DEST fr_dest;
NODE_ID fr_node_id;
+ char node_name[_POSIX_HOST_NAME_MAX];
MDS_SEND_PRIORITY_TYPE rcvd_prio; /* Priority of the recvd evt */
LGSV_LGS_EVT_TYPE evt_type;
union {
diff --git a/osaf/services/saf/logsv/lgs/lgs_fmt.cc
b/osaf/services/saf/logsv/lgs/lgs_fmt.cc
--- a/osaf/services/saf/logsv/lgs/lgs_fmt.cc
+++ b/osaf/services/saf/logsv/lgs/lgs_fmt.cc
@@ -23,6 +23,7 @@
#include <logtrace.h>
#include "lgs_fmt.h"
+#include "lgs.h"
/* Number of seconds per an hour/minute */
#define SECOND_PER_HOUR 3600L
@@ -253,6 +254,24 @@ static SaBoolT validateComToken(SaString
}
break;
+ case C_NETWORK_NAME_LETTER:
+ shiftOffset = static_cast<int>(C_NETWORK_NAME_OFFSET);
+ if ((*tokenFlags >> shiftOffset) & 1) {
+ tokenOk = SA_FALSE; /* Same token used two times */
+ } else {
+ *tokenFlags = (*tokenFlags | (1 << shiftOffset));
+ }
+ break;
+
+ case C_NODE_NAME_LETTER:
+ shiftOffset = static_cast<int>(C_NODE_NAME_OFFSET);
+ if ((*tokenFlags >> shiftOffset) & 1) {
+ tokenOk = SA_FALSE; /* Same token used two times */
+ } else {
+ *tokenFlags = (*tokenFlags | (1 << shiftOffset));
+ }
+ break;
+
default: /* Non valid token letter */
*fmtExpPtrOffset = 1;
tokenOk = SA_FALSE;
@@ -527,7 +546,10 @@ static int extractCommonField(char *dest
SaInt32T inputPos,
SaUint32T logRecordIdCounter,
const SaBoolT *twelveHourModeFlag,
- const struct tm *timeStampData, const
SaLogRecordT *logRecord, SaUint16T rec_size)
+ const struct tm *timeStampData,
+ const SaLogRecordT *logRecord,
+ SaUint16T rec_size,
+ char *node_name)
{
SaInt32T fieldSize;
size_t stringSize, i;
@@ -785,6 +807,16 @@ static int extractCommonField(char *dest
free(hex_string);
break;
+ case C_NETWORK_NAME_LETTER:
+ characters = snprintf(dest, dest_size, "%s",
lgs_get_networkname().c_str());
+ stringSize = characters;
+ break;
+
+ case C_NODE_NAME_LETTER:
+ characters = snprintf(dest, dest_size, "%s", node_name);
+ stringSize = characters;
+ break;
+
default:
characters = 0;
break;
@@ -1003,7 +1035,7 @@ static int extractNotificationField(char
fieldSize = (fieldSize > 2) ? (fieldSize - 2) : 2;
characters = snprintf(dest, dest_size,
"%#.*x", fieldSize,
-
logRecord->logHeader.ntfHdr.eventType);
+ logRecord->logHeader.ntfHdr.eventType);
}
*fmtExpPtrOffset = *fmtExpPtrOffset + fieldSizeOffset;
@@ -1229,8 +1261,14 @@ SaBoolT lgs_is_valid_format_expression(c
*
* @return int number of bytes written to dest
*/
-int lgs_format_log_record(SaLogRecordT *logRecord, const SaStringT
formatExpression, SaUint64T logFileSize,
- SaUint16T fixedLogRecordSize, size_t dest_size, char *dest, SaUint32T
logRecordIdCounter)
+int lgs_format_log_record(SaLogRecordT *logRecord,
+ const SaStringT formatExpression,
+ SaUint64T logFileSize,
+ SaUint16T fixedLogRecordSize,
+ size_t dest_size,
+ char *dest,
+ SaUint32T logRecordIdCounter,
+ char *node_name)
{
SaStringT fmtExpPtr = &formatExpression[0];
SaStringT fmtExpPtrSnabel = &formatExpression[1];
@@ -1272,7 +1310,11 @@ int lgs_format_log_record(SaLogRecordT *
&truncationLetterPos,
(SaInt32T)strlen(dest),
logRecordIdCounter,
- twelveHourModeFlag,
timeStampData, logRecord,rec_size);
+ twelveHourModeFlag,
+ timeStampData,
+ logRecord,
+ rec_size,
+ node_name);
break;
case NOTIFICATION_LOG_RECORD_FIELD_TYPE:
diff --git a/osaf/services/saf/logsv/lgs/lgs_fmt.h
b/osaf/services/saf/logsv/lgs/lgs_fmt.h
--- a/osaf/services/saf/logsv/lgs/lgs_fmt.h
+++ b/osaf/services/saf/logsv/lgs/lgs_fmt.h
@@ -54,7 +54,9 @@ typedef enum {
C_NOTIFICATION_CLASS_ID_SHIFT_OFFSET,
C_LR_TRUNCATION_INFO_SHIFT_OFFSET,
C_LR_STRING_BODY_SHIFT_OFFSET,
- C_LR_HEX_CHAR_BODY_SHIFT_OFFSET
+ C_LR_HEX_CHAR_BODY_SHIFT_OFFSET,
+ C_NETWORK_NAME_OFFSET,
+ C_NODE_NAME_OFFSET
} commonTokenShiftOffsetT;
typedef enum {
@@ -100,7 +102,9 @@ typedef enum {
C_NOTIFICATION_CLASS_ID_LETTER = 'c',
C_LR_TRUNCATION_INFO_LETTER = 'x',
C_LR_STRING_BODY_LETTER = 'b',
- C_LR_HEX_CHAR_BODY_LETTER = 'i'
+ C_LR_HEX_CHAR_BODY_LETTER = 'i',
+ C_NETWORK_NAME_LETTER = 'p',
+ C_NODE_NAME_LETTER = 'q'
} commonTokenLetterT;
typedef enum {
@@ -172,7 +176,15 @@ typedef enum {
} logStreamTypeT;
extern SaBoolT lgs_is_valid_format_expression(const SaStringT, logStreamTypeT,
SaBoolT *);
-extern int lgs_format_log_record(SaLogRecordT *, const SaStringT, SaUint64T
logFileSize, SaUint16T fixedLogRecordSize,
- size_t dest_size, char *dest, SaUint32T);
+extern int lgs_format_log_record(
+ SaLogRecordT *,
+ const SaStringT,
+ SaUint64T logFileSize,
+ SaUint16T fixedLogRecordSize,
+ size_t dest_size,
+ char *dest,
+ SaUint32T,
+ char *node_name
+ );
#endif
diff --git a/osaf/services/saf/logsv/lgs/lgs_imm_gcfg.cc
b/osaf/services/saf/logsv/lgs/lgs_imm_gcfg.cc
new file mode 100644
--- /dev/null
+++ b/osaf/services/saf/logsv/lgs/lgs_imm_gcfg.cc
@@ -0,0 +1,1082 @@
+/* -*- OpenSAF -*-
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#include "lgs_imm_gcfg.h"
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/socket.h>
+#include <fcntl.h>
+
+#include "saf_error.h"
+#include "logtrace.h"
+#include "saImmOi.h"
+#include "saImmOm.h"
+#include "immutil.h"
+#include "osaf_time.h"
+#include "osaf_poll.h"
+
+/*
+ * Implements an IMM applier for the OpensafConfig class.
+ * Used for detecting changes of opensafNetworkName attribute.
+ * The applier runs in its own thread
+ *
+ * API:
+ *
+ * int lgs_start_gcfg_applier()
+ * This function starts the applier in a separate thread
+ *
+ * int lgs_stop_gcfg_applier()
+ * This function stops the applier and free all resources
+ *
+ * char* lgs_get_networkname(char **name_str)
+ * Gives a pointer to a network name string
+ *
+ * TBC: Place a message in the mail box when network name is changed??
+ *
+ * USAGE:
+ *
+ * The applier shall be started on the ACTIVE server only.
+ * Start the applier when log server is started and when changing HA state
+ * to ACTIVE.
+ * Stop the applier when leaving ACTIVE state (quiesced and standby state
handler)
+ *
+ * NOTES:
+ * 1. Immutil cannot be used. The immutil wrapper profile is global snd not
+ * thread safe.
+ *
+ */
+
+/* Information given when starting thread
+ */
+typedef struct thread_info {
+ int socket;
+} lgs_thread_info_t;
+
+/**
+ * 'Private' global variables used for:
+ */
+static const SaImmClassNameT gcfg_class =
const_cast<SaImmClassNameT>("OpensafConfig");
+static const SaImmOiImplementerNameT applier_name =
const_cast<SaImmOiImplementerNameT>("@safLogService_appl");
+/* IMM handling */
+static SaVersionT immVersion = { 'A', 2, 11 };
+
+/* Network name handling */
+static char *network_name = NULL; /* Save pointer to current name */
+static pthread_mutex_t lgs_gcfg_applier_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+/* Inter thread communication (socket pair) */
+static const char* CMD_STOP = "s";
+static const char* CMD_START = "a";
+static const size_t CMD_LEN = 2;
+
+typedef enum {
+ AP_START,
+ AP_STOP
+} th_cmd_t;
+
+static int to_thread_fd = 0; /* Socket for communication with thread */
+
+/* Become applier cancellation handling */
+static bool cancel_flg = false; /* If true, cancel at next cancellation point
*/
+
+/* Thread */
+static pthread_t thread_id = 0;
+
+/* States for the applier thread. Stopping and starting the applier is handled
+ * differently dependent on the thread state
+ */
+typedef enum {
+ /* Thread not started */
+ TH_NOT_STARTED = 0,
+ /* Thread is started but has not yet entered the event handling poll
loop */
+ TH_STARTING,
+ /* Thread is fully started and running as applier */
+ TH_IS_APPLIER,
+ /* Thread is fully started but is not running as applier. In this state
+ * it can service commands e.g. start applier command but has never
+ * become an applier or have given up the applier role
+ */
+ TH_IDLE
+} th_state_t;
+
+static th_state_t th_state = TH_NOT_STARTED;
+
+extern struct ImmutilWrapperProfile immutilWrapperProfile;
+
+/******************************************************************************
+ * Outside applier thread
+
******************************************************************************/
+
+/*******************
+ * Utility functions
+ */
+
+static int start_applier_thread(lgs_thread_info_t *start_info);
+static void save_network_name(char* new_name);
+static void applier_finalize(SaImmOiHandleT imm_appl_hdl);
+static void *applier_thread(void *info_in);
+static int read_network_name();
+static bool th_do_cancel();
+
+static void send_command(th_cmd_t command)
+{
+ const char *cmd_ptr = NULL;
+ int rc = 0;
+
+ TRACE_ENTER();
+
+ switch (command) {
+ case AP_START:
+ cmd_ptr = CMD_START;
+ break;
+ case AP_STOP:
+ cmd_ptr = CMD_STOP;
+ break;
+ default:
+ LOG_ER("Unknown command %d", command);
+ osaf_abort(0);
+ }
+
+ while (1) {
+ rc = write(to_thread_fd, cmd_ptr, CMD_LEN);
+ if ((rc == -1) && ((errno == EINTR) || (errno == EAGAIN)))
+ /* Try again */
+ continue;
+ else
+ break;
+ }
+
+ if (rc == -1) {
+ LOG_ER("Write Fail %s", strerror(errno));
+ osaf_abort(0);
+ }
+
+ TRACE_LEAVE2("Command '%s', rc=%d", cmd_ptr, rc);
+}
+
+/**
+ * Activate cancellation of ongoing applier initialization.
+ * This function is used outside of thread to trig cancellation
+ * The corresponding th_cancel_check function is used inside thread as a
+ * "cancellation point".
+ */
+static void th_cancel_activate()
+{
+ osaf_mutex_lock_ordie(&lgs_gcfg_applier_mutex);
+ cancel_flg = true;
+ osaf_mutex_unlock_ordie(&lgs_gcfg_applier_mutex);
+}
+
+/**
+ * Set th_state protected by mutex. See corresponding th_state_get()
+ * @param th_state_set[in]
+ */
+static th_state_t inline th_state_get()
+{
+ th_state_t rc_th_state;
+
+ osaf_mutex_lock_ordie(&lgs_gcfg_applier_mutex);
+ rc_th_state = th_state;
+ osaf_mutex_unlock_ordie(&lgs_gcfg_applier_mutex);
+
+ return rc_th_state;
+}
+
+/**************************
+ * Network name handler API
+ */
+
+/**
+ * Start the applier
+ * Create applier thread (if needed) and start the applier.
+ * The thread initiates the IMM applier, reads opensafNetworkName and then
waits
+ * for callbacks (selection object) in a poll loop
+ *
+ */
+void lgs_start_gcfg_applier()
+{
+ static lgs_thread_info_t thread_input;
+ int sock_fd[2] = {0};
+ int rc = 0;
+ std::string tmp_name;
+
+ TRACE_ENTER();
+
+ switch (th_state_get()) {
+ case TH_NOT_STARTED:
+ TRACE("TH_NOT_STARTED");
+ /* Get the network name if not already fetched and saved */
+ tmp_name = lgs_get_networkname();
+ if (tmp_name.empty() == true) {
+ rc = read_network_name();
+ if (rc == -1) {
+ LOG_WA("read_network_name() Fail");
+ }
+ }
+
+ /* Create socket pair for communication with applier thread
+ * Non blocking
+ */
+ rc = socketpair(AF_UNIX, SOCK_STREAM, 0, sock_fd);
+ if (rc == -1) {
+ LOG_ER("socketpair Fail %s", strerror(errno));
+ osaf_abort(0);
+ }
+
+ fcntl(sock_fd[0], F_SETFL, O_NONBLOCK);
+ fcntl(sock_fd[1], F_SETFL, O_NONBLOCK);
+ to_thread_fd = sock_fd[0];
+ thread_input.socket = sock_fd[1];
+
+ /* Start the thread */
+ (void) start_applier_thread(&thread_input);
+ break;
+
+ case TH_IDLE:
+ TRACE("TH_IDLE");
+ /* Send applier start command to running thread */
+ send_command(AP_START);
+ break;
+
+ case TH_STARTING:
+ TRACE("TH_STARTING");
+ case TH_IS_APPLIER:
+ TRACE("TH_IS_APPLIER");
+ /* There is nothing to start we are already applier */
+ default:
+ TRACE("%s: Called in wrong state %d", __FUNCTION__, th_state);
+ break;
+ }
+
+ TRACE_LEAVE();
+}
+
+/**
+ * Stop the applier but only if an applier is started
+ *
+ */
+void lgs_stop_gcfg_applier()
+{
+ TRACE_ENTER();
+
+ switch (th_state_get()) {
+ case TH_IS_APPLIER:
+ TRACE("TH_IS_APPLIER");
+ send_command(AP_STOP);
+ break;
+
+ case TH_STARTING:
+ TRACE("TH_STARTING");
+ /* Cancel ongoing applier activation and send stop command to
+ * enter correct state
+ */
+ th_cancel_activate();
+ send_command(AP_STOP);
+ break;
+
+ case TH_NOT_STARTED:
+ TRACE("TH_NOT_STARTED");
+ case TH_IDLE:
+ TRACE("TH_IDLE");
+ /* Nothing to stop there is no active applier */
+ default:
+ TRACE("%s: Called in wrong state %d", __FUNCTION__, th_state);
+ }
+
+ TRACE_LEAVE();
+}
+
+/**
+ * Get the network name.
+ * If no network name exist a NULL pointer is returned
+ * Saved as a dynamic variable string. In parameter name_str will be set
+ * to point to the string.
+ * network_name. Saving and reading is done in different threads so
+ * must be protected by mutex. See also save_network_name()
+ *
+ * @param name_str[in]
+ * Memory for a string will be allocated and the pointer will be given
+ * to the calling function that has to free the memory.
+ *
+ * @return pointer to a network name string
+ */
+std::string lgs_get_networkname()
+{
+ std::string networkName;
+
+ TRACE_ENTER();
+
+ osaf_mutex_lock_ordie(&lgs_gcfg_applier_mutex);
+
+ /* Thread safe handling of return value */
+ if (network_name != NULL) {
+ networkName = network_name;
+ }
+
+ osaf_mutex_unlock_ordie(&lgs_gcfg_applier_mutex);
+
+ TRACE_LEAVE2("name_str \"%s\"", networkName.empty()? "<empty>":
networkName.c_str());
+
+ return networkName;
+}
+
+/******************************************************************************
+ * Used by applier thread only
+
******************************************************************************/
+
+/*********************************
+ * Applier callback functions
+ * See IMM AIS SaImmOiCallbacksT_2
+ * Executed in OI thread
+ */
+
+/**
+ * Save ccb info if OpensafConfig object is modified
+ *
+ */
+static SaAisErrorT ccbObjectModifyCallback(SaImmOiHandleT immOiHandle,
+ SaImmOiCcbIdT ccbId, const SaNameT *objectName,
+ const SaImmAttrModificationT_2 **attrMods)
+{
+ SaAisErrorT rc = SA_AIS_OK;
+ struct CcbUtilCcbData *ccbUtilCcbData;
+
+ TRACE_ENTER2("CCB ID %llu, '%s'", ccbId, objectName->value);
+
+ if ((ccbUtilCcbData = ccbutil_findCcbData(ccbId)) == NULL) {
+ if ((ccbUtilCcbData = ccbutil_getCcbData(ccbId)) == NULL) {
+ TRACE("Failed to get CCB object for %llu", ccbId);
+ rc = SA_AIS_ERR_NO_MEMORY;
+ goto done;
+ }
+ }
+
+ ccbutil_ccbAddModifyOperation(ccbUtilCcbData, objectName, attrMods);
+
+done:
+ TRACE_LEAVE();
+ return rc;
+}
+
+/**
+ * Cleanup by deleting saved ccb info if aborted
+ *
+ */
+static void ccbAbortCallback(SaImmOiHandleT immOiHandle, SaImmOiCcbIdT ccbId)
+{
+ struct CcbUtilCcbData *ccbUtilCcbData;
+
+ TRACE_ENTER2("CCB ID %llu", ccbId);
+
+ if ((ccbUtilCcbData = ccbutil_findCcbData(ccbId)) != NULL)
+ ccbutil_deleteCcbData(ccbUtilCcbData);
+ else
+ TRACE("Failed to find CCB object for %llu", ccbId);
+
+ TRACE_LEAVE();
+}
+
+/**
+ * Check if network name has been modified and save new network name
+ *
+ * We are an applier for the OpensafConfig class. Only one object of this class
+ * can exist so we don't have iterate over objects.
+ * We only save modifications so the operation type must be modify.
+ * We iterate over attributes even if there is only one configuration attribute
+ * but more attributes may be added in the future.
+ *
+ */
+static void ccbApplyCallback(SaImmOiHandleT immOiHandle, SaImmOiCcbIdT ccbId)
+{
+ struct CcbUtilCcbData *ccbUtilCcbData;
+ struct CcbUtilOperationData *opdata;
+ const SaImmAttrModificationT_2 *attrMod;
+ char *value_str = NULL;
+ int i = 0;
+
+ TRACE_ENTER2("CCB ID %llu", ccbId);
+
+ /* Verify the ccb */
+ if ((ccbUtilCcbData = ccbutil_findCcbData(ccbId)) == NULL) {
+ TRACE("Failed to find CCB object for %llu", ccbId);
+ goto done;
+ }
+
+ /* We don't need to loop since the only possible opereation is MODIFY
+ * and the only possible class is OpensafConfig class
+ */
+ opdata = ccbUtilCcbData->operationListHead;
+ if (opdata->operationType != CCBUTIL_MODIFY) {
+ TRACE("Not a modify operation");
+ goto done;
+ }
+
+ if (strncmp(reinterpret_cast<char *>(opdata->objectName.value),
+ "opensafConfigId", sizeof("opensafConfigId") - 1) != 0) {
+ TRACE("Object \"%s\" not a OpensafConfig object",
+ reinterpret_cast<char *>(opdata->objectName.value));
+ goto done;
+ }
+
+ /* Read value in opensafNetworkName
+ * Note: This is implemented as a loop in case more attributes are
+ * added in the class in the future. For now the only
+ * attribute of interest here is opensafNetworkName
+ */
+ TRACE("Read value in attributes");
+ i = 0;
+ attrMod = opdata->param.modify.attrMods[i];
+ for (i = 1; attrMod != NULL; i++) {
+ const SaImmAttrValuesT_2 *attribute = &attrMod->modAttr;
+ TRACE("Found attribute \"%s\"", attribute->attrName);
+ if (strcmp(attribute->attrName, "opensafNetworkName") == 0) {
+ /* Get the value for opensafNetworkName */
+ void *value = NULL;
+ if (attribute->attrValuesNumber != 0)
+ value = attribute->attrValues[0];
+
+ if (value == NULL) {
+ TRACE("Value is NULL");
+ save_network_name(value_str);
+ goto done;
+ }
+
+ value_str = *(static_cast<char **>(value));
+ TRACE("%s='%s'", attribute->attrName, value_str);
+
+ /*
+ * Save the new network_name
+ */
+ save_network_name(value_str);
+ } else {
+ /* Not opensafNetworkName */
+ TRACE("Found attribute %s", attribute->attrName);
+ }
+
+ attrMod = opdata->param.modify.attrMods[i];
+ }
+
+done:
+ if (ccbUtilCcbData != NULL)
+ ccbutil_deleteCcbData(ccbUtilCcbData);
+
+ TRACE_LEAVE();
+}
+
+/**
+ * An object of OpensafConfig class is created. We don't have to do anything
+ *
+ */
+static SaAisErrorT ccbCreateCallback(SaImmOiHandleT immOiHandle,
+ SaImmOiCcbIdT ccbId, const SaImmClassNameT className,
+ const SaNameT *parentName, const SaImmAttrValuesT_2 **attr)
+{
+ TRACE_ENTER();
+ TRACE_LEAVE();
+ return SA_AIS_OK;
+}
+
+/**
+ * An object of OpensafConfig class is deleted. We don't have to do anything
+ *
+ */
+static SaAisErrorT ccbDeleteCallback(SaImmOiHandleT immOiHandle,
+ SaImmOiCcbIdT ccbId, const SaNameT *objectName)
+{
+ TRACE_ENTER();
+ TRACE_LEAVE();
+ return SA_AIS_OK;
+}
+
+/* Callback function list
+ * We need:
+ * Modify for saving modify ccb
+ * Apply for knowing that the modification has been applied
+ * Abort for removing saved ccb in case of an abortion of ccb
+ */
+static const SaImmOiCallbacksT_2 callbacks = {
+ .saImmOiAdminOperationCallback = NULL,
+ .saImmOiCcbAbortCallback = ccbAbortCallback,
+ .saImmOiCcbApplyCallback = ccbApplyCallback,
+ .saImmOiCcbCompletedCallback = NULL,
+ .saImmOiCcbObjectCreateCallback = ccbCreateCallback,
+ .saImmOiCcbObjectDeleteCallback = ccbDeleteCallback,
+ .saImmOiCcbObjectModifyCallback = ccbObjectModifyCallback,
+ .saImmOiRtAttrUpdateCallback = NULL
+};
+
+
+/***************************************
+ * Internal utility function definitions
+ */
+
+/**
+ * Save a new network name
+ * Saved as a dynamic variable string pointed to by 'private' global pointer
+ * network_name. Saving and reading is done in different threads so
+ * must be protected by mutex. See also lgs_get_networkname
+ *
+ * @param new_name[in]
+ */
+static void save_network_name(char* new_name)
+{
+ uint32_t name_len = 0;
+
+ TRACE_ENTER2("\"%s\"", new_name);
+
+ osaf_mutex_lock_ordie(&lgs_gcfg_applier_mutex);
+
+ /* Delete old name */
+ if (network_name != NULL)
+ free(network_name);
+
+ /* Save new name */
+ if (new_name == NULL) {
+ network_name = NULL;
+ } else {
+ name_len = strlen(new_name) + 1;
+ network_name = static_cast<char *>(calloc(1, name_len));
+ if (network_name == NULL) {
+ LOG_ER("%s: calloc Fail", __FUNCTION__);
+ osaf_abort(0);
+ }
+
+ strcpy(network_name, new_name);
+ }
+
+ osaf_mutex_unlock_ordie(&lgs_gcfg_applier_mutex);
+
+ TRACE_LEAVE();
+}
+
+/**
+ * Read network name from the OpensafConfig object
+ * - Create an Object manager
+ * - Search for and get opensafNetworkName value
+ * - Allocate memory for and save the value. Save pointer in network_name
+ *
+ * If no value is found network_name will be NULL
+ *
+ * @return -1 on error
+ */
+static int read_network_name()
+{
+ SaAisErrorT ais_rc = SA_AIS_OK;
+ SaImmHandleT om_handle = 0;
+ char *tmp_name_str = NULL;
+ int rc = 0;
+ /* Setup value get parameters */
+ SaNameT object_name;
+ SaImmAttrValuesT_2 **attributes;
+ SaImmAttrValuesT_2 *attribute;
+ void *value = NULL;
+ /* Setup search initialize parameters */
+ SaImmSearchHandleT searchHandle;
+ SaImmSearchParametersT_2 searchParam;
+ searchParam.searchOneAttr.attrName = const_cast<SaImmAttrNameT>(
+ "opensafNetworkName");
+ searchParam.searchOneAttr.attrValueType = SA_IMM_ATTR_SASTRINGT;
+ searchParam.searchOneAttr.attrValue = NULL;
+
+ SaImmAttrNameT attributeNames[2] = {
+ const_cast<SaImmAttrNameT>("opensafNetworkName"),
+ NULL
+ };
+
+ TRACE_ENTER();
+
+ /*
+ * Initialize an IMM object manager
+ */
+ // Wait up to 500ms
+ immutilWrapperProfile.errorsAreFatal = 0;
+ immutilWrapperProfile.nTries = 500;
+ immutilWrapperProfile.retryInterval = 1000;
+
+ ais_rc = immutil_saImmOmInitialize(&om_handle, NULL, &immVersion);
+ if (ais_rc != SA_AIS_OK) {
+ TRACE("immutil_saImmOmInitialize FAIL %s", saf_error(ais_rc));
+ rc = -1;
+ goto done;
+ }
+
+ /*
+ * Search for objects with attribute opensafNetworkName
+ */
+ /* Find the opensafNetworkName attribute in the OpensafConfig object and
+ * get its value
+ */
+ ais_rc = immutil_saImmOmSearchInitialize_2(
+ om_handle,
+ NULL,
+ SA_IMM_SUBTREE,
+ SA_IMM_SEARCH_ONE_ATTR | SA_IMM_SEARCH_GET_SOME_ATTR,
+ &searchParam,
+ attributeNames,
+ &searchHandle
+ );
+ if (ais_rc != SA_AIS_OK) {
+ TRACE("immutil_saImmOmSearchInitialize_2 FAIL %s",
saf_error(ais_rc));
+ rc = -1;
+ goto done;
+ }
+
+ /*
+ * Get the value for the searched attribute
+ */
+ ais_rc = immutil_saImmOmSearchNext_2(searchHandle, &object_name,
&attributes);
+ if (ais_rc != SA_AIS_OK) {
+ TRACE("immutil_saImmOmSearchNext_2 FAIL %s", saf_error(ais_rc));
+ rc = -1;
+ goto done;
+ }
+
+ /*
+ * Save the network name or set to NULL if no name is found
+ * Note: Saving network_name must be thread safe
+ */
+ attribute = attributes[0];
+ if (attribute->attrValuesNumber != 0) {
+ value = attribute->attrValues[0];
+ tmp_name_str = *(static_cast<char **>(value));
+ } else {
+ /* Set network name to an empty string if the attribute value
+ * is "empty"
+ */
+ tmp_name_str = const_cast<char *>("");
+ }
+
+ save_network_name(tmp_name_str);
+
+done:
+ /* Finalize search */
+ ais_rc = immutil_saImmOmFinalize(om_handle);
+ if ((ais_rc != SA_AIS_OK) && (ais_rc != SA_AIS_ERR_BAD_HANDLE)) {
+ /* BAD HANDLE is not a fault here since finalize is called
+ * also if initialize failed
+ */
+ TRACE("immutil_saImmOmFinalize FAIL %s", saf_error(ais_rc));
+ rc = -1;
+ }
+
+ TRACE_LEAVE2("rc = %d", rc);
+ return rc;
+}
+
+/**
+ * Initialize IMM API and get selection object
+ * The following API sequence is used:
+ * - Finalize if a handle exist
+ * - Initialize (get imm OI handle)
+ * - Get selection object
+ *
+ * Note1:TRY AGAIN loops time out after "max_waiting_time..." which can be
+ * up to 60 sec.
+ *
+ * Note2: Init can be canclled. See th_cancel_activate()
+ * Cancelling is done when reaching a cancellation point defined by
+ * th_cancel_OIinit()
+ *
+ * Is 60 sec timeout for initialize really needed?
+ *
+ * @param imm_appl_hdl[out]
+ * @param imm_appl_selobj[out]
+ *
+ * @return -1 on error
+ */
+/**
+ *
+ * @param imm_appl_hdl
+ * @param imm_appl_selobj
+ * @param nfds
+ * @return
+ */
+static int applier_init(SaImmOiHandleT *imm_appl_hdl,
+ SaSelectionObjectT *imm_appl_selobj)
+{
+ SaAisErrorT ais_rc = SA_AIS_OK;
+ int rc = 0;
+
+ TRACE_ENTER();
+
+ if (th_do_cancel()) {
+ TRACE("Canceled at 1");
+ /* Cancellation point no error */
+ goto done;
+ }
+
+ /* Finalize applier OI handle if needed */
+ applier_finalize(*imm_appl_hdl);
+
+ if (th_do_cancel()) {
+ TRACE("Canceled at 2");
+ /* Cancellation point no error */
+ goto done;
+ }
+
+ // Wait up to 500ms
+ immutilWrapperProfile.errorsAreFatal = 0;
+ immutilWrapperProfile.nTries = 500;
+ immutilWrapperProfile.retryInterval = 1000;
+
+ /* Initialize OI for applier and get OI handle */
+ ais_rc = immutil_saImmOiInitialize_2(imm_appl_hdl, &callbacks,
&immVersion);
+ if (ais_rc != SA_AIS_OK) {
+ LOG_WA("immutil_saImmOiInitialize_2 Failed %s",
saf_error(ais_rc));
+ rc = -1;
+ goto done;
+ }
+
+ if (th_do_cancel()) {
+ TRACE("Canceled at 3");
+ /* Cancellation point no error */
+ applier_finalize(*imm_appl_hdl);
+ goto done;
+ }
+
+ /* Get selection object for event handling */
+ ais_rc = immutil_saImmOiSelectionObjectGet(*imm_appl_hdl,
imm_appl_selobj);
+ if (ais_rc != SA_AIS_OK) {
+ LOG_WA("immutil_saImmOiSelectionObjectGet Failed %s",
saf_error(ais_rc));
+ applier_finalize(*imm_appl_hdl);
+ imm_appl_hdl = 0;
+ rc = -1;
+ goto done;
+ }
+
+ if (th_do_cancel()) {
+ TRACE("Canceled at 3");
+ /* Cancellation point no error */
+ applier_finalize(*imm_appl_hdl);
+ goto done;
+ }
+
+done:
+ TRACE_LEAVE2("rc = %d", rc);
+ return rc;
+}
+
+/**
+ * Become an IMM applier for OpensafConfig class
+ * - Register applier name
+ * - Become class implementer
+ *
+ * Note1: TRY AGAIN loops time out after "max_waiting_time..." which can be
+ * up to 60 sec.
+ *
+ * Note2: Must be done after lgs_imma_init_handle()
+ *
+ * @return -1 on error
+ */
+static int applier_set_name_class(SaImmOiHandleT imm_appl_hdl)
+{
+ SaAisErrorT ais_rc = SA_AIS_OK;
+ int rc = 0;
+
+ TRACE_ENTER();
+
+ if (th_do_cancel()) {
+ TRACE("Canceled at 1");
+ /* Cancellation point no error */
+ applier_finalize(imm_appl_hdl);
+ goto done;
+ }
+
+ /* Become applier */
+ immutilWrapperProfile.errorsAreFatal = 0;
+ immutilWrapperProfile.nTries = 500;
+ immutilWrapperProfile.retryInterval = 1000;
+
+ ais_rc = immutil_saImmOiImplementerSet(imm_appl_hdl, applier_name);
+ if (ais_rc != SA_AIS_OK) {
+ LOG_WA("immutil_saImmOiImplementerSet Failed %s",
saf_error(ais_rc));
+ applier_finalize(imm_appl_hdl);
+ rc = -1;
+ goto done;
+ }
+
+ if (th_do_cancel()) {
+ TRACE("Canceled at 2");
+ /* Cancellation point no error */
+ applier_finalize(imm_appl_hdl);
+ goto done;
+ }
+
+ /* Become class implementer (applier) for the OpensafConfig class */
+ ais_rc = immutil_saImmOiClassImplementerSet(imm_appl_hdl, gcfg_class);
+ if (ais_rc != SA_AIS_OK) {
+ LOG_WA("immutil_saImmOiClassImplementerSet Failed %s",
saf_error(ais_rc));
+ applier_finalize(imm_appl_hdl);
+ rc = -1;
+ goto done;
+ }
+
+ if (th_do_cancel()) {
+ TRACE("Canceled at 3");
+ /* Cancellation point no error */
+ applier_finalize(imm_appl_hdl);
+ goto done;
+ }
+
+done:
+ TRACE_LEAVE();
+ return rc;
+}
+
+/**
+ * Finalize the IMM applier
+ *
+ * @param imm_appl_hdl[in]
+ */
+static void applier_finalize(SaImmOiHandleT imm_appl_hdl)
+{
+ SaAisErrorT ais_rc = SA_AIS_OK;
+
+ TRACE_ENTER();
+
+ /* Finalize applier OI handle if needed */
+ if (imm_appl_hdl != 0) {
+ /* We have a handle to finalize */
+ TRACE("saImmOiFinalize");
+
+ immutilWrapperProfile.errorsAreFatal = 0;
+ immutilWrapperProfile.nTries = 500;
+ immutilWrapperProfile.retryInterval = 1000;
+
+ ais_rc = immutil_saImmOiFinalize(imm_appl_hdl);
+ if (ais_rc != SA_AIS_OK) {
+ TRACE("immutil_saImmOiFinalize Failed %s",
saf_error(ais_rc));
+ }
+
+ imm_appl_hdl = 0;
+ } else {
+ TRACE("Finalize not needed");
+ }
+
+ TRACE_LEAVE();
+}
+
+
+/*******************************
+ * 'Private' variables used for:
+ */
+
+/**
+ * Check if applier init cancellation is activated
+ * Return value of cancellation flag and reset flag
+ *
+ * @return true if cancellation is active
+ */
+static bool th_do_cancel()
+{
+ bool rc = false;
+ osaf_mutex_lock_ordie(&lgs_gcfg_applier_mutex);
+ rc = cancel_flg;
+ cancel_flg = false;
+ osaf_mutex_unlock_ordie(&lgs_gcfg_applier_mutex);
+ return rc;
+}
+
+/****************************
+ * Applier event handler main
+ *
+ * The applier runs in a separate thread. The thread uses a poll loop to handle
+ * IMM events and communication events. Communication is handled using a socket
+ * pair.
+ * Possible communication events:
+ * - Start applier
+ * Set implementer name and become class-applier
+ * - Stop applier
+ * Do saImmOiImplementerClear()
+ *
+ * The handler also needs a cancellation mechanism. This mechanism does not
+ * cancel the thread but an ongoing applier initiation must be possible to
+ * cancel. This means that if setting of implementer name or class is ongoing
+ * it will be stopped and saImmOiImplementerClear() is called
+ */
+
+/**
+ * Start the applier thread if not already started
+ *
+ * @param start_info[in] See lgs_thread_info_t
+ * @return -1 on error
+ */
+static int start_applier_thread(lgs_thread_info_t *start_info)
+{
+ int rc = 0;
+ void *thr_arg = start_info;
+
+ TRACE_ENTER();
+
+ if (th_state == TH_NOT_STARTED) {
+ rc = pthread_create(&thread_id, NULL, applier_thread, thr_arg);
+ if (rc != 0) {
+ LOG_ER("pthread_create Fail %d", rc);
+ osaf_abort(0);
+ }
+ } else {
+ TRACE("Thread already started");
+ rc = -1;
+ }
+
+ TRACE_LEAVE();
+ return rc;
+}
+
+/**
+ * Set th_state protected by mutex. See corresponding th_state_get()
+ * @param th_state_set[in]
+ */
+static void inline th_state_set(th_state_t th_state_set)
+{
+ osaf_mutex_lock_ordie(&lgs_gcfg_applier_mutex);
+ th_state = th_state_set;
+ osaf_mutex_unlock_ordie(&lgs_gcfg_applier_mutex);
+}
+
+/**
+ * The applier thread
+ * @param info_in[in] See lgs_thread_info_t
+ * @return -
+ */
+static void *applier_thread(void *info_in)
+{
+ /* Event handling
+ * Note:
+ * IMM selection object can only be part of polling when IMM OI is
+ * initialized. If IMM is finalized the selection object is not valid.
+ * This is handled by placing IMM selection fd as last element in fds
+ * vector and decrease and decrease nfds when IMM is finalized.
+ */
+ enum {
+ FDA_COM = 0, /* Communication events */
+ FDA_IMM /* IMM events */
+ };
+
+ static struct pollfd fds[2];
+ static nfds_t nfds = 1; /* We have no IMM selection object yet */
+ int rc = 0;
+ SaAisErrorT ais_rc = SA_AIS_OK;
+ static SaImmOiHandleT imm_appl_hdl = 0;
+ static SaSelectionObjectT imm_appl_selobj = 0;
+
+ TRACE_ENTER2("Thread will never return");
+ lgs_thread_info_t *start_info = static_cast<lgs_thread_info_t
*>(info_in);
+ int com_fd = start_info->socket;
+
+ /* Loop needed for new intialize if imm_appl_hdl becomes invalid or the
+ * applier is restarted
+ */
+ while (1) {
+ /* Initiate applier */
+ th_state_set(TH_STARTING);
+
+ rc = applier_init(&imm_appl_hdl, &imm_appl_selobj);
+ if (rc == -1) {
+ /* Some error handling */
+ TRACE("applier_init Fail");
+ osaf_abort(0);
+ }
+
+ nfds = FDA_IMM + 1; /* IMM selection object is valid */
+
+ rc = applier_set_name_class(imm_appl_hdl);
+ if (rc == -1) {
+ /* Some error handling */
+ LOG_ER("applier_set_name_class Fail");
+ osaf_abort(0);
+ }
+
+ th_state_set(TH_IS_APPLIER);
+
+ /* Event handling */
+ fds[FDA_IMM].fd = imm_appl_selobj;
+ fds[FDA_IMM].events = POLLIN;
+ fds[FDA_COM].fd = com_fd;
+ fds[FDA_COM].events = POLLIN;
+
+ /* If no network name is saved, read the network name from the
+ * OpensafConfig class and save it
+ */
+ std::string tmp_networkname;
+ tmp_networkname = lgs_get_networkname();
+ if (tmp_networkname.empty() == true) {
+ rc = read_network_name();
+ if (rc == -1) {
+ LOG_WA("read_network_name() Fail");
+ }
+ }
+
+ /*** Event handling loop ***/
+ while(1) {
+
+ (void) osaf_poll(fds, nfds, -1);
+
+ if (fds[FDA_IMM].revents & POLLIN) {
+ TRACE("%s: IMM event", __FUNCTION__);
+ ais_rc = saImmOiDispatch(imm_appl_hdl,
SA_DISPATCH_ALL);
+ if (ais_rc == SA_AIS_ERR_BAD_HANDLE) {
+ /* Handle is lost. We must initialize
again */
+ th_state_set(TH_STARTING);
+ break;
+ }
+ }
+
+ if (fds[FDA_COM].revents & POLLIN) {
+ TRACE("%s: COM event", __FUNCTION__);
+ /* Handle start and stop requests */
+ char cmd_str[256] = {0};
+ while (1) {
+ rc = read(com_fd, cmd_str, 256);
+ if ((rc == -1) && ((errno == EINTR) ||
+ (errno == EAGAIN))) {
+ /* Try again */
+ continue;
+ } else break;
+ }
+
+ if (rc == -1) {
+ LOG_ER("write Fail %s",
strerror(errno));
+ osaf_abort(0);
+ }
+
+ TRACE("Read command '%s'", cmd_str);
+
+ if (!strcmp(cmd_str, CMD_STOP)) {
+ TRACE("STOP received");
+ /* Reset cancel flag */
+ th_do_cancel();
+ /* Give up applier */
+ applier_finalize(imm_appl_hdl);
+ /* The IMM selection object is no longer
+ * valid so we have to stop polling IMM
+ */
+ nfds -= 1;
+ th_state_set(TH_IDLE);
+ } else if (!strcmp(cmd_str, CMD_START)) {
+ TRACE("START received");
+ /* Leave event loop for outer restart
+ * loop
+ */
+ break;
+ }
+ }
+ } /* END Event handling loop */
+ } /* END Restart loop */
+}
diff --git a/osaf/services/saf/logsv/lgs/lgs_imm_gcfg.h
b/osaf/services/saf/logsv/lgs/lgs_imm_gcfg.h
new file mode 100644
--- /dev/null
+++ b/osaf/services/saf/logsv/lgs/lgs_imm_gcfg.h
@@ -0,0 +1,28 @@
+/* -*- OpenSAF -*-
+ *
+ * (C) Copyright 2016 The OpenSAF Foundation
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are licensed
+ * under the GNU Lesser General Public License Version 2.1, February 1999.
+ * The complete license can be accessed from the following location:
+ * http://opensource.org/licenses/lgpl-license.php
+ * See the Copying file included with the OpenSAF distribution for full
+ * licensing terms.
+ *
+ * Author(s): Ericsson AB
+ *
+ */
+
+#ifndef LGS_IMM_CLM_H
+#define LGS_IMM_CLM_H
+
+#include <string>
+
+void lgs_start_gcfg_applier();
+void lgs_stop_gcfg_applier();
+std::string lgs_get_networkname();
+
+#endif /* LGS_IMM_CLM_H */
+
diff --git a/osaf/services/saf/logsv/lgs/lgs_main.cc
b/osaf/services/saf/logsv/lgs/lgs_main.cc
--- a/osaf/services/saf/logsv/lgs/lgs_main.cc
+++ b/osaf/services/saf/logsv/lgs/lgs_main.cc
@@ -392,6 +392,7 @@ static uint32_t log_initialize(void)
/* Become OI. We will be blocked here until done */
lgs_imm_impl_set(lgs_cb->immOiHandle);
conf_runtime_obj_create(lgs_cb->immOiHandle);
+ lgs_start_gcfg_applier();
/* Create streams that has configuration objects and become
* class implementer for the SaLogStreamConfig class
diff --git a/osaf/services/saf/logsv/lgs/lgs_mbcsv.cc
b/osaf/services/saf/logsv/lgs/lgs_mbcsv.cc
--- a/osaf/services/saf/logsv/lgs/lgs_mbcsv.cc
+++ b/osaf/services/saf/logsv/lgs/lgs_mbcsv.cc
@@ -780,25 +780,29 @@ static uint32_t ckpt_encode_async_update
TRACE_ENTER();
/* Set reo_hdl from callback arg to ckpt_rec */
if (lgs_is_peer_v5()) {
- data_v5 = reinterpret_cast<lgsv_ckpt_msg_v5_t
*>((long)cbk_arg->info.encode.io_reo_hdl);
+ data_v5 = reinterpret_cast<lgsv_ckpt_msg_v5_t *>(
+ static_cast<long>( cbk_arg->info.encode.io_reo_hdl));
vdata = data_v5;
edp_function = edp_ed_ckpt_msg_v5;
} else if (lgs_is_peer_v4()) {
- data_v3 = reinterpret_cast<lgsv_ckpt_msg_v3_t
*>((long)cbk_arg->info.encode.io_reo_hdl);
+ data_v3 = reinterpret_cast<lgsv_ckpt_msg_v3_t *>(
+ static_cast<long>(cbk_arg->info.encode.io_reo_hdl));
vdata = data_v3;
edp_function = edp_ed_ckpt_msg_v3;
} else if (lgs_is_peer_v2()) {
- data_v2 = reinterpret_cast<lgsv_ckpt_msg_v2_t
*>((long)cbk_arg->info.encode.io_reo_hdl);
+ data_v2 = reinterpret_cast<lgsv_ckpt_msg_v2_t *>(
+ static_cast<long>(cbk_arg->info.encode.io_reo_hdl));
vdata = data_v2;
edp_function = edp_ed_ckpt_msg_v2;
} else {
- data_v1 = reinterpret_cast<lgsv_ckpt_msg_v1_t
*>((long)cbk_arg->info.encode.io_reo_hdl);
+ data_v1 = reinterpret_cast<lgsv_ckpt_msg_v1_t *>(
+ static_cast<long>(cbk_arg->info.encode.io_reo_hdl));
vdata = data_v1;
edp_function = edp_ed_ckpt_msg_v1;
}
if (vdata == NULL) {
- TRACE(" data == NULL, FAILED");
+ TRACE("data == NULL, FAILED");
TRACE_LEAVE();
return NCSCC_RC_FAILURE;
}
@@ -1136,11 +1140,11 @@ static uint32_t ckpt_decode_async_update
lgsv_ckpt_msg_v5_t *ckpt_msg_v5 = &msg_v5;
void *ckpt_msg;
lgsv_ckpt_header_t hdr, *hdr_ptr = &hdr;
-
+
/* Same in all versions */
lgs_ckpt_initialize_msg_t *reg_rec;
lgs_ckpt_stream_open_t *stream_open;
-
+
TRACE_ENTER();
/* Decode the message header */
@@ -1444,10 +1448,10 @@ static uint32_t process_ckpt_data(lgs_cb
lgsv_ckpt_msg_v5_t *data_v5;
if ((!cb) || (data == NULL)) {
- TRACE("%s - FAILED: (!cb) || (data == NULL)",__FUNCTION__);
+ TRACE("%s - FAILED: (!cb) || (data == NULL)", __FUNCTION__);
return (rc = NCSCC_RC_FAILURE);
}
-
+
if (lgs_is_peer_v5()) {
data_v5 = static_cast<lgsv_ckpt_msg_v5_t *>(data);
lgsv_ckpt_msg_type = data_v5->header.ckpt_rec_type;
@@ -1615,10 +1619,19 @@ static void insert_localmsg_in_stream(lo
goto done;
}
+ /* Use local host name as node name for missing record */
+ char host_name[_POSIX_HOST_NAME_MAX];
+ memset(host_name, 0, _POSIX_HOST_NAME_MAX);
+ /* TODO: should use gethostname or fopen(PKGSYSCONFDIR "/node_name",
"r") */
+ if (gethostname(host_name, _POSIX_HOST_NAME_MAX) == -1) {
+ TRACE("gethostname failed. Use default SC-2");
+ strcpy(host_name, "SC-2");
+ }
+
/* Format the log record */
if ((n = lgs_format_log_record(&log_record, stream->logFileFormat,
stream->maxLogFileSize,
- stream->fixedLogRecordSize, buf_size, logOutputString,
- LOG_REC_ID)) == 0) {
+ stream->fixedLogRecordSize, buf_size,
logOutputString,
+ LOG_REC_ID, host_name)) == 0) {
LOG_ER("%s - Could not format internal log
record",__FUNCTION__);
goto done;
}
@@ -1640,10 +1653,15 @@ static void insert_localmsg_in_stream(lo
}
/* Format the log record */
- if ((n = lgs_format_log_record(&log_record,
stream->logFileFormat, stream->maxLogFileSize,
-
stream->fixedLogRecordSize, buf_size, logOutputString,
- LOG_REC_ID)) == 0) {
- LOG_ER("%s - Could not format internal log
record",__FUNCTION__);
+ if ((n = lgs_format_log_record(
+ &log_record,
+ stream->logFileFormat,
+ stream->maxLogFileSize,
+ stream->fixedLogRecordSize,
+ buf_size,
+ logOutputString,
+ LOG_REC_ID, host_name)) == 0) {
+ LOG_ER("%s - Could not format internal log
record", __FUNCTION__);
}
}
@@ -1771,7 +1789,9 @@ static uint32_t ckpt_proc_log_write(lgs_
lgs_free_edu_mem(logRecord);
logRecord = NULL;
}
+
lgs_free_edu_mem(logFileCurrent);
+
TRACE_LEAVE();
/*
If rc == -2, means something happens in log handler thread
diff --git a/osaf/services/saf/logsv/lgs/lgs_mbcsv.h
b/osaf/services/saf/logsv/lgs/lgs_mbcsv.h
--- a/osaf/services/saf/logsv/lgs/lgs_mbcsv.h
+++ b/osaf/services/saf/logsv/lgs/lgs_mbcsv.h
@@ -35,6 +35,7 @@
#define LGS_MBCSV_VERSION_2 2
#define LGS_MBCSV_VERSION_4 4
#define LGS_MBCSV_VERSION_5 5
+
/* Current version */
#define LGS_MBCSV_VERSION 5
#define LGS_MBCSV_VERSION_MIN 1
diff --git a/osaf/services/saf/logsv/lgs/lgs_mds.cc
b/osaf/services/saf/logsv/lgs/lgs_mds.cc
--- a/osaf/services/saf/logsv/lgs/lgs_mds.cc
+++ b/osaf/services/saf/logsv/lgs/lgs_mds.cc
@@ -283,7 +283,7 @@ static uint32_t dec_lstr_close_msg(NCS_U
Notes : None.
******************************************************************************/
-static uint32_t dec_write_log_async_msg(NCS_UBAID *uba, lgsv_msg_t *msg)
+static uint32_t dec_write_log_async_msg(NCS_UBAID *uba, lgsv_msg_t *msg,
NODE_ID nodeId)
{
uint8_t *p8;
uint32_t rc = NCSCC_RC_SUCCESS;
@@ -796,6 +796,7 @@ static uint32_t mds_dec(struct ncsmds_ca
uint8_t *p8;
lgsv_lgs_evt_t *evt = NULL;
NCS_UBAID *uba = info->info.dec.io_uba;
+ NODE_ID node_id = info->info.dec.i_node_id;
uint8_t local_data[20];
uint32_t rc = NCSCC_RC_SUCCESS;
@@ -841,7 +842,7 @@ static uint32_t mds_dec(struct ncsmds_ca
rc = dec_lstr_close_msg(uba, &evt->info.msg);
break;
case LGSV_WRITE_LOG_ASYNC_REQ:
- rc = dec_write_log_async_msg(uba, &evt->info.msg);
+ rc = dec_write_log_async_msg(uba, &evt->info.msg,
node_id);
break;
default:
break;
@@ -979,14 +980,18 @@ static uint32_t mds_rcv(struct ncsmds_ca
/* Wait if the mailbox is being reinitialized in the main thread.
*/
osaf_mutex_lock_ordie(&lgs_mbox_init_mutex);
-
+
evt->evt_type = LGSV_LGS_LGSV_MSG;
evt->cb_hdl = (uint32_t)mds_info->i_yr_svc_hdl;
evt->fr_node_id = mds_info->info.receive.i_node_id;
evt->fr_dest = mds_info->info.receive.i_fr_dest;
evt->rcvd_prio = mds_info->info.receive.i_priority;
evt->mds_ctxt = mds_info->info.receive.i_msg_ctxt;
-
+
+ /* Get node name from MDS */
+ memset(evt->node_name, 0, _POSIX_HOST_NAME_MAX);
+ strncpy(evt->node_name, mds_info->info.receive.i_node_name,
_POSIX_HOST_NAME_MAX);
+
/* for all msg types but WRITEs, sample curr time and store in msg */
if ((type == LGSV_INITIALIZE_REQ) || (type == LGSV_STREAM_OPEN_REQ)) {
osaf_clock_gettime(CLOCK_MONOTONIC, &evt->entered_at);
diff --git a/tests/logsv/logtest.c b/tests/logsv/logtest.c
--- a/tests/logsv/logtest.c
+++ b/tests/logsv/logtest.c
@@ -44,6 +44,13 @@ SaNameT alarmStreamName =
.length = sizeof(SA_LOG_STREAM_ALARM)
};
+SaNameT globalConfig =
+{
+ .value = LOGTST_IMM_LOG_GCFG,
+ .length = sizeof(LOGTST_IMM_LOG_GCFG)
+};
+
+
SaNameT notificationStreamName =
{
.value = SA_LOG_STREAM_NOTIFICATION,
diff --git a/tests/logsv/logtest.h b/tests/logsv/logtest.h
--- a/tests/logsv/logtest.h
+++ b/tests/logsv/logtest.h
@@ -49,10 +49,12 @@
#define LOGTST_IMM_LOG_CONFIGURATION "logConfig=1,safApp=safLogService"
#define LOGTST_IMM_LOG_RUNTIME
"logConfig=currentConfig,safApp=safLogService"
+#define LOGTST_IMM_LOG_GCFG
"opensafConfigId=opensafGlobalConfig,safApp=OpenSAF"
extern SaNameT systemStreamName;
extern SaNameT alarmStreamName;
extern SaNameT notificationStreamName;
+extern SaNameT globalConfig;
extern SaNameT app1StreamName;
extern SaNameT notifyingObject;
extern SaNameT notificationObject;
diff --git a/tests/logsv/tet_LogOiOps.c b/tests/logsv/tet_LogOiOps.c
--- a/tests/logsv/tet_LogOiOps.c
+++ b/tests/logsv/tet_LogOiOps.c
@@ -3401,6 +3401,209 @@ void verLogFileName(void)
rc_validate(WEXITSTATUS(rc), 1);
}
+
+/****************************************
+ * These below function(s) are used to test added new tokens @Cq and @Cp:
+ * @Cp: represents network name.
+ * @Cq: represent node name.
+ *
+ * The test case will do following sequences:
+ *
+ * 1. Backup the current `opensafNetworkName` attribute.
+ * 2. Modify the attribute to a specific name.
+ * 3. Backup the current `saLogStreamLogFileFormat`
+ * 4. Modify the attribute by adding new @Cq, @Cp tokens
+ * 5. Send a log stream
+ * 6. Check content of log file (*.log) cotaining the node name & network name.
+ * 7. Restore the modified attributes to previous values
+ *
+ ***************************************/
+
+/* Commands to search for specific pattern on files having 01 last minute
+ * (?) accessed, but only openning file.
+ *
+ * The flow of execution as below:
+ *
+ * 1. Find (linux `find` command) all files in the directory specificed by
+ * %s (e.g: root_log_path) and subfolders which having 01 last minute accessed
+ * (e.g: read/write access) or lesser.
+ *
+ * 2. With `egrep``, it helps to filter just openning log files
+ * in list of files found - which have correct format
+ * <logfilename>_<yyyymmdd>_<hhmmss>.log
+ *
+ * 3. With `egrep`, search content in the list of right-format
+ * found files for a specific pattern.
+ * (e.g: timezone format = [+-][0-9]{4}, millisecond format = [0-9]{3})
+ *
+ * 4. Don't show found result (if tester wants to see the search result,
+ * comment final line and its above slash)
+ *
+ * Note: If found pattern, exit status of these pipes will be
+ * EXIT_SUCCESS(0), otherwise EXIT_FAILURE(1)/non-zero(?)
+ */
+#define VERIFY_CMD_1 "find %s -type f -mmin -1" \
+ " | egrep \".*(%s_[0-9]{8}_[0-9]{6})\\.log$\"" \
+ " | xargs egrep \" %s \"" \
+ " 1> /dev/null"
+
+/* Search pattern for node name pattern, including prefix for testing */
+#define NODENAME_PATTERN "prefNd_[a-zA-Z0-9,_,-]*"
+/* Search pattern for network name pattern, including prefix for testing */
+#define NWNAME_PATTERN "prefNw_Network A"
+
+/**
+ * CCB Object Modify saLogStreamLogFileFormat of alarm log stream
+ * by adding node name token and check if log file are reflected correctly.
+ */
+void verNodeName_01(void)
+{
+ int rc;
+ char command[MAX_DATA];
+ char preLogStrFileFmt[MAX_DATA];
+
+ /* Enable node name token - @Cq */
+ const char* modLogStrFileFmt = "@Cr @Ct prefNd_@Cq @Nz @Ne6 @No30 @Ng30
@Cb";
+
+ /* Get current value of the attribute, use default value if failed */
+ rc = get_attr_value(&alarmStreamName, "saLogStreamLogFileFormat", NULL,
+ preLogStrFileFmt);
+ if (rc == -1) {
+ /* Failed, use default one */
+ fprintf(stderr, "Failed to get attribute value from IMM\n");
+ strncpy(preLogStrFileFmt, DEFAULT_ALM_NOT_FORMAT_EXP, MAX_DATA);
+ }
+
+ /* Modify the attribute */
+ sprintf(command, IMMCFG_CMD, modLogStrFileFmt, SA_LOG_STREAM_ALARM);
+ rc = system(command);
+ if (WEXITSTATUS(rc) == 0) {
+ /* Send an alarm to alarm log stream */
+ rc = system("saflogger -l");
+ if (WEXITSTATUS(rc)) {
+ /* Failed to send the alarm to log stream */
+ fprintf(stderr, "Failed to invoke saflogger -a\n");
+ rc_validate(WEXITSTATUS(rc), 0);
+ /* Exit the test case */
+ return;
+ }
+
+ /* Verify the content of log file if it is reflected with right
format */
+ sprintf(command, VERIFY_CMD_1, log_root_path, ALM_LOG_FILE,
NODENAME_PATTERN);
+ rc = system(command);
+ if (rc == -1) {
+ fprintf(stderr, "Failed to execute command (%s) on
shell\n",
+ VERIFY_CMD_1);
+ test_validate(rc, 0);
+ /* Exit the test case */
+ return;
+ }
+ /* Command is executed succesfully on the shell, verify the
result */
+ rc_validate(WEXITSTATUS(rc), 0);
+
+ /* Restore the attribute to previous value */
+ sprintf(command, IMMCFG_CMD, preLogStrFileFmt,
SA_LOG_STREAM_ALARM);
+ rc = system(command);
+ if (WEXITSTATUS(rc) != 0) {
+ /* Failed to restore to privous value, print message */
+ fprintf(stderr, "Failed to restore the attribute to
previous value\n");
+ }
+ } else {
+ rc_validate(WEXITSTATUS(rc), 0);
+ }
+}
+
+/**
+ * CCB Object Modify saLogStreamLogFileFormat of alarm log stream
+ * by adding node name token and check if log file are reflected correctly.
+ */
+void verNetworkName_01(void)
+{
+ int rc;
+ char command[MAX_DATA];
+ char preLogStrFileFmt[MAX_DATA];
+ char networkName[MAX_DATA];
+
+ /* Enable network name token - @Cp */
+ const char* modLogStrFileFmt = "@Cr @Ct prefNw_@Cp @Nz @Ne6 @No30 @Ng30
@Cb";
+
+ /* Get current value of the attribute, use default value if failed */
+ rc = get_attr_value(&alarmStreamName, "saLogStreamLogFileFormat", NULL,
+ preLogStrFileFmt);
+ if (rc == -1) {
+ /* Failed, use default one */
+ fprintf(stderr, "Failed to get attribute value from IMM\n");
+ strncpy(preLogStrFileFmt, DEFAULT_ALM_NOT_FORMAT_EXP, MAX_DATA);
+ }
+
+ /* Get current value of the attribute, use default value if failed */
+ rc = get_attr_value(&globalConfig, "opensafNetworkName", NULL,
+ networkName);
+ if (rc == -1) {
+ /* Failed, use default one */
+ strncpy(networkName, "", MAX_DATA);
+ }
+
+ /* Modify attribute network name */
+ sprintf(command, "immcfg -a opensafNetworkName=\"Network A\" %s",
+ LOGTST_IMM_LOG_GCFG);
+ rc = system(command);
+ if (WEXITSTATUS(rc)) {
+ /* Failed to send the alarm to log stream */
+ fprintf(stderr, "Failed to invoke command %s\n", command);
+ rc_validate(WEXITSTATUS(rc), 0);
+ /* Exit the test case */
+ return;
+ }
+
+ /* Modify the logfileFmt attribute */
+ sprintf(command, IMMCFG_CMD, modLogStrFileFmt, SA_LOG_STREAM_ALARM);
+ rc = system(command);
+ if (WEXITSTATUS(rc) == 0) {
+ /* Send an alarm to alarm log stream */
+ rc = system("saflogger -l");
+ if (WEXITSTATUS(rc)) {
+ /* Failed to send the alarm to log stream */
+ fprintf(stderr, "Failed to invoke saflogger -a\n");
+ rc_validate(WEXITSTATUS(rc), 0);
+ /* Exit the test case */
+ return;
+ }
+
+ /* Verify the content of log file if it is reflected with right
format */
+ sprintf(command, VERIFY_CMD_1, log_root_path, ALM_LOG_FILE,
NWNAME_PATTERN);
+ rc = system(command);
+ if (rc == -1) {
+ fprintf(stderr, "Failed to execute command (%s) on
shell\n",
+ VERIFY_CMD_1);
+ test_validate(rc, 0);
+ /* Exit the test case */
+ return;
+ }
+ /* Command is executed succesfully on the shell, verify the
result */
+ rc_validate(WEXITSTATUS(rc), 0);
+
+ /* Restore the attribute to previous value */
+ sprintf(command, IMMCFG_CMD, preLogStrFileFmt,
SA_LOG_STREAM_ALARM);
+ rc = system(command);
+ if (WEXITSTATUS(rc) != 0) {
+ /* Failed to restore to privous value, print message */
+ fprintf(stderr, "Failed to restore logFileFmt\n");
+ }
+
+ sprintf(command, "immcfg -a opensafNetworkName=%s %s",
+ networkName, LOGTST_IMM_LOG_GCFG);
+ rc = system(command);
+ if (WEXITSTATUS(rc) != 0) {
+ /* Failed to restore to privous value, print message */
+ fprintf(stderr, "Failed to restore
opensafNetworkName\n");
+ }
+
+ } else {
+ rc_validate(WEXITSTATUS(rc), 0);
+ }
+}
+
__attribute__ ((constructor)) static void saOiOperations_constructor(void)
{
/* Stream objects */
@@ -3467,6 +3670,8 @@ void verLogFileName(void)
test_case_add(4, modStrLogFileFmt_03, "CCB Object Modify,
saLogstreamLogFileFormat, timezone token (@Cz)");
test_case_add(4, modStrLogFileFmt_04, "CCB Object Modify,
saLogstreamLogFileFormat, millisecond token (@Ck)");
test_case_add(4, modStrLogFileFmt_05, "CCB Object Modify,
saLogstreamLogFileFormat, timezone & millisecond token (@Cz @Ck)");
+ test_case_add(4, verNodeName_01, "CCB Object Modify,
saLogStreamLogFileFormat, node name token (@Cq)");
+ 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");
/* Configuration object */
------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=272487151&iu=/4140
_______________________________________________
Opensaf-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel