Hi Lanert ACK , ( code review only ) will be tested along with Vu Part of #2258
-AVM On 2/23/2017 3:41 PM, A V Mahesh wrote: > Hi Lanert > > This means , user can configure multiple DESTINATION_CONFIGURATION > concurrently ? > > > + 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); > + }; > > -AVM > > > On 2/20/2017 8:48 PM, Lennart Lund wrote: >> 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 ------------------------------------------------------------------------------ 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