Hi Lennart, Ack with few comments. [Vu]
Regards, Vu > -----Original Message----- > From: Lennart Lund [mailto:lennart.l...@ericsson.com] > Sent: Monday, February 20, 2017 10:18 PM > To: mahesh.va...@oracle.com; vu.m.ngu...@dektech.com.au > Cc: opensaf-devel@lists.sourceforge.net > Subject: [PATCH 1 of 1] lgs: Add new multivalue attributes to configuration > handler [#2258] > > 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) { [Vu] Consider to use "const auto&" for read-only values. > + 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) { [Vu] Consider to use "const auto&" for read-only values. > + 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) { [Vu] Consider to use "const auto&" for read-only values. > + 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) { [Vu] Consider to use constant and reference type for read-only class parameters (e.g: const std::string&, const std::vector<std::string>& value_list) > + 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) { [Vu] Consider to use constant and reference type for read-only class parameters (e.g: const std::string&, const std::vector<std::string>& value_list) > + 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