src/log/Makefile.am | 5 +- src/log/apitest/imm_tstutil.c | 126 +++++++ src/log/apitest/imm_tstutil.h | 61 +++ src/log/apitest/logtest.h | 2 +- src/log/apitest/saflogtest.c | 29 - src/log/apitest/tet_LogOiOps.c | 408 ++++++++++++++++++++++++ src/log/apitest/tet_Log_recov.c | 7 +- src/log/apitest/tet_log_runtime_cfgobj.c | 9 +- src/log/config/logsv_classes.xml | 27 + src/log/logd/lgs.h | 2 +- src/log/logd/lgs_config.cc | 507 ++++++++++++++++++++++++------ src/log/logd/lgs_config.h | 252 ++++++++++++++- src/log/logd/lgs_evt.cc | 2 +- src/log/logd/lgs_file.cc | 2 +- src/log/logd/lgs_imm.cc | 69 +++- src/log/logd/lgs_mbcsv.cc | 2 +- src/log/logd/lgs_mbcsv_v5.cc | 2 + 17 files changed, 1344 insertions(+), 168 deletions(-)
Add new attributes to the configuration object and configuration info object The new attributes are multi value so multi value support is also added NOTE: UML test fixed and new test cases added diff --git a/src/log/Makefile.am b/src/log/Makefile.am --- a/src/log/Makefile.am +++ b/src/log/Makefile.am @@ -1,6 +1,7 @@ # -*- OpenSAF -*- # # (C) Copyright 2016 The OpenSAF Foundation +# Copyright Ericsson AB [2016, 2017] - 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 @@ -147,7 +148,8 @@ bin_PROGRAMS += bin/logtest bin/saflogte noinst_HEADERS += \ src/log/apitest/logtest.h \ - src/log/apitest/logutil.h + src/log/apitest/logutil.h \ + src/log/apitest/imm_tstutil.h bin_logtest_CFLAGS = $(AM_CFLAGS) -Wformat=1 @@ -158,6 +160,7 @@ bin_logtest_CPPFLAGS = \ bin_logtest_SOURCES = \ src/log/apitest/logtest.c \ src/log/apitest/logutil.c \ + src/log/apitest/imm_tstutil.c \ src/log/apitest/tet_saLogInitialize.c \ src/log/apitest/tet_saLogSelectionObjectGet.c \ src/log/apitest/tet_saLogDispatch.c \ diff --git a/src/log/apitest/imm_tstutil.c b/src/log/apitest/imm_tstutil.c new file mode 100644 --- /dev/null +++ b/src/log/apitest/imm_tstutil.c @@ -0,0 +1,126 @@ +/* -*- OpenSAF -*- + * + * Copyright Ericsson AB [2017] - 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. + * + */ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include "imm/saf/saImm.h" +#include "imm/saf/saImmOm.h" +#include "osaf/immutil/immutil.h" +#include "base/saf_error.h" +#include "base/osaf_extended_name.h" + +static SaVersionT immVersion = {'A', 2, 11}; + +bool get_multivalue_type_string_from_imm(SaImmHandleT *omHandle, + SaConstStringT objectName, + char *attribute_name, + char ***multivalue_array) { + SaAisErrorT om_rc = SA_AIS_OK; + SaImmAccessorHandleT accessorHandle; + SaImmAttrValuesT_2 *attribute; + SaImmAttrValuesT_2 **attributes; + bool func_rc = true; + + //printf(">> get_multivalue_string_type_from_imm()\n"); + + do { + /* Make sure this is a NULL pointer if no values are found */ + *multivalue_array = NULL; + + om_rc = immutil_saImmOmInitialize(omHandle, NULL, &immVersion); + if (om_rc != SA_AIS_OK) { + printf("immutil_saImmOmInitialize Fail '%s'\n", + saf_error(om_rc)); + func_rc = false; + break; + } + + //printf("\timmutil_saImmOmInitialize() Done\n"); + + om_rc = immutil_saImmOmAccessorInitialize(*omHandle, + &accessorHandle); + if (om_rc != SA_AIS_OK) { + printf("immutil_saImmOmAccessorInitialize failed: %s\n", + saf_error(om_rc)); + func_rc = false; + break; + } + + //printf("\timmutil_saImmOmAccessorInitialize() Done\n"); + + //SaConstStringT objectName = "logConfig=1,safApp=safLogService"; + SaNameT tmpObjName; + osaf_extended_name_lend(objectName, &tmpObjName); + + /* Get the attribute */ + SaImmAttrNameT attributeNames[2]; + attributeNames[0] = attribute_name; + attributeNames[1] = NULL; + om_rc = immutil_saImmOmAccessorGet_2( + accessorHandle, + &tmpObjName, + attributeNames, + &attributes); + if (om_rc != SA_AIS_OK) { + printf("immutil_saImmOmAccessorGet_2 Fail '%s'\n", + saf_error(om_rc)); + func_rc = false; + break; + } + + //printf("\timmutil_saImmOmAccessorGet_2() Done\n"); + + attribute = attributes[0]; + char **str_array = NULL; + + /* Get values if there are any */ + if (attribute->attrValuesNumber > 0) { + size_t array_len = attribute->attrValuesNumber + 1; + str_array = (char **) calloc(array_len, sizeof(char *)); + str_array[array_len - 1] = NULL; /* NULL terminated array */ + + /* Save values */ + void *value = NULL; + for (uint32_t i = 0; i < attribute->attrValuesNumber; + i++) { + value = attribute->attrValues[i]; + str_array[i] = *(char **) value; + } + } + + *multivalue_array = str_array; + } while (0); + + //printf("<< get_multivalue_string_type_from_imm()\n"); + return func_rc; +} + +void free_multivalue(SaImmHandleT omHandle, char ***multivalue_array) { + //printf(">> free_multivalue_array() ptr = %p\n", *multivalue_array); + if (*multivalue_array == NULL) { + return; + } + + free(*multivalue_array); + + SaAisErrorT rc = immutil_saImmOmFinalize(omHandle); + if (rc != SA_AIS_OK) { + printf("free_multivalue: immutil_saImmOmFinalize() Fail %s\n", + saf_error(rc)); + } + //printf("<< free_multivalue_array()\n"); +} + \ No newline at end of file diff --git a/src/log/apitest/imm_tstutil.h b/src/log/apitest/imm_tstutil.h new file mode 100644 --- /dev/null +++ b/src/log/apitest/imm_tstutil.h @@ -0,0 +1,61 @@ +/* -*- OpenSAF -*- + * + * Copyright Ericsson AB [2017] - 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. + * + */ + +#include "log/apitest/logtest.h" + +#ifndef IMM_TSTUTIL_H +#define IMM_TSTUTIL_H + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Handle reading of multivalue of string type from log service configuration + * object + */ + +/** + * Get one multi value of string type (SA_IMM_ATTR_SASTRINGT) from the + * "logConfig=1,safApp=safLogService" object + * + * See also get_attr_value() for other non multivalue attributes + * + * Note: Memory is allocated for the multivalue_array that has to be freed + * after usage. Use free_multivalue_array() + * + * @param attribute_name[in] + * @param multivalue_array[out] NULL terminated array of strings (char *) + * @return false if Fail. Fail message is printed on stdout + */ +bool get_multivalue_type_string_from_imm(SaImmHandleT *omHandle, + SaConstStringT objectName, + char *attribute_name, + char ***multivalue_array); + +/** + * Used to free memory allocated for the multivalue_array by function + * get_multivalue_string_type_from_imm() + * + * @param multivalue_array[in] + */ +void free_multivalue(SaImmHandleT omHandle, char ***multivalue_array); + +#ifdef __cplusplus +} +#endif + +#endif /* IMM_TSTUTIL_H */ + diff --git a/src/log/apitest/logtest.h b/src/log/apitest/logtest.h --- a/src/log/apitest/logtest.h +++ b/src/log/apitest/logtest.h @@ -124,7 +124,7 @@ static inline void time_meas_start(time_ static inline void time_meas_log(time_meas_t* tm, char *id) { osaf_clock_gettime(CLOCK_REALTIME, &tm->end_time); osaf_timespec_subtract(&tm->end_time, &tm->start_time, &tm->diff_time); - LOG_NO("LLDTEST3 %s [%s]\t Elapsed time %ld sec, %ld nsec", + LOG_NO("%s [%s]\t Elapsed time %ld sec, %ld nsec", __FUNCTION__, id, tm->diff_time.tv_sec, tm->diff_time.tv_nsec); } diff --git a/src/log/apitest/saflogtest.c b/src/log/apitest/saflogtest.c --- a/src/log/apitest/saflogtest.c +++ b/src/log/apitest/saflogtest.c @@ -46,35 +46,6 @@ #include "osaf/saf/saAis.h" #include "log/saf/saLog.h" -#if 1 /*LLDTEST1 Test inline functions */ -#include "base/osaf_time.h" -#include "base/logtrace.h" - -typedef struct { - struct timespec start_time; - struct timespec end_time; - struct timespec diff_time; -} time_meas_t; -/** - * - * @param tm[out] - */ -static inline void time_meas_start(time_meas_t* tm) -{ - osaf_clock_gettime(CLOCK_REALTIME, &tm->start_time); -} - - -static inline void time_meas_log(time_meas_t* tm, char *id) -{ - osaf_clock_gettime(CLOCK_REALTIME, &tm->end_time); - osaf_timespec_subtract(&tm->end_time, &tm->start_time, &tm->diff_time); - LOG_NO("LLDTEST3 %s [%s]\t Elapsed time %ld sec, %ld nsec", - __FUNCTION__, id, - tm->diff_time.tv_sec, tm->diff_time.tv_nsec); -} -#endif - #define DEFAULT_FORMAT_EXPRESSION "@Cr @Ch:@Cn:@Cs @Cm/@Cd/@CY @Sv @Sl \"@Cb\"" #define DEFAULT_APP_LOG_REC_SIZE 150 #define DEFAULT_APP_LOG_FILE_SIZE 1024 * 1024 diff --git a/src/log/apitest/tet_LogOiOps.c b/src/log/apitest/tet_LogOiOps.c --- a/src/log/apitest/tet_LogOiOps.c +++ b/src/log/apitest/tet_LogOiOps.c @@ -1,6 +1,7 @@ /* -*- OpenSAF -*- * * (C) Copyright 2008 The OpenSAF Foundation + * Copyright Ericsson AB [2008, 2017] - 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 @@ -24,6 +25,7 @@ #include "base/saf_error.h" #include "logtest.h" +#include "log/apitest/imm_tstutil.h" #define MAX_DATA 256 #define opensaf_user "opensaf" @@ -1844,6 +1846,407 @@ void saLogOi_515(void) rc_validate(WEXITSTATUS(rc), 1); } +/** + * Help function for test of logRecordDestinationConfiguration + * + * @param set_values[in] Array of values to compare + * @param num_values[in] Number of values in set_values array + * @return false if compare fail + */ +static bool read_and_compare(SaConstStringT objectName, + char set_values[][MAX_DATA], + int num_values) { + char **read_values; + char* attr_name = "logRecordDestinationConfiguration"; + SaImmHandleT omHandle; + bool result = true; + + do { + // Read the values in logRecordDestinationConfiguration from IMM + bool rc = get_multivalue_type_string_from_imm(&omHandle, + LOGTST_IMM_LOG_CONFIGURATION, + attr_name, + &read_values); + if (rc == false) { + printf("Read values Fail\n"); + result = false; + break; + } + + // Special case if no values + if (num_values == 0) { + if (read_values == NULL) { + result = true; + } else { + result = false; + } + break; + } + + // Compare values + // Note: the order of the read values is not guaranteed meaning + // that it must be checked if any of the read values + // match a set value + bool match = false; + for (int i = 0; i < num_values; i++) { + for (int j = 0; j < num_values; j++) { + if (read_values[i] == NULL) { + match = false; + break; + } + if (strcmp(read_values[i], set_values[j]) == 0) { + match = true; + break; + } + } + if (match == false) { + result = false; + break; + } + } + + free_multivalue(omHandle, &read_values); + } while(0); + + return result; +} + +/** + * Test adding values. Check configuration object and current config object + */ +void check_logRecordDestinationConfigurationAdd(void) { + char command[MAX_DATA]; + const int num_values = 5; + char set_values[num_values][MAX_DATA]; + int test_result = 0; /* -1 if Fail */ + + do { + // Add values + for (int i = 0; i < num_values; i++) { + sprintf(set_values[i], "Name%d;Type%d;Setting%d", i, i, i); + sprintf(command, "immcfg " + "-a logRecordDestinationConfiguration+=" + "'%s' " + "logConfig=1,safApp=safLogService 2> /dev/null", + set_values[i]); + int rc = system(command); + if (rc != 0) { + printf("Set values Fail\n"); + test_result = 1; + break; + } + } + + // Check that all added values exist + bool result = read_and_compare(LOGTST_IMM_LOG_CONFIGURATION, + set_values, num_values); + if (result == false) { + test_result = 1; + printf("Check OpenSafLogConfig Fail\n"); + break; + } + + // Same check for current config object + result = read_and_compare(LOGTST_IMM_LOG_RUNTIME, + set_values, num_values); + if (result == false) { + test_result = 1; + printf("Check OpenSafLogCurrentConfig Fail\n"); + break; + } + } while(0); + + // Cleanup by removing all values + sprintf(command, "immcfg -a logRecordDestinationConfiguration='' " + "logConfig=1,safApp=safLogService 2> /dev/null"); + int rc = system(command); + if (rc != 0) { + printf("Cleanup Failed\n"); + } + + rc_validate(test_result, 0); +} + +/** + * Test deleting values. Check configuration object and current config object + */ +void check_logRecordDestinationConfigurationDelete(void) { + char command[MAX_DATA]; + const int num_values = 5; + char set_values[num_values][MAX_DATA]; + int test_result = 0; /* -1 if Fail */ + + do { + // Add values + for (int i = 0; i < num_values; i++) { + sprintf(set_values[i], "Name%d;Type%d;Setting%d", i, i, i); + sprintf(command, "immcfg " + "-a logRecordDestinationConfiguration+=" + "'%s' " + "logConfig=1,safApp=safLogService 2> /dev/null", + set_values[i]); + int rc = system(command); + if (rc != 0) { + printf("Add values Fail\n"); + test_result = 1; + break; + } + } + + // Delete last 2 values + for (int i = num_values - 2; i < num_values; i++) { + sprintf(command, "immcfg " + "-a logRecordDestinationConfiguration-=" + "'%s' " + "logConfig=1,safApp=safLogService 2> /dev/null", + set_values[i]); + int rc = system(command); + if (rc != 0) { + printf("Delete values Fail\n"); + test_result = 1; + break; + } + } + + // Check that all not deleted values exist + bool result = read_and_compare(LOGTST_IMM_LOG_CONFIGURATION, + set_values, num_values - 2); + if (result == false) { + test_result = 1; + printf("Check values not deleted Fail\n"); + break; + } + + // Check that deleted values do not exist + result = read_and_compare(LOGTST_IMM_LOG_CONFIGURATION, + set_values, num_values); + if (result == true) { + test_result = 1; + printf("Check values deleted Fail\n"); + break; + } + + // Same checks for current config object + result = read_and_compare(LOGTST_IMM_LOG_RUNTIME, + set_values, num_values - 2); + if (result == false) { + test_result = 1; + printf("Check values not deleted Fail\n"); + break; + } + + result = read_and_compare(LOGTST_IMM_LOG_RUNTIME, + set_values, num_values); + if (result == true) { + test_result = 1; + printf("Check values deleted Fail\n"); + break; + } + } while(0); + + // Cleanup by removing all values + sprintf(command, "immcfg -a logRecordDestinationConfiguration='' " + "logConfig=1,safApp=safLogService 2> /dev/null"); + int rc = system(command); + if (rc != 0) { + printf("Cleanup Failed\n"); + } + + rc_validate(test_result, 0); +} + +/** + * Test replacing values. Check configuration object and current config object + */ +void check_logRecordDestinationConfigurationReplace(void) { + char command[MAX_DATA*2]; + const int num_values = 5; + char set_values[num_values][MAX_DATA]; + int test_result = 0; /* 1 if Fail */ + + do { + // Add values that will be replaced + for (int i = 0; i < num_values; i++) { + sprintf(set_values[i], "Name%d;Type%d;Setting%d", i, i, i); + sprintf(command, "immcfg " + "-a logRecordDestinationConfiguration+=" + "'%s' " + "logConfig=1,safApp=safLogService 2> /dev/null", + set_values[i]); + int rc = system(command); + if (rc != 0) { + printf("Add values Fail\n"); + test_result = 1; + break; + } + } + + // Check that values exist + bool result = read_and_compare(LOGTST_IMM_LOG_CONFIGURATION, + set_values, num_values); + if (result == false) { + test_result = 1; + printf("Check OpenSafLogConfig Fail\n"); + break; + } + + // Replace the values + int num_new_values = 3; + for (int i = 0; i < num_new_values; i++) { + sprintf(set_values[i], + "NewName%d;NewType%d;NewSetting%d", i, i, i); + } + sprintf(command, "immcfg " + "-a logRecordDestinationConfiguration='%s' " + "-a logRecordDestinationConfiguration='%s' " + "-a logRecordDestinationConfiguration='%s' " + "logConfig=1,safApp=safLogService 2> /dev/null", + set_values[0], set_values[1], set_values[2]); + int rc = system(command); + if (rc != 0) { + printf("Add values Fail\n"); + test_result = 1; + break; + } + + // Check that new values exist in configuration object + result = read_and_compare(LOGTST_IMM_LOG_CONFIGURATION, + set_values, num_new_values); + if (result == false) { + test_result = 1; + printf("Check OpenSafLogConfig Fail\n"); + break; + } + + // Check that new values exist in current config object + result = read_and_compare(LOGTST_IMM_LOG_RUNTIME, + set_values, num_new_values); + if (result == false) { + test_result = 1; + printf("Check OpenSafLogCurrentConfig Fail\n"); + break; + } + + // Check that no old values exist in current config object + result = read_and_compare(LOGTST_IMM_LOG_RUNTIME, + set_values, num_new_values+1); + if (result == true) { + test_result = 1; + printf("Check OpenSafLogCurrentConfig Fail\n"); + break; + } + + } while(0); + + // Cleanup by removing all values + sprintf(command, "immcfg -a logRecordDestinationConfiguration='' " + "logConfig=1,safApp=safLogService 2> /dev/null"); + int rc = system(command); + if (rc != 0) { + printf("Cleanup Failed\n"); + } + + rc_validate(test_result, 0); +} + +/** + * Test to clear all values (make <empty> + */ +void check_logRecordDestinationConfigurationEmpty(void) { + char command[MAX_DATA*2]; + const int num_values = 5; + char set_values[num_values][MAX_DATA]; + int test_result = 0; /* 1 if Fail */ + + do { + // Add values that will be replaced + for (int i = 0; i < num_values; i++) { + sprintf(set_values[i], "Name%d;Type%d;Setting%d", i, i, i); + sprintf(command, "immcfg " + "-a logRecordDestinationConfiguration+=" + "'%s' " + "logConfig=1,safApp=safLogService 2> /dev/null", + set_values[i]); + int rc = system(command); + if (rc != 0) { + printf("Add values Fail\n"); + test_result = 1; + break; + } + } + + // Check that values exist + bool result = read_and_compare(LOGTST_IMM_LOG_CONFIGURATION, + set_values, num_values); + if (result == false) { + test_result = 1; + printf("Check OpenSafLogConfig Fail\n"); + break; + } + + // Clear the values + sprintf(command, "immcfg " + "-a logRecordDestinationConfiguration='' " + "logConfig=1,safApp=safLogService 2> /dev/null"); + int rc = system(command); + if (rc != 0) { + printf("Clear values Fail\n"); + test_result = 1; + break; + } + + // Check that new values cleared in configuration object + result = read_and_compare(LOGTST_IMM_LOG_CONFIGURATION, + set_values, 0); + if (result == false) { + test_result = 1; + printf("Clear OpenSafLogConfig Fail\n"); + break; + } + + // Check that new values cleared in current config object + result = read_and_compare(LOGTST_IMM_LOG_RUNTIME, + set_values, 0); + if (result == false) { + test_result = 1; + printf("Clear OpenSafLogCurrentConfig Fail\n"); + break; + } + + } while(0); + + // Cleanup by removing all values + sprintf(command, "immcfg -a logRecordDestinationConfiguration='' " + "logConfig=1,safApp=safLogService 2> /dev/null"); + int rc = system(command); + if (rc != 0) { + printf("Cleanup Failed\n"); + } + + rc_validate(test_result, 0); +} + +/** + * Test setting an invalid value + */ +void check_logRecordDestinationConfigurationInvalid(void) { + char command[MAX_DATA]; + int test_result = 0; /* 1 if Fail */ + + // Set invalid value + sprintf(command, "immcfg " + "-a logRecordDestinationConfiguration+=" + "'Invalid value' " + "logConfig=1,safApp=safLogService 2> /dev/null"); + + int rc = system(command); + if (rc != 0) { + test_result = 1; + } + + rc_validate(test_result, 1); +} + /* ============================================================================= * Test stream configuration object attribute validation, suite 6 * Note: @@ -4317,6 +4720,11 @@ done: test_case_add(5, saLogOi_514, "CCB Object Modify, logMaxApplicationStreams. Not allowed"); test_case_add(5, saLogOi_515, "CCB Object Modify, logFileSysConfig. Not allowed"); test_case_add(5, change_root_path, "CCB Object Modify, change root directory. Path exist. OK"); + test_case_add(5, check_logRecordDestinationConfigurationAdd, "Add logRecordDestinationConfiguration. OK"); + test_case_add(5, check_logRecordDestinationConfigurationDelete, "Delete logRecordDestinationConfiguration. OK"); + test_case_add(5, check_logRecordDestinationConfigurationReplace, "Replace logRecordDestinationConfiguration. OK"); + test_case_add(5, check_logRecordDestinationConfigurationEmpty, "Clear logRecordDestinationConfiguration. OK"); + test_case_add(5, check_logRecordDestinationConfigurationInvalid, "Invalid logRecordDestinationConfiguration. ERR"); /* Add test cases to test #1288 */ test_case_add(5, verLogFileIoTimeout, "CCB Object Modify: logFileIoTimeout is in range [500 - 5000], OK"); diff --git a/src/log/apitest/tet_Log_recov.c b/src/log/apitest/tet_Log_recov.c --- a/src/log/apitest/tet_Log_recov.c +++ b/src/log/apitest/tet_Log_recov.c @@ -1,6 +1,7 @@ /* -*- OpenSAF -*- * * (C) Copyright 2015 The OpenSAF Foundation + * Copyright Ericsson AB [2015, 2017] - 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 @@ -853,7 +854,7 @@ typedef struct { */ static void log_write_callback(SaInvocationT invocation, SaAisErrorT error) { - printf_v(">> LLDTEST %s\n",__FUNCTION__); + printf_v(">> %s\n",__FUNCTION__); if (error != SA_AIS_OK) { fprintf(stderr,"\t%s: error = %s\n",__FUNCTION__, saf_error(error)); } @@ -872,7 +873,7 @@ static void log_write_callback(SaInvocat lgt_cb.ais_errno = error; lgt_cb.invocation_out = invocation; osaf_mutex_unlock_ordie(&write_mutex); - printf_v("<< LLDTEST %s\n",__FUNCTION__); + printf_v("<< %s\n",__FUNCTION__); } /** @@ -1355,7 +1356,7 @@ void saLogRecov_prepare_client1_8streams rc = tst_StreamOpen_app_logtest_sc(g_client[0].glob_logHandle, g_client[0].glob_logStreamHandle, - 8); /* LLDTEST shall be 8 */ + 8); if (rc != 0) { fprintf(stderr, "\t%s Failed to open log stream\n", __FUNCTION__); diff --git a/src/log/apitest/tet_log_runtime_cfgobj.c b/src/log/apitest/tet_log_runtime_cfgobj.c --- a/src/log/apitest/tet_log_runtime_cfgobj.c +++ b/src/log/apitest/tet_log_runtime_cfgobj.c @@ -1,6 +1,7 @@ /* -*- OpenSAF -*- * * (C) Copyright 2015 The OpenSAF Foundation + * Copyright Ericsson AB [2015, 2017] - 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 @@ -27,7 +28,9 @@ static SaVersionT immVersion = { 'A', 2, * Log configuration config obj <=> runtime obj * * Verfy that the configuration and runtime object for log server configuration - * data contains the same number of attributes + * data contains the same number of attributes. + * Note: The runtime object contains 1 more attribute than the configuration + * object */ void log_rt_cf_obj_compare(void) { @@ -75,8 +78,10 @@ void log_rt_cf_obj_compare(void) r_cnt = 0; while (attributes[r_cnt++] != NULL); /* Count the attributes */ - /* Compare number of attributes. Test pass if the same number + /* Compare number of attributes. Test pass if the runtime object has + * 1 more attribute than the configuration object */ + r_cnt--; if (c_cnt != r_cnt) { tst_res = 1; fprintf(stderr, "Found %d configuration attributes and" diff --git a/src/log/config/logsv_classes.xml b/src/log/config/logsv_classes.xml --- a/src/log/config/logsv_classes.xml +++ b/src/log/config/logsv_classes.xml @@ -148,6 +148,13 @@ <flag>SA_WRITABLE</flag> </attr> <attr> + <name>saLogRecordDestination</name> + <type>SA_UINT32_T</type> + <category>SA_CONFIG</category> + <flag>SA_WRITABLE</flag> + <flag>SA_MULTI_VALUE</flag> + </attr> + <attr> <name>saLogStreamCreationTimestamp</name> <type>SA_TIME_T</type> <category>SA_RUNTIME</category> @@ -250,6 +257,14 @@ to ensure that default global values in <category>SA_CONFIG</category> <flag>SA_WRITABLE</flag> </attr> + <attr> + <name>logRecordDestinationConfiguration</name> + <type>SA_STRING_T</type> + <category>SA_CONFIG</category> + <flag>SA_WRITABLE</flag> + <flag>SA_MULTI_VALUE</flag> + <flag>SA_NO_DUPLICATES</flag> + </attr> </class> <class name="OpenSafLogCurrentConfig"> <category>SA_RUNTIME</category> @@ -314,5 +329,17 @@ to ensure that default global values in <type>SA_STRING_T</type> <category>SA_RUNTIME</category> </attr> + <attr> + <name>logRecordDestinationConfiguration</name> + <type>SA_STRING_T</type> + <category>SA_RUNTIME</category> + <flag>SA_MULTI_VALUE</flag> + </attr> + <attr> + <name>logRecordDestinationStatus</name> + <type>SA_STRING_T</type> + <category>SA_RUNTIME</category> + <flag>SA_MULTI_VALUE</flag> + </attr> </class> </imm:IMM-contents> diff --git a/src/log/logd/lgs.h b/src/log/logd/lgs.h --- a/src/log/logd/lgs.h +++ b/src/log/logd/lgs.h @@ -74,7 +74,7 @@ /* The name of log service config object */ #define LGS_IMM_LOG_CONFIGURATION "logConfig=1,safApp=safLogService" -/* The possible configurations for LGS_IMM_LOG_FILESYS_CFG */ +/* The possible configurations for LGS_IMM_LOG_FILE_SYS_CONFIG */ #define LGS_LOG_SHARED_FILESYSTEM 1 /* Use shared filesystem. Default */ #define LGS_LOG_SPLIT_FILESYSTEM 2 /* Store logs on local file system on each node */ diff --git a/src/log/logd/lgs_config.cc b/src/log/logd/lgs_config.cc --- a/src/log/logd/lgs_config.cc +++ b/src/log/logd/lgs_config.cc @@ -1,6 +1,7 @@ /* -*- OpenSAF -*- * * (C) Copyright 2015 The OpenSAF Foundation + * Copyright Ericsson AB [2015, 2017] - 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 @@ -27,6 +28,10 @@ #include <string.h> #include <utmp.h> +#include <string> +#include <vector> +#include <algorithm> + #include "osaf/configmake.h" #include "base/saf_error.h" #include "base/osaf_secutil.h" @@ -41,15 +46,6 @@ static SaVersionT immVersion = { 'A', 2, /* Mutex for making read and write of configuration data thread safe */ pthread_mutex_t lgs_config_data_mutex = PTHREAD_MUTEX_INITIALIZER; -/*** - * This file contains handling of Log service configuration including: - * - Configuration object - * - Environment variables - * - Default values - * - Verification of attribute values - * - Check-pointing - */ - /* The name of log service config object */ #define LGS_IMM_LOG_CONFIGURATION "logConfig=1,safApp=safLogService" @@ -118,8 +114,13 @@ typedef struct _lgs_conf_t { SaUint32T logMaxApplicationStreams; SaUint32T logFileIoTimeout; SaUint32T logFileSysConfig; + std::vector<std::string> logRecordDestinationConfiguration; // Default empty /* --- end correspond to IMM Class --- */ + /* --- Used with OpenSafLogCurrentConfig runtime object only --- */ + /* Note: Has no cnfflag */ + std::vector<std::string> logRecordDestinationStatus; // Default empty + /* Used for checkpointing time when files are closed */ time_t chkp_file_close_time; @@ -136,20 +137,22 @@ typedef struct _lgs_conf_t { lgs_conf_flg_t logFileSysConfig_cnfflag; lgs_conf_flg_t logDataGroupname_cnfflag; lgs_conf_flg_t logStreamFileFormat_cnfflag; + lgs_conf_flg_t logRecordDestinationConfiguration_cnfflag; _lgs_conf_t() : - logRootDirectory(lgs_conf_def.logRootDirectory), - logRootDirectory_cnfflag(LGS_CNF_DEF), - logMaxLogrecsize_cnfflag(LGS_CNF_DEF), - logStreamSystemHighLimit_cnfflag(LGS_CNF_DEF), - logStreamSystemLowLimit_cnfflag(LGS_CNF_DEF), - logStreamAppHighLimit_cnfflag(LGS_CNF_DEF), - logStreamAppLowLimit_cnfflag(LGS_CNF_DEF), - logMaxApplicationStreams_cnfflag(LGS_CNF_DEF), - logFileIoTimeout_cnfflag(LGS_CNF_DEF), - logFileSysConfig_cnfflag(LGS_CNF_DEF), - logDataGroupname_cnfflag(LGS_CNF_DEF), - logStreamFileFormat_cnfflag(LGS_CNF_DEF) { + logRootDirectory {PKGLOGDIR}, + logRootDirectory_cnfflag {LGS_CNF_DEF}, + logMaxLogrecsize_cnfflag {LGS_CNF_DEF}, + logStreamSystemHighLimit_cnfflag {LGS_CNF_DEF}, + logStreamSystemLowLimit_cnfflag {LGS_CNF_DEF}, + logStreamAppHighLimit_cnfflag {LGS_CNF_DEF}, + logStreamAppLowLimit_cnfflag {LGS_CNF_DEF}, + logMaxApplicationStreams_cnfflag {LGS_CNF_DEF}, + logFileIoTimeout_cnfflag {LGS_CNF_DEF}, + logFileSysConfig_cnfflag {LGS_CNF_DEF}, + logDataGroupname_cnfflag {LGS_CNF_DEF}, + logStreamFileFormat_cnfflag {LGS_CNF_DEF}, + logRecordDestinationConfiguration_cnfflag {LGS_CNF_DEF} { OpenSafLogConfig_object_exist = false; /* * The following attributes cannot be configured in the config file @@ -170,41 +173,10 @@ typedef struct _lgs_conf_t { static lgs_conf_t lgs_conf; -/****************************************************************************** - * Internal functions - ******************************************************************************/ - static char *cnfflag_str(lgs_conf_flg_t cnfflag); static int verify_all_init(); -/****************************************************************************** - * Utility functions - */ -/****************************************************************************** - * Check-pointing handling of configuration - */ - -/** - * Create configuration data buffer - * Creates a buffer containing all configuration data to be updated. - * Each time the function is called a configuration parameter is added. - * - * The buffer structure can be sent as a check-point message and the updating - * is done on the Standby. It can also be used in the OI to create an update - * buffer in the apply callback. Use lgs_cfg_update() for updating the - * configuration. - * - * NOTE1: Parameter name and value is not validated - * NOTE2: This function allocates memory pointed to by config_data in the - * lgs_config_chg_t structure. This memory has to bee freed after usage - * - * @param name_str[in] String containing the parameter name - * @param value_str[in] Parmeter value as a string - * @param config_data[out] Filled in config data structure - * NOTE! Must be initiated before first call {NULL, 0} - * - */ void lgs_cfgupd_list_create(const char *name_str, char *value_str, lgs_config_chg_t *config_data) { char *tmp_char_ptr = NULL; @@ -241,7 +213,7 @@ void lgs_cfgupd_list_create(const char * tmp_char_ptr = static_cast<char *>(realloc( config_data->ckpt_buffer_ptr, alloc_size)); if (tmp_char_ptr == NULL) { - TRACE("%s: malloc Fail Aborted", __FUNCTION__); + LOG_ER("%s: malloc Fail Aborted", __FUNCTION__); osaf_abort(0); } @@ -256,27 +228,120 @@ void lgs_cfgupd_list_create(const char * TRACE_LEAVE(); } +/******************************************************************************* + * Help functions for handling multi value attributes with the cfgupd list. + * Multi values can be handled in three ways Add, Delete and Replace + * In the configuration handler multi values will always be replaced. These + * help functions will always create a complete list of values and add them + * to the cfgupd list. Multiple values will be added to the list by adding + * the same attribute multiple times with different values. + * When reading a list using lgs_cfgupd_list_read() a multi value will be given + * by returning the same attribute multiple times with different values + * + * All functions takes the following parameters: + * + * @param attribute_name: + * The name of the multi value attribute + * + * @param value_list: + * A list of strings where each string represents a value + * + * @param config_data + * See lgs_cfgupd_list_create() + */ + +void lgs_cfgupd_multival_add(const std::string& attribute_name, + const std::vector<std::string>& value_list, + lgs_config_chg_t *config_data) { + TRACE_ENTER(); + // Get the existing multi-values and add them to the config data list + lgs_logconfGet_t param_id = param_name_to_id(attribute_name); + const std::vector<std::string> *exist_list = + reinterpret_cast<const std::vector<std::string>*>(lgs_cfg_get(param_id)); + + for (auto& value : *exist_list) { + lgs_cfgupd_list_create(attribute_name.c_str(), + const_cast<char *>(value.c_str()), + config_data); + } + + // Add the new values in the value-list to the config data list + for (auto& value : value_list) { + lgs_cfgupd_list_create(attribute_name.c_str(), + const_cast<char *>(value.c_str()), + config_data); + } + TRACE_LEAVE(); +} + /** - * Read a config update buffer and get parameter name and value. - * The first time the function is called next_param_ptr shall be - * a pointer to the buffer containing the config data. - * See ckpt_buffer_ptr in lgs_config_chg_t. - * To get the next parameter the next_param_ptr[in] shall be set to the - * return value from the previous call. NULL is returned when the last parameter - * is read. - * The last parameter cfgupd_ptr shall be a pointer to the buffer structure to - * read - * - * NOTE: The string pointed to by cfgupd_ptr->ckpt_buffer_ptr is changed in - * this function! See strtok_r() - * - * @param name_str[out] - * @param value_str[out] - * @param next_param_ptr[in] - * @param cfgupd_ptr[in] - * - * @return next_param_ptr + * Delete the values given in the list from the multi value attribute + * */ +static bool is_value_in_vector(const std::vector<std::string>& search_vector, + const std::string& searched_value) { + // Check if value is in vector + bool rc = false; + for (auto& value : search_vector) { + if (value == searched_value) { + rc = true; + break; + } + } + return rc; +} +void lgs_cfgupd_multival_delete(std::string attribute_name, + std::vector<std::string> value_list, + lgs_config_chg_t *config_data) { + TRACE_ENTER(); + // Get the existing multi-values + lgs_logconfGet_t param_id = param_name_to_id(attribute_name); + const std::vector<std::string> *exist_list = + reinterpret_cast<const std::vector<std::string>*>(lgs_cfg_get(param_id)); + + // Iterate over the exist_list and create a new list containing the + // existing values except the values in the given value-list + std::vector<std::string> result_list; + for (auto& exist_value: *exist_list) { + if (is_value_in_vector(value_list, exist_value) == false) { + result_list.push_back(exist_value); + } + } + + // Add this new list to the config data list + for (auto& value : result_list) { + lgs_cfgupd_list_create(attribute_name.c_str(), + const_cast<char *>(value.c_str()), + config_data); + } + TRACE_LEAVE(); +} + +/** + * Replace all existing values in the multi value attribute with the values in + * the list + */ +void lgs_cfgupd_mutival_replace(std::string attribute_name, + std::vector<std::string> value_list, + lgs_config_chg_t *config_data) { + TRACE_ENTER(); + + // Add given value-list to the config data list + if (value_list.empty()) { + // Special case. Create config_data with empty value + lgs_cfgupd_list_create(attribute_name.c_str(), const_cast<char *>(""), + config_data); + } else { + for (auto& value : value_list) { + lgs_cfgupd_list_create(attribute_name.c_str(), + const_cast<char *>(value.c_str()), + config_data); + } + } + + TRACE_LEAVE(); +} + char *lgs_cfgupd_list_read(char **name_str, char **value_str, char *next_param_ptr, lgs_config_chg_t *cfgupd_ptr) { char *bufend_ptr = NULL; @@ -306,23 +371,6 @@ done: return next_ptr; } -/** - * Parse a configuration data buffer and update the configuration structure. - * Used on Standby when receiving configuration check-point data and by OI - * to update configuration at modify apply. - * - * NOTE1: Operates on a static data structure. Is not thread safe - * NOTE2: Validation is done here. If validation fails we will be out of - * sync. A warning is logged to syslog - * Comment: Check-pointed configuration data is always sent when the - * configuration object is updated or when applying cahnges in IO. - * This means that the corresponding cnfflag is set to LGS_CNF_OBJ - * - * @param config_data[in] Pointer to structure containing configuration - * data buffer - * - * @return -1 if validation error - */ int lgs_cfg_update(const lgs_config_chg_t *config_data) { char *bufend_ptr = NULL; char *allocmem_ptr = NULL; @@ -332,6 +380,8 @@ int lgs_cfg_update(const lgs_config_chg_ char *value_str = NULL; char *saveptr = NULL; int rc = 0; + bool logRecordDestinationConfiguration_list_clear = true; + bool logRecordDestinationStatus_list_clear = true; TRACE_ENTER(); /* Validate config_data */ @@ -403,6 +453,28 @@ int lgs_cfg_update(const lgs_config_chg_ } else if (strcmp(name_str, LOG_FILE_SYS_CONFIG) == 0) { lgs_conf.logFileSysConfig = (SaUint32T) strtoul(value_str, NULL, 0); + } else if (strcmp(name_str, LOG_RECORD_DESTINATION_CONFIGURATION) == 0) { + if (logRecordDestinationConfiguration_list_clear) { + lgs_conf.logRecordDestinationConfiguration.clear(); + logRecordDestinationConfiguration_list_clear = false; + } + if (strlen(value_str) == 0) { + // The attribute has no values + lgs_conf.logRecordDestinationConfiguration.clear(); + } else { + lgs_conf.logRecordDestinationConfiguration.push_back(value_str); + } + } else if (strcmp(name_str, LOG_RECORD_DESTINATION_STATUS) == 0) { + if (logRecordDestinationStatus_list_clear) { + lgs_conf.logRecordDestinationStatus.clear(); + logRecordDestinationStatus_list_clear = false; + } + if (strlen(value_str) == 0) { + // The attribute has no values + lgs_conf.logRecordDestinationStatus.clear(); + } else { + lgs_conf.logRecordDestinationStatus.push_back(value_str); + } } param_ptr = next_ptr; @@ -413,8 +485,6 @@ int lgs_cfg_update(const lgs_config_chg_ /* Config data is written. Mutex can be unlocked */ osaf_mutex_unlock_ordie(&lgs_config_data_mutex); - lgs_trace_config(); - /* Validate the configuration structure data * For the moment Log a warning and do nothing. * NOTE: Configuration that's failed is replaced by default values @@ -639,6 +709,35 @@ static int lgs_cfg_verify_log_filesys_co return rc; } +/** + * Verify all values of log_record_destination_configuration + * Rules: + * - Empty string is Ok else + * - String shall have at least three fields separated by '\n' + * - First and second field cannot be empty + * + * @param log_record_destination_configuration[in] + * @return -1 on error + */ +int lgs_cfg_verify_log_record_destination_configuration( + std::vector<std::string>& log_record_destination_configuration) { + int rc = 0; + TRACE_ENTER(); + + int nl_cnt = 0; + for (auto& config : log_record_destination_configuration) { + // Verify that the string contains at least 2 ';' + nl_cnt = std::count(config.begin(), config.end(), ';'); + if (nl_cnt < 2) { + rc = -1; + break; + } + } + + TRACE_LEAVE2("rc = %s", rc == -1? "Fail": "Pass"); + return rc; +} + /** * Verify logRootDirectory; path to be used as log root directory @@ -745,6 +844,13 @@ static int verify_all_init() { lgs_conf.logFileSysConfig_cnfflag = LGS_CNF_DEF; rc = -1; } + + if (lgs_cfg_verify_log_record_destination_configuration( + lgs_conf.logRecordDestinationConfiguration) == -1) { + lgs_conf.logRecordDestinationConfiguration.clear(); + lgs_conf.logRecordDestinationConfiguration_cnfflag = LGS_CNF_DEF; + rc = -1; + } TRACE_LEAVE(); return rc; @@ -883,6 +989,18 @@ static void read_logsv_config_obj_2() { lgs_conf.logFileSysConfig = *((SaUint32T *) value); lgs_conf.logFileSysConfig_cnfflag = LGS_CNF_OBJ; TRACE("Conf obj; logFileSysConfig: %u", lgs_conf.logFileSysConfig); + } else if (!strcmp(attribute->attrName, + LOG_RECORD_DESTINATION_CONFIGURATION)) { + // Note: Multi value + char *value_string; + for (uint32_t i = 0; i < attribute->attrValuesNumber; i++) { + value = attribute->attrValues[i]; + value_string = *(reinterpret_cast<char **>(value)); + lgs_conf.logRecordDestinationConfiguration.push_back(value_string); + TRACE("Conf obj; logRecordDestinationConfiguration: '%s'", + lgs_conf.logRecordDestinationConfiguration.back().c_str()); + } + lgs_conf.logRecordDestinationConfiguration_cnfflag = LGS_CNF_OBJ; } } @@ -1125,10 +1243,6 @@ static void read_log_config_environ_var_ * Public functions for handling configuration information ******************************************************************************/ -/** - * Read the log service configuration data verify and update configuration - * data structure - */ void lgs_cfg_init(SaImmOiHandleT immOiHandle, SaAmfHAStateT ha_state) { TRACE_ENTER2("immOiHandle = %lld", immOiHandle); @@ -1208,15 +1322,21 @@ const void *lgs_cfg_get(lgs_logconfGet_t case LGS_IMM_LOG_MAX_APPLICATION_STREAMS: value_ptr = &lgs_conf.logMaxApplicationStreams; break; - case LGS_IMM_FILEHDL_TIMEOUT: + case LGS_IMM_FILE_IO_TIMEOUT: value_ptr = &lgs_conf.logFileIoTimeout; break; - case LGS_IMM_LOG_FILESYS_CFG: + case LGS_IMM_LOG_FILE_SYS_CONFIG: value_ptr = &lgs_conf.logFileSysConfig; break; case LGS_IMM_LOG_OPENSAFLOGCONFIG_CLASS_EXIST: value_ptr = &lgs_conf.OpenSafLogConfig_object_exist; break; + case LGS_IMM_LOG_RECORD_DESTINATION_CONFIGURATION: + value_ptr = &lgs_conf.logRecordDestinationConfiguration; + break; + case LGS_IMM_LOG_RECORD_DESTINATION_STATUS: + value_ptr = &lgs_conf.logRecordDestinationStatus; + break; case LGS_IMM_LOG_NUMBER_OF_PARAMS: case LGS_IMM_LOG_NUMEND: @@ -1385,6 +1505,152 @@ void conf_runtime_obj_create(SaImmOiHand } /** + * Same as immutil_update_one_rattr() except that + * + * All parameters are input parameters + * + */ +SaAisErrorT update_multival_rattr(SaImmOiHandleT immOiHandle, + const char *dn, + SaImmAttrNameT attributeName, + SaImmValueTypeT attrValueType, + SaUint32T attrValuesNumber, + void **values) +{ + SaImmAttrModificationT_2 attrMod; + const SaImmAttrModificationT_2 *attrMods[] = { &attrMod, NULL }; + SaImmAttrValueT *attrValues = values; + SaNameT objectName; + + saAisNameLend(dn, &objectName); + + attrMod.modType = SA_IMM_ATTR_VALUES_REPLACE; + attrMod.modAttr.attrName = attributeName; + attrMod.modAttr.attrValuesNumber = attrValuesNumber; + attrMod.modAttr.attrValueType = attrValueType; + attrMod.modAttr.attrValues = attrValues; + return immutil_saImmOiRtObjectUpdate_2(immOiHandle, &objectName, + attrMods); +} + +/** + * Creates a list of type void ** containing pointers to the + * strings in a C++ vector of strings + * Note: The attrValues C array is allocated and must be freed after use + * + * @param strings_in[in] C++ vector of strings + * @param attrValues[out] A C array with void pointers to C strings in + * strings_in + * @return attrValuesNumber + */ +static SaUint32T vector_of_strings_to_attrValues( + const std::vector<std::string>* strings_in, void ***attrValues_out) { + TRACE_ENTER(); + + SaUint32T attrValuesNumber = strings_in->size(); + + char **values_array = (char **) calloc(attrValuesNumber, sizeof(void **)); + if (values_array == nullptr) { + LOG_ER("%s: calloc Fail, Aborted", __FUNCTION__); + osaf_abort(0); + } + *attrValues_out = (void **) values_array; + + SaUint32T i = 0; + for (auto& conf_string : *strings_in) { + values_array[i] = const_cast<char *>(conf_string.c_str()); + i++; + } + + TRACE_LEAVE(); + return attrValuesNumber; +} + +/** + * Update one runtime attribute of the specified object. + * Same as immutil_update_one_rattr() but updates a list of values (multi value) + * + * @param immOiHandle[in] + * @param dn[in] + * @param attributeName[in] + * @param attrValueType[in] + * @param valuesNumber[in] + * @param values[in] + * @return Return value from immutil_saImmOiRtObjectUpdate_2() + */ +static SaAisErrorT update_runtime_attrValues(SaImmOiHandleT immOiHandle, + const char *dn, + SaImmAttrNameT attributeName, + SaImmValueTypeT attrValueType, + SaUint32T valuesNumber, + void **values) +{ + TRACE_ENTER(); + SaImmAttrModificationT_2 attrMod; + const SaImmAttrModificationT_2 *attrMods[] = { &attrMod, NULL }; + SaNameT objectName; + SaAisErrorT ais_rc = SA_AIS_OK; + + void **values_array = (void **) calloc(valuesNumber, sizeof(void *)); + if (values_array == nullptr) { + LOG_ER("%s: calloc Fail, Aborted", __FUNCTION__); + osaf_abort(0); + } + + for (SaUint32T i = 0; i < valuesNumber; i++) { + values_array[i] = &values[i]; + } + + saAisNameLend(dn, &objectName); + + attrMod.modType = SA_IMM_ATTR_VALUES_REPLACE; + attrMod.modAttr.attrName = attributeName; + attrMod.modAttr.attrValuesNumber = valuesNumber; + attrMod.modAttr.attrValueType = attrValueType; + attrMod.modAttr.attrValues = values_array; + ais_rc = immutil_saImmOiRtObjectUpdate_2(immOiHandle, &objectName, + attrMods); + free(values_array); + TRACE_LEAVE(); + return ais_rc; +} + +static SaAisErrorT update_lgs_cfg_runtime_multivalue( + SaImmOiHandleT immOiHandle, + SaImmAttrNameT attributeName, + SaImmValueTypeT valueType) { + TRACE_ENTER(); + // Get the multi value stored as C++ vector + lgs_logconfGet_t attribute_id = param_name_to_id(attributeName); + const std::vector<std::string> *multi_value_list = + reinterpret_cast<const std::vector<std::string>*> + (lgs_cfg_get(attribute_id)); + + // Convert the multi value C++ vector to a void C array + void **attrValues = nullptr; + SaUint32T attrValuesNumber = vector_of_strings_to_attrValues( + multi_value_list, &attrValues); + + // Give the multi value to IMM client + SaAisErrorT ais_rc = update_runtime_attrValues(immOiHandle, + LGS_CFG_RUNTIME_OBJECT, + attributeName, valueType, + attrValuesNumber, attrValues); + if (ais_rc != SA_AIS_OK) { + LOG_NO("%s: update_runtime_attrValues Fail %s", + __FUNCTION__, saf_error(ais_rc)); + } + + // Free the memory allocated by vector_of_strings_to_attrValues() + if (attrValues) { + free(attrValues); + } + + TRACE_LEAVE(); + return ais_rc; +} + +/** * Handler for updating runtime configuration object attributes * Called from the SaImmOiRtAttrUpdateCallbackT type function * @@ -1401,7 +1667,6 @@ void conf_runtime_obj_hdl(SaImmOiHandleT TRACE_ENTER(); while ((attributeName = attributeNames[i++]) != NULL) { - TRACE("Attribute %s", attributeName); if (!strcmp(attributeName, LOG_ROOT_DIRECTORY)) { str_val = (char *) lgs_cfg_get(LGS_IMM_LOG_ROOT_DIRECTORY); @@ -1467,18 +1732,26 @@ void conf_runtime_obj_hdl(SaImmOiHandleT &u32_val); } else if (!strcmp(attributeName, LOG_FILE_IO_TIMEOUT)) { u32_val = *(SaUint32T *) - lgs_cfg_get(LGS_IMM_FILEHDL_TIMEOUT); + lgs_cfg_get(LGS_IMM_FILE_IO_TIMEOUT); ais_rc = immutil_update_one_rattr(immOiHandle, LGS_CFG_RUNTIME_OBJECT, attributeName, SA_IMM_ATTR_SAUINT32T, &u32_val); } else if (!strcmp(attributeName, LOG_FILE_SYS_CONFIG)) { u32_val = *(SaUint32T *) - lgs_cfg_get(LGS_IMM_LOG_FILESYS_CFG); + lgs_cfg_get(LGS_IMM_LOG_FILE_SYS_CONFIG); ais_rc = immutil_update_one_rattr(immOiHandle, LGS_CFG_RUNTIME_OBJECT, attributeName, SA_IMM_ATTR_SAUINT32T, &u32_val); + } else if (!strcmp(attributeName, LOG_RECORD_DESTINATION_CONFIGURATION)) { + ais_rc = update_lgs_cfg_runtime_multivalue(immOiHandle, + attributeName, + SA_IMM_ATTR_SASTRINGT); + } else if (!strcmp(attributeName, LOG_RECORD_DESTINATION_STATUS)) { + ais_rc = update_lgs_cfg_runtime_multivalue(immOiHandle, + attributeName, + SA_IMM_ATTR_SASTRINGT); } else { TRACE("%s: unknown attribute %s", __FUNCTION__, attributeName); @@ -1490,7 +1763,6 @@ void conf_runtime_obj_hdl(SaImmOiHandleT osaf_abort(0); } } - TRACE_LEAVE(); } @@ -1552,6 +1824,22 @@ void lgs_trace_config() { TRACE("logFileSysConfig\t\t %u,\t %s", lgs_conf.logFileSysConfig, cnfflag_str(lgs_conf.logFileSysConfig_cnfflag)); + + // Multivalue: + for (auto& conf_str : lgs_conf.logRecordDestinationConfiguration) { + TRACE("logRecordDestinationConfiguration '%s', %s", conf_str.c_str(), + cnfflag_str(lgs_conf.logRecordDestinationConfiguration_cnfflag)); + } + if (lgs_conf.logRecordDestinationConfiguration.empty()) { + TRACE("logRecordDestinationConfiguration <empty>"); + } + for (auto& conf_str : lgs_conf.logRecordDestinationStatus) { + TRACE("logRecordDestinationStatus '%s'", conf_str.c_str()); + } + if (lgs_conf.logRecordDestinationStatus.empty()) { + TRACE("logRecordDestinationStatus <empty>"); + } + TRACE("OpenSafLogConfig_object_exist\t %s", lgs_conf.OpenSafLogConfig_object_exist ? "True": "False"); TRACE("===== LOG Configuration End ====="); @@ -1584,8 +1872,21 @@ void lgs_cfg_read_trace() { TRACE("logMaxApplicationStreams\t %u", *static_cast<const SaUint32T *>(lgs_cfg_get(LGS_IMM_LOG_MAX_APPLICATION_STREAMS))); TRACE("logFileIoTimeout\t\t %u", - *static_cast<const SaUint32T *>(lgs_cfg_get(LGS_IMM_FILEHDL_TIMEOUT))); + *static_cast<const SaUint32T *>(lgs_cfg_get(LGS_IMM_FILE_IO_TIMEOUT))); TRACE("logFileSysConfig\t\t %u", - *static_cast<const SaUint32T *>(lgs_cfg_get(LGS_IMM_LOG_FILESYS_CFG))); + *static_cast<const SaUint32T *>(lgs_cfg_get(LGS_IMM_LOG_FILE_SYS_CONFIG))); + // Multi value + const std::vector<std::string> *dest_config = + reinterpret_cast<const std::vector<std::string> *> + (lgs_cfg_get(LGS_IMM_LOG_RECORD_DESTINATION_CONFIGURATION)); + for (auto& conf_str : *dest_config) { + TRACE("logRecordDestinationConfiguration '%s'", conf_str.c_str()); + } + const std::vector<std::string> *dest_status = + reinterpret_cast<const std::vector<std::string> *> + (lgs_cfg_get(LGS_IMM_LOG_RECORD_DESTINATION_STATUS)); + for (auto& conf_str : *dest_status) { + TRACE("logRecordDestinationStatus '%s'", conf_str.c_str()); + } TRACE("##### LOG Configuration parameter read done #####"); } diff --git a/src/log/logd/lgs_config.h b/src/log/logd/lgs_config.h --- a/src/log/logd/lgs_config.h +++ b/src/log/logd/lgs_config.h @@ -1,6 +1,7 @@ /* -*- OpenSAF -*- * * (C) Copyright 2015 The OpenSAF Foundation + * Copyright Ericsson AB [2015, 2017] - 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 @@ -15,12 +16,36 @@ * */ +/*** + * This handler contains handling of Log service configuration including: + * - Configuration object + * - Environment variables + * - Default values + * - Verification of attribute values + * - Check-pointing + * - Presenting of configuration related information using runtime object + * + * All configuration data that can be found in the + * 'logConfig=1,safApp=safLogService' configuration object is stored locally on + * both active and standby nodes. The nodes are synchronized using message based + * check-pointing. Local data is synchronized with changes in the configuration + * object in the OI. + * + * Note1: + * The primary interfaces are used for updating e.g. in OI, verifying values + * e.g. in OI and getting values. + * There are also some help interfaces used for event handling of the + * OpenSafLogCurrentConfig information runtime object + * + */ + #ifndef LOG_LOGD_LGS_CONFIG_H_ #define LOG_LOGD_LGS_CONFIG_H_ #include <stdbool.h> #include <stdint.h> #include <string> +#include <vector> #include "imm/saf/saImmOi.h" #include "amf/saf/saAmf.h" @@ -38,6 +63,8 @@ #define LOG_MAX_APPLICATION_STREAMS "logMaxApplicationStreams" #define LOG_FILE_IO_TIMEOUT "logFileIoTimeout" #define LOG_FILE_SYS_CONFIG "logFileSysConfig" +#define LOG_RECORD_DESTINATION_CONFIGURATION "logRecordDestinationConfiguration" +#define LOG_RECORD_DESTINATION_STATUS "logRecordDestinationStatus" typedef enum { LGS_IMM_LOG_ROOT_DIRECTORY, @@ -49,8 +76,10 @@ typedef enum { LGS_IMM_LOG_STREAM_APP_HIGH_LIMIT, LGS_IMM_LOG_STREAM_APP_LOW_LIMIT, LGS_IMM_LOG_MAX_APPLICATION_STREAMS, - LGS_IMM_FILEHDL_TIMEOUT, - LGS_IMM_LOG_FILESYS_CFG, + LGS_IMM_FILE_IO_TIMEOUT, + LGS_IMM_LOG_FILE_SYS_CONFIG, + LGS_IMM_LOG_RECORD_DESTINATION_CONFIGURATION, + LGS_IMM_LOG_RECORD_DESTINATION_STATUS, LGS_IMM_LOG_NUMBER_OF_PARAMS, LGS_IMM_LOG_OPENSAFLOGCONFIG_CLASS_EXIST, @@ -58,6 +87,38 @@ typedef enum { LGS_IMM_LOG_NUMEND } lgs_logconfGet_t; +static inline lgs_logconfGet_t param_name_to_id(std::string param_name) { + if (param_name == LOG_ROOT_DIRECTORY) { + return LGS_IMM_LOG_ROOT_DIRECTORY; + } else if (param_name == LOG_DATA_GROUPNAME) { + return LGS_IMM_DATA_GROUPNAME; + } else if (param_name == LOG_MAX_LOGRECSIZE) { + return LGS_IMM_LOG_MAX_LOGRECSIZE; + } else if (param_name == LOG_STREAM_FILE_FORMAT) { + return LGS_IMM_LOG_STREAM_FILE_FORMAT; + } else if (param_name == LOG_STREAM_SYSTEM_HIGH_LIMIT) { + return LGS_IMM_LOG_STREAM_SYSTEM_HIGH_LIMIT; + } else if (param_name == LOG_STREAM_SYSTEM_LOW_LIMIT) { + return LGS_IMM_LOG_STREAM_SYSTEM_LOW_LIMIT; + } else if (param_name == LOG_STREAM_APP_HIGH_LIMIT) { + return LGS_IMM_LOG_STREAM_APP_HIGH_LIMIT; + } else if (param_name == LOG_STREAM_APP_LOW_LIMIT) { + return LGS_IMM_LOG_STREAM_APP_LOW_LIMIT; + } else if (param_name == LOG_MAX_APPLICATION_STREAMS) { + return LGS_IMM_LOG_MAX_APPLICATION_STREAMS; + } else if (param_name == LOG_FILE_IO_TIMEOUT) { + return LGS_IMM_FILE_IO_TIMEOUT; + } else if (param_name == LOG_FILE_SYS_CONFIG) { + return LGS_IMM_LOG_FILE_SYS_CONFIG; + } else if (param_name == LOG_RECORD_DESTINATION_CONFIGURATION) { + return LGS_IMM_LOG_RECORD_DESTINATION_CONFIGURATION; + } else if (param_name == LOG_RECORD_DESTINATION_STATUS) { + return LGS_IMM_LOG_RECORD_DESTINATION_STATUS; + } else { + return LGS_IMM_LOG_NUMEND; // Error + } +} + /** * Structure for log server configuration changing data */ @@ -66,18 +127,184 @@ typedef struct config_chkpt { uint64_t ckpt_buffer_size; /* Total size of the buffer */ }lgs_config_chg_t; -/* - * For function information see code file lgs_config.c +/* ---------------------------- + * Primary interface functions + */ + +/** + * Read the log service configuration data verify and update configuration + * data structure */ void lgs_cfg_init(SaImmOiHandleT immOiHandle, SaAmfHAStateT ha_state); + +/** + * Get value of log service configuration parameter from the configuration data + * struct. The scope of configuration data is restricted to this file. + * This function gives read access to the configuration data + * Note: The type of the returned value is void. This means that the reader + * must know the actual type and convert to correct type. + * + * Note1: Multivalue is returned as a void * to a std::vector<type> + * Example: + * LGS_IMM_LOG_RECORD_DESTINATION_CONFIGURATION is returned as a void * to + * std::vector<std::string> + * + * @param lgs_logconfGet_t param[in] + * Defines what configuration parameter to return + * + * @return void * + * Pointer to the parameter. See struct lgs_conf + * + */ const void *lgs_cfg_get(lgs_logconfGet_t param); -bool lgs_path_is_writeable_dir_h(const std::string &pathname); + +/** + * Create configuration data buffer + * Creates a buffer containing all configuration data to be updated. + * Each time the function is called a configuration parameter is added. + * + * The buffer structure can be sent as a check-point message and the updating + * is done on the Standby. It can also be used in the OI to create an update + * buffer in the apply callback. Use lgs_cfg_update() for updating the + * configuration. + * + * NOTE1: Parameter name and value is not validated + * NOTE2: This function allocates memory pointed to by config_data in the + * lgs_config_chg_t structure. This memory has to bee freed after usage + * Example: free(config_data.ckpt_buffer_ptr); + * NOTE3: A multi-value is added by iterating the multivalue vector and enter + * each value separately using the same attribute name (name_str). + * Help functions for handling multi-value can be used. + * See lgs_cfgupd_multival_xxx() functions. + * + * @param name_str[in] String containing the parameter name + * @param value_str[in] Parmeter value as a string + * @param config_data[out] Filled in config data structure + * NOTE! Must be initiated before first call {NULL, 0} + * + */ void lgs_cfgupd_list_create(const char *name_str, char *value_str, lgs_config_chg_t *config_data); + +/******************************************************************************* + * Help functions for handling multi value attributes with the cfgupd list. + * Multi values can be handled in three ways Add, Delete and Replace + * In the configuration handler multi values will always be replaced. These + * help functions will always create a complete list of values and add them + * to the cfgupd list. Multiple values are added to the list by adding + * the same attribute multiple times with different values. + * When reading a list using lgs_cfgupd_list_read() a multi value will be given + * by returning the same attribute multiple times with different values + * + * Note1: The NO_DUPLICATES flag shall be used with multi value attributes + * + * Note2: These help functions use lgs_cfgupd_list_create() so information and + * notes for lgs_cfgupd_list_create() regarding config_data also applies + * here. + * + * All functions takes the following parameters: + * + * @param attribute_name: + * The name of the multi value attribute + * + * @param value_list: + * A list of strings where each string represents a value + * + * @param config_data + * See lgs_cfgupd_list_create() + */ + +/** + * Add a list of new values to the existing values in the attribute + * + */ +void lgs_cfgupd_multival_add(const std::string& attribute_name, + const std::vector<std::string>& value_list, + lgs_config_chg_t *config_data); + +/** + * Delete the values given in the list from the multi value attribute + * Note: The attribute shall have the NO_DUPLICATES flag + * + */ +void lgs_cfgupd_multival_delete(std::string attribute_name, + std::vector<std::string> value_list, + lgs_config_chg_t *config_data); + +/** + * Replace all existing values in the multi value attribute with the values in + * the list + */ +void lgs_cfgupd_mutival_replace(std::string attribute_name, + std::vector<std::string> value_list, + lgs_config_chg_t *config_data); + +/** + * Read a config update buffer and get parameter name and value. + * The first time the function is called next_param_ptr shall be + * a pointer to the buffer containing the config data. + * See ckpt_buffer_ptr in lgs_config_chg_t. + * To get the next parameter the next_param_ptr[in] shall be set to the + * return value from the previous call. NULL is returned when the last parameter + * is read. + * The last parameter cfgupd_ptr shall be a pointer to the buffer structure to + * read + * + * NOTE1: The string pointed to by cfgupd_ptr->ckpt_buffer_ptr is changed in + * this function! See strtok_r() + * + * NOTE2: See lgs_cfgupd_list_create() for info about multi-value attribute + * + * @param name_str[out] + * @param value_str[out] + * @param next_param_ptr[in] + * @param cfgupd_ptr[in] + * + * @return next_param_ptr + */ char *lgs_cfgupd_list_read(char **name_str, char **value_str, char *next_param_ptr, lgs_config_chg_t *cfgupd_ptr); + +/** + * Parse a configuration data buffer and update the configuration structure. + * Used e.g. on Standby when receiving configuration check-point data and by OI + * to update configuration at modify apply. + * + * Comment: Check-pointed configuration data is always sent when the + * configuration object is updated or when applying changes in IO. + * This means that the corresponding cnfflag is set to LGS_CNF_OBJ + * + * NOTE1: Multi-value is always replaced. For information on how to handle + * Add, delete and replace see lgs_cfgupd_list_create() and the + * multi-value handling help functions + * This configuration is stored as a C++ vector of C++ strings + * A completely new list is always created if this configuration is + * updated. This attribute may have multiple instances in the config_data + * list. Each instance will add a value to the vector. If the config_data + * list has an empty string as value it means that the multivalue is + * empty and shall have an empty vector as value + * + * @param config_data[in] Pointer to structure containing configuration + * data buffer + * + * @return -1 if validation error + */ int lgs_cfg_update(const lgs_config_chg_t *config_data); +/** + * Parameter value validation functions. Validates parameters. + * For more information e.g. validation rules see lgs_conf.cc file + */ +bool lgs_path_is_writeable_dir_h(const std::string &pathname); +int lgs_cfg_verify_root_dir(const std::string &root_str_in); +int lgs_cfg_verify_log_data_groupname(char *group_name); +int lgs_cfg_verify_log_file_format(const char* log_file_format); +int lgs_cfg_verify_max_logrecsize(uint32_t max_logrecsize_in); +int lgs_cfg_verify_mbox_limit(uint32_t high, uint32_t low); +int lgs_cfg_verify_max_application_streams(uint32_t max_app_streams); +int lgs_cfg_verify_file_io_timeout(uint32_t log_file_io_timeout); +int lgs_cfg_verify_log_record_destination_configuration( + std::vector<std::string>& log_record_destination_configuration); /* * Functions for updating some parameters. Used to support check-point before * version 5 @@ -86,19 +313,8 @@ void lgs_rootpathconf_set(const std::str void lgs_groupnameconf_set(const char *data_groupname_str); /* - * Parameter value validation functions. Validates parameters. See function - * headers for validation rules - */ -int lgs_cfg_verify_root_dir(const std::string &root_str_in); -int lgs_cfg_verify_log_data_groupname(char *group_name); -int lgs_cfg_verify_log_file_format(const char* log_file_format); -int lgs_cfg_verify_max_logrecsize(uint32_t max_logrecsize_in); -int lgs_cfg_verify_mbox_limit(uint32_t high, uint32_t low); -int lgs_cfg_verify_max_application_streams(uint32_t max_app_streams); -int lgs_cfg_verify_file_io_timeout(uint32_t log_file_io_timeout); - -/* - * Handle runtime object for showing actual configuration + * Handle runtime object for showing actual configuration and configuration + * related information */ void conf_runtime_obj_create(SaImmOiHandleT immOiHandle); void conf_runtime_obj_hdl(SaImmOiHandleT immOiHandle, const SaImmAttrNameT *attributeNames); diff --git a/src/log/logd/lgs_evt.cc b/src/log/logd/lgs_evt.cc --- a/src/log/logd/lgs_evt.cc +++ b/src/log/logd/lgs_evt.cc @@ -1225,7 +1225,7 @@ snd_rsp: *****************************************************************************/ static uint32_t proc_write_log_async_msg(lgs_cb_t *cb, lgsv_lgs_evt_t *evt) { lgsv_write_log_async_req_t *param = &(evt->info.msg.info.api_info.param).write_log_async; - log_stream_t *stream; + log_stream_t *stream = NULL; SaAisErrorT error = SA_AIS_OK; SaStringT logOutputString = NULL; SaUint32T buf_size; diff --git a/src/log/logd/lgs_file.cc b/src/log/logd/lgs_file.cc --- a/src/log/logd/lgs_file.cc +++ b/src/log/logd/lgs_file.cc @@ -420,7 +420,7 @@ lgsf_retcode_t log_file_api(lgsf_apipar_ if (rc != 0) osaf_abort(rc); /* Wait for an answer */ - max_waittime_ms = *static_cast<const SaUint32T *>(lgs_cfg_get(LGS_IMM_FILEHDL_TIMEOUT)); + max_waittime_ms = *static_cast<const SaUint32T *>(lgs_cfg_get(LGS_IMM_FILE_IO_TIMEOUT)); get_timeout_time(&timeout_time, max_waittime_ms); while (lgs_com_data.answer_f == false) { diff --git a/src/log/logd/lgs_imm.cc b/src/log/logd/lgs_imm.cc --- a/src/log/logd/lgs_imm.cc +++ b/src/log/logd/lgs_imm.cc @@ -1,6 +1,7 @@ /* -*- OpenSAF -*- * * (C) Copyright 2008 The OpenSAF Foundation + * Copyright Ericsson AB [2008, 2017] - 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 @@ -42,8 +43,8 @@ #include "log/logd/lgs.h" #include "log/logd/lgs_util.h" #include "log/logd/lgs_file.h" -#include "lgs_recov.h" -#include "lgs_config.h" +#include "log/logd/lgs_recov.h" +#include "log/logd/lgs_config.h" #include "base/saf_error.h" #include "lgs_mbcsv_v1.h" @@ -740,10 +741,12 @@ static SaAisErrorT config_ccb_completed_ /** * Ignore deletion of attributes * except for logDataGroupname, - * and logStreamFileFormat + * logStreamFileFormat and + * logRecordDestinationConfiguration */ if ((strcmp(attribute->attrName, LOG_DATA_GROUPNAME) != 0) && (strcmp(attribute->attrName, LOG_STREAM_FILE_FORMAT) != 0) && + (strcmp(attribute->attrName, LOG_RECORD_DESTINATION_CONFIGURATION) != 0) && (attribute->attrValuesNumber == 0)) { report_oi_error(immOiHandle, opdata->ccbId, "deletion of value is not allowed for attribute %s stream %s", @@ -846,6 +849,24 @@ static SaAisErrorT config_ccb_completed_ "%s cannot be changed", attribute->attrName); ais_rc = SA_AIS_ERR_FAILED_OPERATION; goto done; + } else if (!strcmp(attribute->attrName, + LOG_RECORD_DESTINATION_CONFIGURATION)) { + // Note: Multi value attribute + TRACE("logRecordDestinationConfiguration. Values number = %d", + attribute->attrValuesNumber); + std::vector<std::string> values_vector; + for (uint32_t i=0; i < attribute->attrValuesNumber; i++) { + value = attribute->attrValues[i]; + char *value_str = *(reinterpret_cast<char **>(value)); + values_vector.push_back(value_str); + } + rc = lgs_cfg_verify_log_record_destination_configuration(values_vector); + if (rc == -1) { + report_oi_error(immOiHandle, opdata->ccbId, + "%s value is NOT accepted", attribute->attrName); + ais_rc = SA_AIS_ERR_INVALID_PARAM; + goto done; + } } else { report_oi_error(immOiHandle, opdata->ccbId, "attribute %s not recognized", attribute->attrName); @@ -863,7 +884,7 @@ static SaAisErrorT config_ccb_completed_ } done: - TRACE_LEAVE2("rc=%u", ais_rc); + TRACE_LEAVE2("ais_rc='%s'", saf_error(ais_rc)); return ais_rc; } @@ -1972,8 +1993,7 @@ static void config_ccb_apply_modify(cons /* Flag set if any of the mailbox limit values have changed */ bool mailbox_lim_upd = false; - TRACE_ENTER2("CCB ID %llu, '%s'", opdata->ccbId, - osaf_extended_name_borrow(&opdata->objectName)); + TRACE_ENTER(); attrMod = opdata->param.modify.attrMods[i++]; while (attrMod != NULL) { @@ -2058,6 +2078,39 @@ static void config_ccb_apply_modify(cons lgs_cfgupd_list_create(LOG_FILE_IO_TIMEOUT, uint32_str, &config_data); } + else if (!strcmp(attribute->attrName, + LOG_RECORD_DESTINATION_CONFIGURATION)) { + // Note: Multi value attribute + TRACE("logRecordDestinationConfiguration"); + std::vector<std::string> values_vector; + for (uint32_t i=0; i < attribute->attrValuesNumber; i++) { + value = attribute->attrValues[i]; + char *value_str = *(reinterpret_cast<char **>(value)); + values_vector.push_back(value_str); + } + + switch (attrMod->modType) { + case SA_IMM_ATTR_VALUES_ADD: + lgs_cfgupd_multival_add(LOG_RECORD_DESTINATION_CONFIGURATION, + values_vector, + &config_data); + break; + case SA_IMM_ATTR_VALUES_DELETE: + lgs_cfgupd_multival_delete(LOG_RECORD_DESTINATION_CONFIGURATION, + values_vector, + &config_data); + break; + case SA_IMM_ATTR_VALUES_REPLACE: + lgs_cfgupd_mutival_replace(LOG_RECORD_DESTINATION_CONFIGURATION, + values_vector, + &config_data); + break; + default: + // Shall never happen + LOG_ER("%s: Unknown modType %d", __FUNCTION__, attrMod->modType); + osafassert(0); + }; + } attrMod = opdata->param.modify.attrMods[i++]; } @@ -2085,10 +2138,12 @@ static void config_ccb_apply_modify(cons /* Cleanup and free cfg buffer */ if (config_data.ckpt_buffer_ptr != NULL) free(config_data.ckpt_buffer_ptr); + + TRACE_LEAVE(); } static void config_ccb_apply(const CcbUtilOperationData_t *opdata) { - TRACE_ENTER2("CCB ID %llu", opdata->ccbId); + TRACE_ENTER(); switch (opdata->operationType) { case CCBUTIL_CREATE: diff --git a/src/log/logd/lgs_mbcsv.cc b/src/log/logd/lgs_mbcsv.cc --- a/src/log/logd/lgs_mbcsv.cc +++ b/src/log/logd/lgs_mbcsv.cc @@ -367,7 +367,7 @@ bool lgs_is_peer_v5() { */ bool lgs_is_split_file_system() { SaUint32T lgs_file_config; - lgs_file_config = *static_cast<const SaUint32T*>(lgs_cfg_get(LGS_IMM_LOG_FILESYS_CFG)); + lgs_file_config = *static_cast<const SaUint32T*>(lgs_cfg_get(LGS_IMM_LOG_FILE_SYS_CONFIG)); if ((lgs_file_config == LGS_LOG_SPLIT_FILESYSTEM) && lgs_is_peer_v2()) { return true; diff --git a/src/log/logd/lgs_mbcsv_v5.cc b/src/log/logd/lgs_mbcsv_v5.cc --- a/src/log/logd/lgs_mbcsv_v5.cc +++ b/src/log/logd/lgs_mbcsv_v5.cc @@ -48,6 +48,7 @@ uint32_t ckpt_proc_lgs_cfg_v5(lgs_cb_t * char *saved_buf = NULL; int rc = 0; + TRACE_ENTER(); /* Flag set if any of the mailbox limit values have changed */ bool mailbox_lim_upd = false; @@ -140,6 +141,7 @@ uint32_t ckpt_proc_lgs_cfg_v5(lgs_cb_t * lgs_trace_config(); + TRACE_LEAVE(); return NCSCC_RC_SUCCESS; } ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot _______________________________________________ Opensaf-devel mailing list Opensaf-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/opensaf-devel