Thanks, Mathi.

Here is the fix for comments of patch 1/4 and 2/4.

Regards, Vu.

>-----Original Message-----
>From: Mathivanan Naickan Palanivelu [mailto:[email protected]]
>Sent: Wednesday, February 24, 2016 5:24 PM
>To: [email protected]
>Cc: [email protected]; [email protected];
>[email protected]
>Subject: Re: [PATCH 1 of 4] log: add support for cloud resilience feature 
>(service
>part) [#1179]
>
>Ack for patch 1,
>You could use %PRIx64 for MDS addresses.
>Mathi.
>
>----- [email protected] wrote:
>
>> osaf/services/saf/logsv/lgs/Makefile.am    |    6 +-
>>  osaf/services/saf/logsv/lgs/lgs.h          |   12 +
>>  osaf/services/saf/logsv/lgs/lgs_cb.h       |   14 +
>>  osaf/services/saf/logsv/lgs/lgs_evt.cc     |   66 ++-
>>  osaf/services/saf/logsv/lgs/lgs_evt.h      |    5 +
>>  osaf/services/saf/logsv/lgs/lgs_file.cc    |    5 +
>>  osaf/services/saf/logsv/lgs/lgs_file.h     |    1 +
>>  osaf/services/saf/logsv/lgs/lgs_filehdl.cc |  424 ++++++++++++++++-
>>  osaf/services/saf/logsv/lgs/lgs_filehdl.h  |   21 +
>>  osaf/services/saf/logsv/lgs/lgs_imm.cc     |  541
>> ++++++++++++++++++++-
>>  osaf/services/saf/logsv/lgs/lgs_main.cc    |  134 ++++-
>>  osaf/services/saf/logsv/lgs/lgs_mbcsv.cc   |   22 +-
>>  osaf/services/saf/logsv/lgs/lgs_recov.cc   |  758
>> +++++++++++++++++++++++++++++
>>  osaf/services/saf/logsv/lgs/lgs_recov.h    |   37 +
>>  osaf/services/saf/logsv/lgs/lgs_stream.cc  |   65 +-
>>  osaf/services/saf/logsv/lgs/lgs_stream.h   |   28 +-
>>  osaf/services/saf/logsv/lgs/lgs_util.cc    |   50 +-
>>  osaf/services/saf/logsv/lgs/lgs_util.h     |    4 +
>>  18 files changed, 2121 insertions(+), 72 deletions(-)
>>
>>
>> The patch makes LOG service be able to handle the case that both SC
>> nodes
>> are down at the same time.
>> When one or both nodes go up again the log service must be able to
>> resume its work preferably without actions by the clients.
>>
>> A log client should not have to be aware of if one or both SC nodes
>> are down.
>> The only thing that should happen is that a TRY AGAIN (and in some
>> cases TIMEOUT) returned.
>> It is the responsibility of the client to decide how to handle this.
>>
>> diff --git a/osaf/services/saf/logsv/lgs/Makefile.am
>> b/osaf/services/saf/logsv/lgs/Makefile.am
>> --- a/osaf/services/saf/logsv/lgs/Makefile.am
>> +++ b/osaf/services/saf/logsv/lgs/Makefile.am
>> @@ -35,7 +35,8 @@ noinst_HEADERS = \
>>      lgs_mbcsv_v1.h \
>>      lgs_mbcsv_v2.h \
>>      lgs_mbcsv_v3.h \
>> -    lgs_mbcsv_v5.h
>> +    lgs_mbcsv_v5.h \
>> +    lgs_recov.h
>>
>>  osaf_execbindir = $(pkglibdir)
>>  osaf_execbin_PROGRAMS = osaflogd
>> @@ -63,7 +64,8 @@ osaflogd_SOURCES = \
>>      lgs_mbcsv_v1.cc \
>>      lgs_mbcsv_v2.cc \
>>      lgs_mbcsv_v3.cc \
>> -    lgs_mbcsv_v5.cc
>> +    lgs_mbcsv_v5.cc \
>> +    lgs_recov.cc
>>
>>  osaflogd_LDADD = \
>>      $(top_builddir)/osaf/tools/safimm/src/libimmutil.la \
>> diff --git a/osaf/services/saf/logsv/lgs/lgs.h
>> b/osaf/services/saf/logsv/lgs/lgs.h
>> --- a/osaf/services/saf/logsv/lgs/lgs.h
>> +++ b/osaf/services/saf/logsv/lgs/lgs.h
>> @@ -30,6 +30,8 @@
>>  #include <ncs_edu_pub.h>
>>  #include <ncs_util.h>
>>  #include <saAis.h>
>> +#include <saf_error.h>
>> +#include <saImmOm.h>
>>
>>  /* LGS files */
>>  #include "lgsv_defs.h"
>> @@ -111,6 +113,16 @@ extern void lgs_imm_impl_reinit_nonblock
>>  extern void lgs_imm_init_OI_handle(SaImmOiHandleT *immOiHandle,
>>                                     SaSelectionObjectT
>> *immSelectionObject);
>>  extern void lgs_imm_impl_set(SaImmOiHandleT immOiHandle);
>> +extern  SaAisErrorT lgs_imm_init_configStreams(lgs_cb_t *cb);
>>
>> +// Functions for recovery handling
>> +void lgs_clean_stream_objects(void);
>> +void lgs_delete_one_stream_object(char *name_str);
>> +void lgs_search_stream_objects(void);
>> +SaUint32T *lgs_get_scAbsenceAllowed_attr(SaUint32T *attr_val);
>> +int lgs_get_streamobj_attr(SaImmAttrValuesT_2 ***attrib_out,
>> +                       char *object_name,
>> +                       SaImmHandleT *immOmHandle);
>> +int lgs_free_streamobj_attr(SaImmHandleT immHandle);
>>
>>  #endif   /* ifndef __LGS_H */
>> diff --git a/osaf/services/saf/logsv/lgs/lgs_cb.h
>> b/osaf/services/saf/logsv/lgs/lgs_cb.h
>> --- a/osaf/services/saf/logsv/lgs/lgs_cb.h
>> +++ b/osaf/services/saf/logsv/lgs/lgs_cb.h
>> @@ -26,6 +26,14 @@
>>
>>  #include "lgs_stream.h"
>>
>> +/* LGS Recovery states */
>> +typedef enum {
>> +    LGS_NORMAL,     /* No recovery is ongoing. All requests are
>> handled normally */
>> +    LGS_RECOVERY    /* Recover streams if in recovery list when
>> stream open
>> +                                     * request with no parameters
>> +                                     */
>> +} lgs_state_t;
>> +
>>  /* Default HA state assigned locally during lgs initialization */
>>  #define LGS_HA_INIT_STATE 0
>>
>> @@ -87,6 +95,12 @@ typedef struct lgs_cb {
>>      LGA_DOWN_LIST *lga_down_list_tail;
>>
>>      bool nid_started;       /**< true if started by NID */
>> +    SaUint32T scAbsenceAllowed; /* OpenSAF global configuration for
>> recovery handling */
>> +    lgs_state_t lgs_recovery_state; /* Indicate current recovery state
>> for the server */
>> +
>> +    // Initialize default value in contructor
>> +    lgs_cb() : lgs_recovery_state(LGS_NORMAL) {};
>> +
>>  } lgs_cb_t;
>>
>>  extern uint32_t lgs_cb_init(lgs_cb_t *);
>> diff --git a/osaf/services/saf/logsv/lgs/lgs_evt.cc
>> b/osaf/services/saf/logsv/lgs/lgs_evt.cc
>> --- a/osaf/services/saf/logsv/lgs/lgs_evt.cc
>> +++ b/osaf/services/saf/logsv/lgs/lgs_evt.cc
>> @@ -21,6 +21,7 @@
>>
>>  #include "lgs_mbcsv_v1.h"
>>  #include "lgs_mbcsv_v2.h"
>> +#include "lgs_recov.h"
>>
>>  /* Macro to validate the version */
>>  #define m_LOG_VER_IS_VALID(ver)   \
>> @@ -375,6 +376,8 @@ static uint32_t proc_lga_updn_mds_msg(lg
>>              break;
>>
>>      case LGSV_LGS_EVT_LGA_DOWN:
>> +            TRACE("%s: LGSV_LGS_EVT_LGA_DOWN mds_dest = %" PRIu64,
>> +                  __FUNCTION__, evt->fr_dest);
>>              if ((lgs_cb->ha_state == SA_AMF_HA_ACTIVE) || (lgs_cb-
>>ha_state ==
>> SA_AMF_HA_QUIESCED)) {
>>              /* Remove this LGA entry from our processing lists */
>>                      osaf_clock_gettime(CLOCK_REALTIME,
>&closetime_tspec);
>> @@ -772,11 +775,17 @@ static uint32_t lgs_ckpt_stream_open(lgs
>>
>>  /**
>>   * Create a new application stream
>> - * @param open_sync_param
>> - * @param o_stream
>> - * @return
>> + *
>> + * @param open_sync_param[in] Parameters used to create the stream
>> + * @param o_stream[out]       The created stream
>> + * @param create_object_f     IMM stream object is created
>> + *
>> + * @return AIS return code
>>   */
>> -static SaAisErrorT create_new_app_stream(lgsv_stream_open_req_t
>> *open_sync_param, log_stream_t **o_stream)
>> +SaAisErrorT create_new_app_stream(
>> +            lgsv_stream_open_req_t *open_sync_param,
>> +            log_stream_t **o_stream,
>> +            int creationFlag)
>>  {
>>      SaAisErrorT rc = SA_AIS_OK;
>>      log_stream_t *stream;
>> @@ -870,7 +879,7 @@ static SaAisErrorT create_new_app_stream
>>              goto done;
>>      }
>>
>> -    stream = log_stream_new(&open_sync_param->lstr_name,
>> +    stream = log_stream_new_1(&open_sync_param->lstr_name,
>>                              open_sync_param->logFileName,
>>                              open_sync_param->logFilePathName,
>>                              open_sync_param->maxLogFileSize,
>> @@ -878,7 +887,11 @@ static SaAisErrorT create_new_app_stream
>>                              open_sync_param->logFileFullAction,
>>                              open_sync_param->maxFilesRotated,
>>                              open_sync_param->logFileFmt,
>> -                            STREAM_TYPE_APPLICATION, STREAM_NEW,
>twelveHourModeFlag, 0);
>> +                            STREAM_TYPE_APPLICATION,
>> +                            STREAM_NEW,
>> +                            twelveHourModeFlag,
>> +                            0,
>> +                            creationFlag);
>>
>>      if (stream == NULL) {
>>              rc = SA_AIS_ERR_NO_MEMORY;
>> @@ -960,6 +973,7 @@ static uint32_t proc_stream_open_msg(lgs
>>      log_stream_t *logStream;
>>      char name[SA_MAX_NAME_LENGTH + 1];
>>      time_t file_closetime = 0;
>> +    int i_rc = 0;
>>
>>      /* Create null-terminated stream name */
>>      memcpy(name, open_sync_param->lstr_name.value,
>> open_sync_param->lstr_name.length);
>> @@ -981,10 +995,12 @@ static uint32_t proc_stream_open_msg(lgs
>>                      /* One of the well-known log streams */
>>                      if (open_sync_param->lstr_open_flags &
>SA_LOG_STREAM_CREATE) {
>>                              ais_rv = SA_AIS_ERR_INVALID_PARAM;
>> +                            rc = NCSCC_RC_FAILURE;
>>                              goto snd_rsp;
>>                      }
>>              }
>>      } else {
>> +            /* Stream does not exist */
>>              if (cb->immOiHandle == 0) {
>>                      TRACE("IMM service unavailable, open stream failed");
>>                      ais_rv = SA_AIS_ERR_TRY_AGAIN;
>> @@ -992,20 +1008,48 @@ static uint32_t proc_stream_open_msg(lgs
>>              }
>>
>>              if ((open_sync_param->lstr_open_flags &
>SA_LOG_STREAM_CREATE) == 0)
>> {
>> -                    ais_rv = SA_AIS_ERR_NOT_EXIST;
>> -                    goto snd_rsp;
>> +                    /* The stream does not exist but the create flag is not
>> +                     * set. If lgs_state is LGS_RECOVERY then:
>> +                     * Check if the stream is in the list of stream objects
>> +                     * not recovered. If in list, recover the stream and
>> +                     * add it to the client
>> +                     */
>> +                    if (lgs_cb->lgs_recovery_state == LGS_RECOVERY) {
>> +                            TRACE("%s LGS_RECOVERY",__FUNCTION__);
>> +                            i_rc = lgs_restore_one_app_stream(name,
>> +                                    open_sync_param->client_id,
>> +                                    &logStream);
>> +                            if (i_rc == -1) {
>> +                                    TRACE("%s lgs_restore_one_stream
>Fail", __FUNCTION__);
>> +                                    ais_rv = SA_AIS_ERR_NOT_EXIST;
>> +                                    goto snd_rsp;
>> +                            }
>> +                            TRACE("%s Stream %s is recovered",
>__FUNCTION__, name);
>> +                            log_stream_print(logStream); /* TRACE */
>> +                            lstr_id = logStream->streamId;
>> +                            goto snd_rsp;
>> +                    } else {
>> +                            /* Trying to open a non existing stream */
>> +                            TRACE("%s Attempt to open not existing
>stream", __FUNCTION__);
>> +                            ais_rv = SA_AIS_ERR_NOT_EXIST;
>> +                            goto snd_rsp;
>> +                    }
>>              }
>>
>>              /* Create the stream:
>>               *  - Check parameters
>>               *  - Create the stream in the stream "data base"
>>               *  - If active create IMM runtime object
>> +             *  - If recover do not create IMM object
>>               *
>>               * Note: Files are not created here
>>               */
>> -            ais_rv = create_new_app_stream(open_sync_param,
>&logStream);
>> -            if (ais_rv != SA_AIS_OK)
>> +            ais_rv = create_new_app_stream(open_sync_param,
>&logStream, 1);
>> +            if (ais_rv != SA_AIS_OK) {
>> +                    TRACE("%s create_new_app_stream Fail \"%s\"",
>> +                            __FUNCTION__, saf_error(ais_rv));
>>                      goto snd_rsp;
>> +            }
>>      }
>>
>>      /* Create the log files:
>> @@ -1030,7 +1074,7 @@ static uint32_t proc_stream_open_msg(lgs
>>              goto snd_rsp;
>>      }
>>
>> -    TRACE_4("logStream->streamId = %u", logStream->streamId);
>> +    TRACE_4("logStream->streamId = %u is created",
>> logStream->streamId);
>>      lstr_id = logStream->streamId;
>>
>>   snd_rsp:
>> diff --git a/osaf/services/saf/logsv/lgs/lgs_evt.h
>> b/osaf/services/saf/logsv/lgs/lgs_evt.h
>> --- a/osaf/services/saf/logsv/lgs/lgs_evt.h
>> +++ b/osaf/services/saf/logsv/lgs/lgs_evt.h
>> @@ -77,4 +77,9 @@ extern uint32_t lgs_remove_lga_down_rec(
>>  extern void lgs_send_write_log_ack(uint32_t client_id, SaInvocationT
>> invocation, SaAisErrorT error, MDS_DEST mds_dest);
>>  extern void lgs_free_write_log(const lgsv_write_log_async_req_t
>> *param);
>>
>> +SaAisErrorT create_new_app_stream(
>> +            lgsv_stream_open_req_t *open_sync_param,
>> +            log_stream_t **o_stream,
>> +            int creationFlag);
>> +
>>  #endif   /*!LGS_EVT_H */
>> diff --git a/osaf/services/saf/logsv/lgs/lgs_file.cc
>> b/osaf/services/saf/logsv/lgs/lgs_file.cc
>> --- a/osaf/services/saf/logsv/lgs/lgs_file.cc
>> +++ b/osaf/services/saf/logsv/lgs/lgs_file.cc
>> @@ -184,6 +184,11 @@ static void *file_hndl_thread(void *nopa
>>                              hndl_rc =
>own_log_files_by_group_hdl(lgs_com_data.indata_ptr,
>>                                              lgs_com_data.outdata_ptr,
>lgs_com_data.outdata_size);
>>                              break;
>> +                    case LGSF_GET_FILE_PAR:
>> +                            hndl_rc =
>lgs_get_file_params_hdl(lgs_com_data.indata_ptr,
>> +
>lgs_com_data.outdata_ptr,
>> +
>lgs_com_data.outdata_size);
>> +                            break;
>>                      default:
>>                              break;
>>                      }
>> diff --git a/osaf/services/saf/logsv/lgs/lgs_file.h
>> b/osaf/services/saf/logsv/lgs/lgs_file.h
>> --- a/osaf/services/saf/logsv/lgs/lgs_file.h
>> +++ b/osaf/services/saf/logsv/lgs/lgs_file.h
>> @@ -43,6 +43,7 @@ typedef enum {
>>      LGSF_CHECKPATH,
>>      LGSF_CHECKDIR,
>>      LGSF_OWN_LOGFILES,
>> +    LGSF_GET_FILE_PAR,
>>      LGSF_NOREQ
>>  }lgsf_treq_t;
>>
>> diff --git a/osaf/services/saf/logsv/lgs/lgs_filehdl.cc
>> b/osaf/services/saf/logsv/lgs/lgs_filehdl.cc
>> --- a/osaf/services/saf/logsv/lgs/lgs_filehdl.cc
>> +++ b/osaf/services/saf/logsv/lgs/lgs_filehdl.cc
>> @@ -23,7 +23,6 @@
>>  #include <dirent.h>
>>  #include <fcntl.h>
>>  #include <sys/stat.h>
>> -
>>  #include <unistd.h>
>>
>>  #include <logtrace.h>
>> @@ -731,3 +730,426 @@ done_exit:
>>      TRACE_LEAVE();
>>      return rc;
>>  }
>> +
>> +/*
>>
>******************************************************************
>**********
>> + * lgs_get_file_params_hdl() with help functions
>> + *
>> + * Find the file that was current log file before server down.
>> + * Get file size
>> + * Get last written record Id by reading the first characters of the
>> last
>> + * log record in the file
>> + *
>> + */
>> +
>> +/**
>> + * Count the occurrences  of character <c> in a string
>> + * Count from end of string and stop when lim <c> is found or
>> + * beginning of string
>> + *
>> + * @param str[in] '\0' terminated string to count characters in
>> + * @param c[in]   Character to count
>> + * @param lim[in] Stop count when lim characters found
>> + * @return number of occurrences
>> + */
>> +static int chr_cnt_b(char *str, char c, int lim)
>> +{
>> +    int cnt = 0;
>> +
>> +    if ((str == NULL) || (*str == '\0')) {
>> +            TRACE("%s: Parameter error", __FUNCTION__);
>> +            return 0;
>> +    }
>> +
>> +    char *ptr_str_end = strchr(str, '\0');
>> +    char *ptr_str_pos = ptr_str_end - 1;
>> +
>> +    while (1) {
>> +            if (*ptr_str_pos == c)
>> +                    cnt++;
>> +
>> +            /* End if beginning of file or char limit */
>> +            if ((ptr_str_pos == str) || (cnt >= lim))
>> +                    break;
>> +
>> +            ptr_str_pos--;
>> +    }
>> +
>> +    return cnt;
>> +}
>> +
>> +/**
>> + * Filter function used by scandir.
>> + * Find a current log file if it exist
>> + * - name as in file_name_find[]
>> + * - extension .log
>> + * - two timestamps (other log files has four)
>> + */
>> +/* Filename prefix (no timestamps or extension */
>> +static std::string file_name_find_g;
>> +static int filter_logfile_name(const struct dirent *finfo)
>> +{
>> +    bool name_found = false, ext_found = false;
>> +
>> +    if (strstr(finfo->d_name, file_name_find_g.c_str()) != NULL)
>> +            name_found = true;
>> +    if (strstr(finfo->d_name, ".log") != NULL)
>> +            ext_found = true;
>> +
>> +    return (int) (name_found && ext_found);
>> +}
>> +
>> +/**
>> + * Get name and size of log file containing the last record Id. Is
>> current log
>> + * file if not empty or last rotated if current log file is empty
>> + * Also give name of current log file if exist
>> + *
>> + * @param filepath_i[in]    Path to log file directory
>> + * @param filename_i[in]    Name prefix for file to search for
>> + * @param filename_o[out]   Name of file with Id. "" if no file
>> found
>> + * @param curname_o[out]    Name of current log  file or "" if no
>> current found
>> + * @param fsize[out]        Size of current log file
>> + * @return -1 on error filename_o is not valid
>> + */
>> +static int filename_get(
>> +    char *filepath_i, char *filename_i,
>> +    std::string &filename_o, std::string &curname_o,
>> +    uint32_t *fsize)
>> +{
>> +    int rc = 0;
>> +    int num_files = 0;
>> +    int i = 0;
>> +    struct dirent **namelist;
>> +    struct stat statbuf;
>> +    std::string file_path;
>> +    double time_tmp;
>> +    char *str_p = NULL;
>> +    int len = 0;
>> +    /* Time newest file */
>> +    double time_new = 0;
>> +    /* Index in namelist for newest and second newest file */
>> +    int name_ix_prv = 0, name_ix_new = 0;
>> +    /* Set to true if file is empty */
>> +    bool empty_flg_prv = true, empty_flg_new = true;
>> +
>> +    TRACE_ENTER();
>> +
>> +    // /* Initiate out data */
>> +    filename_o.clear();
>> +    curname_o.clear();
>> +    *fsize = 0;
>> +
>> +    /* Create a list of all .log files that has
>> +     * <filename_i> in <filepath_i>
>> +     */
>> +    file_name_find_g = filename_i;
>> +    num_files = scandir(filepath_i, &namelist, filter_logfile_name,
>> alphasort);
>> +    if (num_files == -1) {
>> +            TRACE("%s: scandir Fail %s", __FUNCTION__, strerror(errno));
>> +            rc = -1;
>> +            goto done;
>> +    }
>> +
>> +    if (num_files == 0) {
>> +            /* There is no log file at all */
>> +            TRACE("\t No log file at all found");
>> +            goto done_free;
>> +    }
>> +
>> +    /* Special case, only one file is found
>> +     */
>> +    if (num_files == 1) {
>> +            file_path = std::string(filepath_i) + "/" + namelist[0]->d_name;
>> +            if (stat(file_path.c_str(), &statbuf) == -1) {
>> +                    TRACE("%s: stat() Fail %s", __FUNCTION__,
>strerror(errno));
>> +                    rc = -1;
>> +                    goto done_free;
>> +            }
>> +
>> +            /* Save found file name */
>> +            filename_o = namelist[0]->d_name;
>> +
>> +            /* Handle current log file output */
>> +            goto done_hdl_cur;
>> +    }
>> +
>> +    /* Find the newest and the second newest file in the list
>> +     * Return in filename_o name of newest file if not empty else
>> +     * the second newest (if that also is empty return error)
>> +     */
>> +    time_new = time_tmp = 0;
>> +    name_ix_prv = name_ix_new = 0;
>> +    empty_flg_prv = empty_flg_new = false;
>> +
>> +    for (i = 0; i < num_files; i++) {
>> +            file_path = std::string(filepath_i) + "/" + namelist[i]->d_name;
>> +            if (stat(file_path.c_str(), &statbuf) == -1) {
>> +                    TRACE("%s: stat() Fail %s", __FUNCTION__,
>strerror(errno));
>> +                    rc = -1;
>> +                    goto done_free;
>> +            }
>> +
>> +            time_tmp = osaf_timespec_to_double(&statbuf.st_mtim);
>> +            if (time_tmp > time_new) {
>> +                    name_ix_prv = name_ix_new;
>> +                    name_ix_new = i;
>> +                    time_new = time_tmp;
>> +                    empty_flg_prv = empty_flg_new;
>> +                    if (statbuf.st_size == 0)
>> +                            empty_flg_new = true;
>> +                    else
>> +                            empty_flg_new = false;
>> +            }
>> +    }
>> +
>> +    /* Give found filename for output */
>> +    *fsize = 0;
>> +    if (empty_flg_new == false) {
>> +            /* Give the newest filename and its size. File is not empty */
>> +            filename_o = namelist[name_ix_new]->d_name;
>> +            *fsize = statbuf.st_size;
>> +    } else if (empty_flg_prv == false) {
>> +            /* Give the second newest filename. File is not empty */
>> +            filename_o = namelist[name_ix_prv]->d_name;
>> +    } else {
>> +            /* Both files are empty. This is an error */
>> +            TRACE("%s: Both newest and second newest are empy",
>__FUNCTION__);
>> +            filename_o.clear();
>> +            rc = -1;
>> +    }
>> +
>> +done_hdl_cur:
>> +    /* Handle current log file output */
>> +    len = strlen(filename_i);
>> +    str_p = namelist[name_ix_new]->d_name + len;
>> +    if (chr_cnt_b(str_p, '_', 4) == 2) {
>> +            /* Newest is current log file */
>> +            curname_o = namelist[name_ix_new]->d_name;
>> +    }
>> +
>> +done_free:
>> +    /* Free namelist */
>> +    for (i = 0; i < num_files; i++) {
>> +            free(namelist[i]);
>> +    }
>> +
>> +    free(namelist);
>> +
>> +done:
>> +    TRACE_LEAVE();
>> +    return rc;
>> +}
>> +
>> +/**
>> + * Get last record Id from the given file.
>> + * Each record begins with a record Id number. The wanted Id is the
>> last Id
>> + * in the file
>> + *
>> + * @param file_name[in] Complete path to the file
>> + * @return record Id or -1 on error. Set to 0 if no error but no Id
>> is found
>> + */
>> +static int record_id_get(const char *file_path)
>> +{
>> +    FILE *fd = NULL;
>> +    int id_rc = 0;
>> +    int i;
>> +    int c;
>> +    long endpos;
>> +
>> +    char *read_line = NULL;
>> +    size_t dummy_n = 0;
>> +    ssize_t line_len;
>> +
>> +    TRACE_ENTER();
>> +
>> +    /* Open the file */
>> +    while (1) {
>> +            fd = fopen(file_path, "r");
>> +            if (fd != NULL) {
>> +                    break;
>> +            } else if (errno != EINTR){
>> +                    TRACE("%s fopen Fail %s",
>> +                            __FUNCTION__, strerror(errno));
>> +                    id_rc = -1;
>> +                    goto done;
>> +            }
>> +    }
>> +
>> +    /* Get last pos in file */
>> +    while(1) {
>> +            if (fseek(fd, 0, SEEK_END) == -1) {
>> +                    if (errno == EINTR)
>> +                            continue;
>> +                    TRACE("\t %d fseek Fail %s",__LINE__, strerror(errno));
>> +                    id_rc = -1;
>> +                    goto done;
>> +            }
>> +            break;
>> +    }
>> +    endpos = ftell(fd);
>> +
>> +    if (endpos == 0) {
>> +            /* The file is empty. No Id to find */
>> +            id_rc = 0;
>> +            goto done;
>> +    }
>> +
>> +    /* Search from the end for '\n' (end of prev record)
>> +     * or beginning of file
>> +     */
>> +    for (i = 2; i < endpos; i++) {
>> +            while(1) {
>> +                    if (fseek(fd, -i, SEEK_END) == -1) {
>> +                            if (errno == EINTR)
>> +                                    continue;
>> +                            TRACE("\t %d fseek Fail %s",
>> +                                    __LINE__, strerror(errno));
>> +                            id_rc = -1;
>> +                            goto done;
>> +                    }
>> +                    break;
>> +            }
>> +
>> +            c = getc(fd);
>> +            if (c == '\n')
>> +                    break;
>> +    }
>> +
>> +    /* Get pos for line start */
>> +    c = getc(fd); /* Dummy read '\n' */
>> +
>> +    /* Read the last record and get record id */
>> +    line_len = getline(&read_line, &dummy_n, fd);
>> +    if (line_len == -1) {
>> +            TRACE("%s: getline Fail %s",
>> +                    __FUNCTION__, strerror(errno));
>> +            id_rc = -1;
>> +            goto done;
>> +    }
>> +    id_rc = atoi(read_line);
>> +    if (id_rc == 0) {
>> +            TRACE("%s: \"%s\" has no number. Id set to 0",
>> +                    __FUNCTION__, read_line);
>> +            id_rc = 0;
>> +            goto done_free;
>> +    }
>> +
>> +done_free:
>> +    free(read_line);
>> +
>> +done:
>> +    if (fd != NULL)
>> +            fclose(fd);
>> +
>> +    TRACE_LEAVE();
>> +    return id_rc;
>> +}
>> +
>> +/**
>> + * Get log file information:
>> + * - Name of current log file: <name prefix>_YYMMDD_HHMMSS
>> + * - Log record id
>> + *
>> + * Rules:
>> + * - If current log file not empty: Name = cur log file, Size = file
>> size,
>> + *                                  Id = fr file, rc = OK
>> + * - If current log file empty no rotated: Name = cur log file, Size
>> = 0,
>> + *                                         Id = 1, rc = OK
>> + * - If current log file empty is rotated: Name = cur log file, Size
>> = 0,
>> + *                                         Id = fr last rotated, rc =
>> OK
>> + * - If no log file at all:  Name = NULL, Size = 0, Id = 1, rc = OK
>> + * - If only rotated log file: Name = NULL, Size = 0, Id = fr rotated
>> file,
>> + *                             rc = OK
>> + *
>> + * @param indata[in]      gfp_in_t
>> + *        file_name: File name prefix (name part before time stamps)
>> + *        file_path: Full path to directory root path + rel path
>> + *
>> + * @param outdata[out]    gfp_out_t
>> + *        curFileName: Current file name <name prefix>_YYMMDD_HHMMSS
>> + *        curFileSize: Bytes written to current log file (file size)
>> + *        logRecordId: log record identifier for last written log
>> record
>> +
>> + * @param max_outsize[in] sizeof gfp_out_t (not used)
>> + *
>> + * @return (-1) on error, out data not valid
>> + */
>> +int lgs_get_file_params_hdl(void *indata, void *outdata, size_t
>> max_outsize)
>> +{
>> +    gfp_in_t *par_in = static_cast<gfp_in_t *>(indata);
>> +    gfp_out_t *par_out = static_cast<gfp_out_t *>(outdata);
>> +    int rc = 0, int_rc = 0;
>> +    std::string file_name;
>> +    std::string file_name_cur;
>> +    std::string file_path;
>> +    int rec_id = 0;
>> +    char *ptr_str;
>> +
>> +    uint32_t file_size = 0;
>> +
>> +    TRACE_ENTER();
>> +
>> +    osaf_mutex_unlock_ordie(&lgs_ftcom_mutex); /* UNLOCK  Critical
>> section */
>> +
>> +    /* Initialize out parameters */
>> +    par_out->curFileName = NULL;
>> +    par_out->curFileSize = 0;
>> +    par_out->logRecordId = 0;
>> +
>> +    /* Get log file to get info from and its size */
>> +    int_rc = filename_get(
>> +            par_in->file_path, par_in->file_name,
>> +            file_name, file_name_cur, &file_size
>> +            );
>> +    if (int_rc == -1) {
>> +            TRACE("%s: filename_get Fail",__FUNCTION__);
>> +            rc = -1;
>> +            goto done;
>> +    }
>> +
>> +    if (file_name[0] == '\0') {
>> +            TRACE("No file found.");
>> +            rc = -1;
>> +            par_out->logRecordId = 0;
>> +            goto done;
>> +    }
>> +
>> +    /* Create the file path */
>> +    file_path = std::string(par_in->file_path) + "/" + file_name;
>> +
>> +    /* Find record id in file */
>> +    rec_id = record_id_get(file_path.c_str());
>> +    if (rec_id == -1) {
>> +            TRACE("%s: record_id_get Fail", __FUNCTION__);
>> +            rc = -1;
>> +            goto done;
>> +    }
>> +
>> +    /* Fill in out data */
>> +    par_out->logRecordId = rec_id;
>> +    par_out->curFileSize = file_size;
>> +    if (file_name_cur.empty() == false) {
>> +            // This memory will be deleted in
>log_stream_open_file_restore()
>> +            // who wants to get the info from this memory -
>> par_out->curFileName
>> +            par_out->curFileName = static_cast<char *>(
>> +                    calloc(1, file_name_cur.size() + 1));
>> +            if (par_out->curFileName == NULL) {
>> +                    LOG_ER("%s Failed to allocate memory",
>__FUNCTION__);
>> +                    rc = -1;
>> +                    goto done;
>> +            }
>> +
>> +            strcpy(par_out->curFileName, file_name_cur.c_str());
>> +            /* Remove extension */
>> +            ptr_str = strstr(par_out->curFileName, ".log");
>> +            if (ptr_str == NULL) {
>> +                    TRACE("%s: Could not find .log extension Fail",
>__FUNCTION__);
>> +                    rc = -1;
>> +            }
>> +            *ptr_str = '\0';
>> +    }
>> +
>> +done:
>> +    osaf_mutex_lock_ordie(&lgs_ftcom_mutex); /* LOCK after critical
>> section */
>> +    TRACE_LEAVE2("rc = %d", rc);
>> +    return rc;
>> +}
>> diff --git a/osaf/services/saf/logsv/lgs/lgs_filehdl.h
>> b/osaf/services/saf/logsv/lgs/lgs_filehdl.h
>> --- a/osaf/services/saf/logsv/lgs/lgs_filehdl.h
>> +++ b/osaf/services/saf/logsv/lgs/lgs_filehdl.h
>> @@ -155,6 +155,26 @@ typedef struct {
>>   * No out parameters
>>   */
>>
>> +/*
>> + * lgs_get_file_params_hdl(...)
>> + * Ret code -1 if error
>> + */
>> +/* IN params */
>> +typedef struct {
>> +    /* File name prefix (name part before time stamps) */
>> +    char *file_name;
>> +    /* Full path to directory root path + rel path */
>> +    char *file_path;
>> +} gfp_in_t;
>> +
>> +/* OUT params */
>> +typedef struct {
>> +    char *curFileName;
>> +    uint32_t curFileSize;   /* Bytes written to current log file */
>> +    uint32_t logRecordId;   /* log record identifier increased for each
>> record */
>> +} gfp_out_t;
>> +
>> +
>>  int path_is_writeable_dir_hdl(void *indata, void *outdata, size_t
>> max_outsize);
>>  int check_path_exists_hdl(void *indata, void *outdata, size_t
>> max_outsize);
>>  int rename_file_hdl(void *indata, void *outdata, size_t
>> max_outsize);
>> @@ -166,6 +186,7 @@ int fileclose_hdl(void *indata, void *ou
>>  int delete_file_hdl(void *indata, void *outdata, size_t
>> max_outsize);
>>  int get_number_of_log_files_hdl(void *indata, void *outdata, size_t
>> max_outsize);
>>  int own_log_files_by_group_hdl(void *indata, void *outdata, size_t
>> max_outsize);
>> +int lgs_get_file_params_hdl(void *indata, void *outdata, size_t
>> max_outsize);
>>
>>  #endif      /* LGS_FILEHDL_H */
>>
>> diff --git a/osaf/services/saf/logsv/lgs/lgs_imm.cc
>> b/osaf/services/saf/logsv/lgs/lgs_imm.cc
>> --- a/osaf/services/saf/logsv/lgs/lgs_imm.cc
>> +++ b/osaf/services/saf/logsv/lgs/lgs_imm.cc
>> @@ -42,6 +42,7 @@
>>  #include "lgs.h"
>>  #include "lgs_util.h"
>>  #include "lgs_file.h"
>> +#include "lgs_recov.h"
>>  #include "lgs_config.h"
>>  #include "saf_error.h"
>>
>> @@ -2507,7 +2508,8 @@ done:
>>   * @return SaAisErrorT
>>   */
>>  static SaAisErrorT stream_create_and_configure(const char *dn,
>> -            log_stream_t **in_stream, int stream_id,
>SaImmAccessorHandleT
>> accessorHandle)
>> +            log_stream_t **in_stream, int stream_id,
>> +            SaImmAccessorHandleT accessorHandle)
>>  {
>>      SaAisErrorT rc = SA_AIS_OK;
>>      SaNameT objectName;
>> @@ -2606,6 +2608,15 @@ static SaAisErrorT stream_create_and_con
>>              } else if (!strcmp(attribute->attrName,
>> "saLogStreamSeverityFilter")) {
>>                      stream->severityFilter = *((SaUint32T *)value);
>>                      TRACE("severityFilter: %u", stream->severityFilter);
>> +            } else if (!strcmp(attribute->attrName,
>> "saLogStreamCreationTimestamp")) {
>> +                    if (attribute->attrValuesNumber != 0) {
>> +                            /* Restore creation timestamp if exist
>> +                             * Note: Creation timestamp in stream is set to
>> +                             * current time which will be the value if no
>> +                             * value found in object
>> +                             */
>> +                            stream->creationTimeStamp =
>*(static_cast<SaTimeT *>(value));
>> +                    }
>>              }
>>      }
>>
>> @@ -2648,11 +2659,15 @@ static const SaImmOiCallbacksT_2 callbac
>>   * IMM-OM interface and initialize the corresponding information
>>   * in the LOG control block. Initialize the LOG IMM-OI
>>   * interface. Become class implementer.
>> + *
>> + * @param immOiHandle[in]
>> + * @return
>>   */
>> -SaAisErrorT lgs_imm_create_configStream(lgs_cb_t *cb)
>> +SaAisErrorT lgs_imm_init_configStreams(lgs_cb_t *cb)
>>  {
>> -    SaAisErrorT rc = SA_AIS_OK;
>> +    SaAisErrorT ais_rc = SA_AIS_OK;
>>      SaAisErrorT om_rc;
>> +    int int_rc = 0;
>>      log_stream_t *stream;
>>      SaImmHandleT omHandle;
>>      SaImmAccessorHandleT accessorHandle;
>> @@ -2685,9 +2700,13 @@ SaAisErrorT lgs_imm_create_configStream(
>>                      &immSearchHandle)) == SA_AIS_OK) {
>>
>>              while (immutil_saImmOmSearchNext_2(immSearchHandle,
>&objectName,
>> &attributes) == SA_AIS_OK) {
>> -                    if ((rc = stream_create_and_configure((char*)
>objectName.value,
>> -                                    &stream, streamId, accessorHandle)) !=
>SA_AIS_OK) {
>> -                            LOG_ER("stream_create_and_configure failed
>%d", rc);
>> +                    /* Note: Here is creationTimeStamp and severityFilter
>set
>> +                     * Can be recovered if scAbseceAllowed
>> +                     */
>> +                    ais_rc = stream_create_and_configure((char*)
>objectName.value,
>> +                                    &stream, streamId, accessorHandle);
>> +                    if (ais_rc != SA_AIS_OK) {
>> +                            LOG_WA("stream_create_and_configure failed
>%d", ais_rc);
>>                              goto done;
>>                      }
>>                      streamId += 1;
>> @@ -2709,12 +2728,35 @@ SaAisErrorT lgs_imm_create_configStream(
>>
>>      stream = log_stream_getnext_by_name(NULL);
>>      while (stream != NULL) {
>> -            (void)immutil_update_one_rattr(cb->immOiHandle, stream-
>>name,
>> -
>> const_cast<SaImmAttrNameT>("saLogStreamCreationTimestamp"),
>> -                                           SA_IMM_ATTR_SATIMET,
>> -                                           &stream->creationTimeStamp);
>> -
>> -            log_stream_open_fileinit(stream);
>> +            if (cb->scAbsenceAllowed != 0) {
>> +                    /**
>> +                     * This code to make LOG distinguish b/w headless and
>cluster
>> start-up/restarts
>> +                     * 1) If data reading from IMM differs with default
>ones, headless
>> just occurs
>> +                     * 2) If data reading from IMM equals to default ones,
>continue
>> checking:
>> +                     *  2.1) If info in cfg file are equal to data reading 
>> from
>IMM,
>> can reuse the cfg/log files
>> +                     *  2.2) If info in cfg are not equal to, can not re-use
>cfg/log
>> file. Creating new ones instead.
>> +                     */
>> +                    int_rc = log_stream_open_file_restore(stream);
>> +                    if (int_rc == -1) {
>> +                            /* Restore failed. Initialize instead */
>> +                            LOG_NO("%s: log_stream_open_file_restore
>Fail", __FUNCTION__);
>> +                            log_stream_open_fileinit(stream);
>> +                            stream->creationTimeStamp =
>lgs_get_SaTime();
>> +                    }
>> +            } else {
>> +                    /* Always create new files and set current timestamp
>to
>> +                     * current time
>> +                     */
>> +                    log_stream_open_fileinit(stream);
>> +                    stream->creationTimeStamp = lgs_get_SaTime();
>> +            }
>> +
>> +            (void)immutil_update_one_rattr(
>> +                    cb->immOiHandle, stream->name,
>> +
>       const_cast<SaImmAttrNameT>("saLogStreamCreationTimestamp"),
>> +                    SA_IMM_ATTR_SATIMET,
>> +                    &stream->creationTimeStamp);
>> +
>>              stream = log_stream_getnext_by_name(stream->name);
>>      }
>>
>> @@ -2740,7 +2782,7 @@ SaAisErrorT lgs_imm_create_configStream(
>>      immutilWrapperProfile.errorsAreFatal = errorsAreFatal; /* Enable
>> again */
>>
>>      TRACE_LEAVE();
>> -    return rc;
>> +    return ais_rc;
>>  }
>>
>>  /**
>> @@ -2951,3 +2993,476 @@ void lgs_imm_impl_reinit_nonblocking(lgs
>>
>>      TRACE_LEAVE();
>>  }
>> +
>>
>+/****************************************************************
>**************
>> + * Functions used for recovery handling
>> +
>>
>******************************************************************
>************/
>> +/**
>> + * Search for old runtime stream objects and put their names in a
>> list.
>> + * Become OI for the runtime stream class if any objects found
>> + *
>> + * @param object_list
>> + */
>> +void lgs_search_stream_objects(void)
>> +{
>> +    int rc = 0;
>> +    SaAisErrorT ais_rc = SA_AIS_OK;
>> +    SaImmHandleT immOmHandle;
>> +    SaImmSearchHandleT immSearchHandle;
>> +    const char* class_name = "SaLogStream";
>> +
>> +    TRACE_ENTER();
>> +
>> +    /* Save immutil settings and reconfigure immutil
>> +     */
>> +    struct ImmutilWrapperProfile tmp_immutilWrapperProfile;
>> +    tmp_immutilWrapperProfile.errorsAreFatal =
>> immutilWrapperProfile.errorsAreFatal;
>> +    tmp_immutilWrapperProfile.nTries = immutilWrapperProfile.nTries;
>> +    tmp_immutilWrapperProfile.retryInterval =
>> immutilWrapperProfile.retryInterval;
>> +
>> +    immutilWrapperProfile.errorsAreFatal = 0;
>> +    immutilWrapperProfile.nTries = 500;
>> +    immutilWrapperProfile.retryInterval = 1000;
>> +
>> +
>> +    /* Intialize Om API
>> +     */
>> +    ais_rc = immutil_saImmOmInitialize(&immOmHandle, NULL,
>> &immVersion);
>> +    if (ais_rc != SA_AIS_OK) {
>> +            LOG_WA("%s saImmOmInitialize FAIL %d", __FUNCTION__,
>ais_rc);
>> +            goto done;
>> +    }
>> +
>> +    /* Initialize search for application stream runtime objects
>> +     * Search for all objects of class 'SaLogStream'
>> +     * Search criteria:
>> +     * Attribute SaImmAttrClassName == SaLogStream
>> +     */
>> +    SaImmSearchParametersT_2 searchParam;
>> +    searchParam.searchOneAttr.attrName = const_cast<char
>> *>("SaImmAttrClassName");
>> +    searchParam.searchOneAttr.attrValueType =
>SA_IMM_ATTR_SASTRINGT;
>> +    searchParam.searchOneAttr.attrValue = &class_name;
>> +    SaNameT root_name;
>> +    root_name.value[0] = '\0';
>> +    root_name.length = 1;
>> +
>> +    ais_rc = immutil_saImmOmSearchInitialize_2(
>> +                    immOmHandle,
>> +                    &root_name,
>> +                    SA_IMM_SUBTREE,
>> +                    SA_IMM_SEARCH_ONE_ATTR |
>SA_IMM_SEARCH_GET_NO_ATTR,
>> +                    &searchParam,
>> +                    NULL,
>> +                    &immSearchHandle);
>> +    if (ais_rc != SA_AIS_OK) {
>> +            LOG_WA("%s saImmOmSearchInitialize FAIL %d",
>__FUNCTION__,
>> ais_rc);
>> +            goto done_fin_Om;
>> +    }
>> +
>> +    /* Iterate the search and save objects in list until all objects
>> found
>> +     */
>> +    SaNameT object_name;
>> +    SaImmAttrValuesT_2 **attributes;
>> +
>> +    ais_rc = immutil_saImmOmSearchNext_2(immSearchHandle,
>&object_name,
>> &attributes);
>> +    if (ais_rc == SA_AIS_ERR_NOT_EXIST) {
>> +            TRACE("\tNo objects found");
>> +    }
>> +
>> +    while (ais_rc == SA_AIS_OK) {
>> +            TRACE("\tFound object \"%s\"", reinterpret_cast<char
>> *>(object_name.value));
>> +            /* Add the string to the list
>> +             */
>> +            rc = log_rtobj_list_add(reinterpret_cast<char
>> *>(object_name.value));
>> +            if (rc == -1) {
>> +                    TRACE("%s Could not add %s to list Fail",
>> +                          __FUNCTION__, reinterpret_cast<char
>*>(object_name.value));
>> +            }
>> +
>> +            /* Get next object */
>> +            ais_rc = immutil_saImmOmSearchNext_2(immSearchHandle,
>> +                    &object_name, &attributes);
>> +    }
>> +    if (ais_rc == SA_AIS_ERR_NOT_EXIST) {
>> +            TRACE("\tAll objects found OK");
>> +    } else {
>> +            LOG_WA("\t%s saImmOmSearchNext FAILED %d",
>__FUNCTION__, ais_rc);
>> +    }
>> +
>> +    /* Finalize the serach API
>> +     */
>> +    ais_rc = immutil_saImmOmSearchFinalize(immSearchHandle);
>> +    if (ais_rc != SA_AIS_OK) {
>> +            TRACE("\tsaImmOmSearchFinalize FAIL %d", ais_rc);
>> +    }
>> +
>> +done_fin_Om:
>> +    /* Finalize the Om API
>> +     */
>> +    ais_rc = immutil_saImmOmFinalize(immOmHandle);
>> +    if (ais_rc != SA_AIS_OK) {
>> +            TRACE("\tsaImmOmFinalize FAIL %d", ais_rc);
>> +    }
>> +
>> +done:
>> +    /* Restore immutil settings */
>> +    immutilWrapperProfile.errorsAreFatal =
>> tmp_immutilWrapperProfile.errorsAreFatal;
>> +    immutilWrapperProfile.nTries = tmp_immutilWrapperProfile.nTries;
>> +    immutilWrapperProfile.retryInterval =
>> tmp_immutilWrapperProfile.retryInterval;
>> +
>> +    TRACE_LEAVE();
>> +}
>> +
>> +void lgs_delete_one_stream_object(char *name_str)
>> +{
>> +    SaAisErrorT ais_rc = SA_AIS_OK;
>> +    SaNameT object_name;
>> +
>> +    if (name_str == NULL) {
>> +            TRACE("%s No object name given", __FUNCTION__);
>> +            return;
>> +    }
>> +
>> +    /* Save immutil settings and reconfigure */
>> +    struct ImmutilWrapperProfile tmp_immutilWrapperProfile;
>> +    tmp_immutilWrapperProfile.errorsAreFatal =
>> immutilWrapperProfile.errorsAreFatal;
>> +    tmp_immutilWrapperProfile.nTries = immutilWrapperProfile.nTries;
>> +    tmp_immutilWrapperProfile.retryInterval =
>> immutilWrapperProfile.retryInterval;
>> +
>> +    immutilWrapperProfile.errorsAreFatal = 0;
>> +    immutilWrapperProfile.nTries = 500;
>> +    immutilWrapperProfile.retryInterval = 1000;
>> +
>> +    /* Copy name to a SaNameT */
>> +    (void) strncpy(reinterpret_cast<char *>(object_name.value),
>> +                   name_str, SA_MAX_NAME_LENGTH);
>> +    object_name.length = strlen(name_str) + 1;
>> +
>> +    /* and delete the object */
>> +    ais_rc = immutil_saImmOiRtObjectDelete(lgs_cb->immOiHandle,
>> &object_name);
>> +    if (ais_rc == SA_AIS_OK) {
>> +            TRACE("%s Object \"%s\" deleted", __FUNCTION__,
>> +                  reinterpret_cast<char *>(object_name.value));
>> +    } else {
>> +            LOG_WA("%s saImmOiRtObjectDelete for \"%s\" FAILED %d",
>> +                   __FUNCTION__, reinterpret_cast<char
>*>(object_name.value),
>> ais_rc);
>> +    }
>> +
>> +    /* Restore immutil settings */
>> +    immutilWrapperProfile.errorsAreFatal =
>> tmp_immutilWrapperProfile.errorsAreFatal;
>> +    immutilWrapperProfile.nTries = tmp_immutilWrapperProfile.nTries;
>> +    immutilWrapperProfile.retryInterval =
>> tmp_immutilWrapperProfile.retryInterval;
>> +}
>> +
>> +/**
>> + * Delete all stream objects in the stream object list.
>> + * See also: lgs_search_stream_objects()
>> + *
>> + */
>> +void lgs_clean_stream_objects(void)
>> +{
>> +    SaAisErrorT ais_rc = SA_AIS_OK;
>> +    int pos = 0;
>> +    char *name_str;
>> +    SaNameT object_name;
>> +
>> +    TRACE_ENTER();
>> +    /* Check if there are any objects to delete. If not do nothing  */
>> +    if (log_rtobj_list_no() <= 0) {
>> +            TRACE("%s\t No objects to delete is found", __FUNCTION__);
>> +            return;
>> +    }
>> +
>> +    /* Save immutil settings and reconfigure */
>> +    struct ImmutilWrapperProfile tmp_immutilWrapperProfile;
>> +    tmp_immutilWrapperProfile.errorsAreFatal =
>> immutilWrapperProfile.errorsAreFatal;
>> +    tmp_immutilWrapperProfile.nTries = immutilWrapperProfile.nTries;
>> +    tmp_immutilWrapperProfile.retryInterval =
>> immutilWrapperProfile.retryInterval;
>> +
>> +    immutilWrapperProfile.errorsAreFatal = 0;
>> +    immutilWrapperProfile.nTries = 500;
>> +    immutilWrapperProfile.retryInterval = 1000;
>> +
>> +    pos = log_rtobj_list_getnamepos();
>> +    while (pos != -1) {
>> +            /* Get found name */
>> +            name_str = log_rtobj_list_getname(pos);
>> +
>> +            /* Delete the object if in object list. Note this is an Oi
>> operation
>> +             * Remove name from list
>> +             */
>> +            if (name_str != NULL) {
>> +                    /* Copy name to a SaNameT */
>> +                    (void) strncpy(reinterpret_cast<char
>*>(object_name.value),
>> +                                   name_str, SA_MAX_NAME_LENGTH);
>> +                    object_name.length = strlen(name_str) + 1;
>> +                    /* and delete the object */
>> +                    ais_rc = immutil_saImmOiRtObjectDelete(lgs_cb-
>>immOiHandle,
>> +                            &object_name);
>> +                    if (ais_rc == SA_AIS_OK) {
>> +                            TRACE("\tObject \"%s\" deleted",
>> +                                  reinterpret_cast<char
>*>(object_name.value));
>> +                    } else {
>> +                            LOG_WA("%s saImmOiRtObjectDelete for
>\"%s\" FAILED %d",
>> +                                   __FUNCTION__,
>> +                                   reinterpret_cast<char
>*>(object_name.value), ais_rc);
>> +                    }
>> +            } else {
>> +                    /* Should never happen! */
>> +                    TRACE("%s\tFound name has NULL pointer!",
>__FUNCTION__);
>> +            }
>> +            /* Remove deleted object name from list */
>> +            log_rtobj_list_erase_one_pos(pos);
>> +
>> +            /* Get next object */
>> +            pos = log_rtobj_list_getnamepos();
>> +    }
>> +
>> +    /* Restore immutil settings */
>> +    immutilWrapperProfile.errorsAreFatal =
>> tmp_immutilWrapperProfile.errorsAreFatal;
>> +    immutilWrapperProfile.nTries = tmp_immutilWrapperProfile.nTries;
>> +    immutilWrapperProfile.retryInterval =
>> tmp_immutilWrapperProfile.retryInterval;
>> +
>> +    TRACE_LEAVE();
>> +}
>> +
>> +/**
>> + * Get cached stream attributes for given object name
>> + *
>> + * @param attrib_out[out] Pointer to a NULL terminated
>> SaImmAttrValuesT_2 vector
>> + * @param object_name[in]  String containing the object name
>> + * @param immOmHandle[out]
>> + * @return -1 on error
>> + */
>> +int lgs_get_streamobj_attr(SaImmAttrValuesT_2 ***attrib_out, char
>> *object_name_in,
>> +    SaImmHandleT *immOmHandle)
>> +{
>> +    int rc = 0;
>> +    SaAisErrorT ais_rc = SA_AIS_OK;
>> +    SaImmAccessorHandleT accessorHandle;
>> +    char *attribute_names[] = {
>> +            const_cast<char *>("saLogStreamFileName"),
>> +            const_cast<char *>("saLogStreamPathName"),
>> +            const_cast<char *>("saLogStreamMaxLogFileSize"),
>> +            const_cast<char *>("saLogStreamFixedLogRecordSize"),
>> +            const_cast<char *>("saLogStreamHaProperty"),
>> +            const_cast<char *>("saLogStreamLogFullAction"),
>> +            const_cast<char *>("saLogStreamMaxFilesRotated"),
>> +            const_cast<char *>("saLogStreamLogFileFormat"),
>> +            const_cast<char *>("saLogStreamSeverityFilter"),
>> +            const_cast<char *>("saLogStreamCreationTimestamp"),
>> +            NULL
>> +    };
>> +
>> +    TRACE_ENTER2("object_name_in \"%s\"", object_name_in);
>> +
>> +    SaNameT object_name;
>> +
>> +    /* Save immutil settings and reconfigure */
>> +    struct ImmutilWrapperProfile tmp_immutilWrapperProfile;
>> +    tmp_immutilWrapperProfile.errorsAreFatal =
>> immutilWrapperProfile.errorsAreFatal;
>> +    tmp_immutilWrapperProfile.nTries = immutilWrapperProfile.nTries;
>> +    tmp_immutilWrapperProfile.retryInterval =
>> immutilWrapperProfile.retryInterval;
>> +
>> +    immutilWrapperProfile.errorsAreFatal = 0;
>> +    immutilWrapperProfile.nTries = 500;
>> +    immutilWrapperProfile.retryInterval = 1000;
>> +
>> +    if (object_name_in == NULL) {
>> +            TRACE("%s No object name given (NULL)", __FUNCTION__);
>> +            rc = -1;
>> +            goto done;
>> +    }
>> +
>> +    /* Initialize Om API
>> +     */
>> +    ais_rc = immutil_saImmOmInitialize(immOmHandle, NULL,
>&immVersion);
>> +    if (ais_rc != SA_AIS_OK) {
>> +            LOG_WA("\t%s saImmOmInitialize FAIL %d", __FUNCTION__,
>ais_rc);
>> +            rc = -1;
>> +            goto done;
>> +    }
>> +
>> +    /* Initialize accessor for reading attributes
>> +     */
>> +    ais_rc = immutil_saImmOmAccessorInitialize(*immOmHandle,
>> &accessorHandle);
>> +    if (ais_rc != SA_AIS_OK) {
>> +            TRACE("%s\t saImmOmAccessorInitialize Fail '%s'",
>> +                    __FUNCTION__, saf_error(ais_rc));
>> +            rc = -1;
>> +            goto done;
>> +    }
>> +
>> +    strncpy(reinterpret_cast<char *>(object_name.value),
>> +            object_name_in, SA_MAX_NAME_LENGTH);
>> +    object_name.length = strlen(reinterpret_cast<char
>> *>(object_name.value)) + 1;
>> +
>> +    ais_rc = immutil_saImmOmAccessorGet_2(accessorHandle,
>&object_name,
>> +                    attribute_names, attrib_out);
>> +    if (ais_rc != SA_AIS_OK) {
>> +            TRACE("%s\t saImmOmAccessorGet_2 Fail '%s'",
>> +                    __FUNCTION__, saf_error(ais_rc));
>> +            rc = -1;
>> +            goto done_fin_Om;
>> +    } else {
>> +            goto done;
>> +    }
>> +
>> +done_fin_Om:
>> +    /* Free resources if fail */
>> +    ais_rc = immutil_saImmOmFinalize(*immOmHandle);
>> +    if (ais_rc != SA_AIS_OK) {
>> +            TRACE("%s\t saImmOmFinalize Fail '%s'",
>> +                    __FUNCTION__, saf_error(ais_rc));
>> +    }
>> +
>> +done:
>> +    /* Restore immutil settings */
>> +    immutilWrapperProfile.errorsAreFatal =
>> tmp_immutilWrapperProfile.errorsAreFatal;
>> +    immutilWrapperProfile.nTries = tmp_immutilWrapperProfile.nTries;
>> +    immutilWrapperProfile.retryInterval =
>> tmp_immutilWrapperProfile.retryInterval;
>> +
>> +    TRACE_LEAVE();
>> +    return rc;
>> +}
>> +
>> +/**
>> + * Free resources claimed when calling lgs_get_streamobj_attr()
>> + *
>> + * @param immHandle[in]
>> + * @return -1 on error
>> + */
>> +int lgs_free_streamobj_attr(SaImmHandleT immOmHandle)
>> +{
>> +    int rc = 0;
>> +    SaAisErrorT ais_rc = SA_AIS_OK;
>> +
>> +    TRACE_ENTER();
>> +
>> +    /* Save immutil settings and reconfigure */
>> +    struct ImmutilWrapperProfile tmp_immutilWrapperProfile;
>> +    tmp_immutilWrapperProfile.errorsAreFatal =
>> immutilWrapperProfile.errorsAreFatal;
>> +    tmp_immutilWrapperProfile.nTries = immutilWrapperProfile.nTries;
>> +    tmp_immutilWrapperProfile.retryInterval =
>> immutilWrapperProfile.retryInterval;
>> +
>> +    immutilWrapperProfile.errorsAreFatal = 0;
>> +    immutilWrapperProfile.nTries = 500;
>> +    immutilWrapperProfile.retryInterval = 1000;
>> +
>> +    ais_rc = immutil_saImmOmFinalize(immOmHandle);
>> +    if (ais_rc != SA_AIS_OK) {
>> +            TRACE("%s\t saImmOmFinalize Fail '%s'",
>> +                    __FUNCTION__, saf_error(ais_rc));
>> +            rc = -1;
>> +    }
>> +
>> +    /* Restore immutil settings */
>> +    immutilWrapperProfile.errorsAreFatal =
>> tmp_immutilWrapperProfile.errorsAreFatal;
>> +    immutilWrapperProfile.nTries = tmp_immutilWrapperProfile.nTries;
>> +    immutilWrapperProfile.retryInterval =
>> tmp_immutilWrapperProfile.retryInterval;
>> +
>> +    TRACE_LEAVE();
>> +    return rc;
>> +}
>> +
>> +/**
>> + * Read the scAbsenceAllowed attribute in
>> + * opensafImm=opensafImm,safApp=safImmService object.
>> + * No value means that "absence handling" is not allowed. For Log
>> this means
>> + * that no recovery shall be done.
>> + *
>> + * @param attr_val[out] Value read from scAbsenceAllowed attribute. 0
>> = No value
>> + * @return Pointer to attr_val if value is read. NULL if no value. If
>> NULL the
>> + *         value in attr_val is not valid
>> + */
>> +SaUint32T *lgs_get_scAbsenceAllowed_attr(SaUint32T *attr_val)
>> +{
>> +    SaUint32T *rc_attr_val = NULL;
>> +    SaAisErrorT ais_rc = SA_AIS_OK;
>> +    SaImmAccessorHandleT accessorHandle;
>> +    SaImmHandleT immOmHandle;
>> +    SaImmAttrValuesT_2 *attribute;
>> +    SaImmAttrValuesT_2 **attributes;
>> +
>> +    TRACE_ENTER();
>> +    char *attribute_names[] = {
>> +            const_cast<char *>("scAbsenceAllowed"),
>> +            NULL
>> +    };
>> +    char object_name_str[] =
>> "opensafImm=opensafImm,safApp=safImmService";
>> +
>> +    SaNameT object_name;
>> +    strncpy(reinterpret_cast<char *>(object_name.value),
>> +            object_name_str, SA_MAX_NAME_LENGTH);
>> +    object_name.length = strlen(reinterpret_cast<char
>> *>(object_name.value)) + 1;
>> +
>> +    /* Default restore handling shall be disabled. Is enabled if the
>> +     * scAbsenceAllowed attribute is not empty
>> +     */
>> +    *attr_val = 0;
>> +
>> +    /* Save immutil settings and reconfigure */
>> +    struct ImmutilWrapperProfile tmp_immutilWrapperProfile;
>> +    tmp_immutilWrapperProfile.errorsAreFatal =
>> immutilWrapperProfile.errorsAreFatal;
>> +    tmp_immutilWrapperProfile.nTries = immutilWrapperProfile.nTries;
>> +    tmp_immutilWrapperProfile.retryInterval =
>> immutilWrapperProfile.retryInterval;
>> +
>> +    immutilWrapperProfile.errorsAreFatal = 0;
>> +    immutilWrapperProfile.nTries = 500;
>> +    immutilWrapperProfile.retryInterval = 1000;
>> +
>> +    /* Initialize Om API
>> +     */
>> +    ais_rc = immutil_saImmOmInitialize(&immOmHandle, NULL,
>> &immVersion);
>> +    if (ais_rc != SA_AIS_OK) {
>> +            LOG_WA("\t%s saImmOmInitialize FAIL %d", __FUNCTION__,
>ais_rc);
>> +            goto done;
>> +    }
>> +
>> +    /* Initialize accessor for reading attributes
>> +     */
>> +    ais_rc = immutil_saImmOmAccessorInitialize(immOmHandle,
>> &accessorHandle);
>> +    if (ais_rc != SA_AIS_OK) {
>> +            TRACE("%s\t saImmOmAccessorInitialize Fail '%s'",
>> +                    __FUNCTION__, saf_error(ais_rc));
>> +            goto done;
>> +    }
>> +
>> +
>> +    ais_rc = immutil_saImmOmAccessorGet_2(accessorHandle,
>&object_name,
>> +                    attribute_names, &attributes);
>> +    if (ais_rc != SA_AIS_OK) {
>> +            TRACE("%s\t saImmOmAccessorGet_2 Fail '%s'",
>> +                    __FUNCTION__, saf_error(ais_rc));
>> +            goto done_fin_Om;
>> +    }
>> +
>> +    void *value;
>> +
>> +    /* Handle the global scAbsenceAllowed_flag */
>> +    attribute = attributes[0];
>> +    TRACE("%s\t attrName \"%s\"", __FUNCTION__, attribute->attrName);
>> +    if ((attribute != NULL) && (attribute->attrValuesNumber != 0)) {
>> +            /* scAbsenceAllowed has value. Get the value */
>> +            value = attribute->attrValues[0];
>> +            *attr_val = *(static_cast<SaUint32T *>(value));
>> +            rc_attr_val = attr_val;
>> +    }
>> +
>> +done_fin_Om:
>> +    /* Free Om resources */
>> +    ais_rc = immutil_saImmOmFinalize(immOmHandle);
>> +    if (ais_rc != SA_AIS_OK) {
>> +            TRACE("%s\t saImmOmFinalize Fail '%s'",
>> +                    __FUNCTION__, saf_error(ais_rc));
>> +    }
>> +
>> +done:
>> +    /* Restore immutil settings */
>> +    immutilWrapperProfile.errorsAreFatal =
>> tmp_immutilWrapperProfile.errorsAreFatal;
>> +    immutilWrapperProfile.nTries = tmp_immutilWrapperProfile.nTries;
>> +    immutilWrapperProfile.retryInterval =
>> tmp_immutilWrapperProfile.retryInterval;
>> +
>> +    TRACE_LEAVE();
>> +    return rc_attr_val;
>> +}
>> diff --git a/osaf/services/saf/logsv/lgs/lgs_main.cc
>> b/osaf/services/saf/logsv/lgs/lgs_main.cc
>> --- a/osaf/services/saf/logsv/lgs/lgs_main.cc
>> +++ b/osaf/services/saf/logsv/lgs/lgs_main.cc
>> @@ -31,21 +31,26 @@
>>  #include <daemon.h>
>>  #include <nid_api.h>
>>  #include <ncs_main_papi.h>
>> +#include <osaf_time.h>
>>
>>  #include "lgs.h"
>>  #include "lgs_file.h"
>>  #include "osaf_utility.h"
>> +#include "lgs_recov.h"
>>
>>  /*
>>
>==================================================================
>======
>>   *   DEFINITIONS
>>   *
>>
>==================================================================
>======
>>   */
>> -
>> -#define FD_TERM 0
>> -#define FD_AMF 1
>> -#define FD_MBCSV 2
>> -#define FD_MBX 3
>> -#define FD_IMM 4            /* Must be the last in the fds array */
>> +enum {
>> +    FD_TERM = 0,
>> +    FD_AMF,
>> +    FD_MBCSV,
>> +    FD_MBX,
>> +    FD_CLTIMER,
>> +    FD_IMM,         /* Must be the last in the fds array */
>> +    FD_NUM
>> +};
>>
>>  #ifndef LOG_STREAM_LOW_LIMIT_PERCENT
>>  #define LOG_STREAM_LOW_LIMIT_PERCENT 0.6 // default value for low is
>> 60%
>> @@ -62,6 +67,7 @@
>>   */
>>
>>  static lgs_cb_t _lgs_cb;
>> +
>>  lgs_cb_t *lgs_cb = &_lgs_cb;
>>  SYSF_MBX lgs_mbx; /* LGS's mailbox */
>>
>> @@ -83,8 +89,8 @@ uint32_t mbox_low[NCS_IPC_PRIORITY_MAX];
>>   */
>>  pthread_mutex_t lgs_mbox_init_mutex = PTHREAD_MUTEX_INITIALIZER;
>>
>> -static struct pollfd fds[5];
>> -static nfds_t nfds = 5;
>> +static struct pollfd fds[FD_NUM];
>> +static nfds_t nfds = FD_NUM;
>>  static NCS_SEL_OBJ usr1_sel_obj;
>>
>>  /**
>> @@ -195,6 +201,69 @@ uint32_t lgs_configure_mailbox(void)
>>  }
>>
>>  /**
>> + * Get OpenSAF global scAbsenceAllowed configuration
>> + */
>> +static void init_scAbsenceAllowed()
>> +{
>> +    SaUint32T scAbsenceAllowed_val = 0;
>> +
>> +    TRACE_ENTER();
>> +
>> +    if (lgs_get_scAbsenceAllowed_attr(&scAbsenceAllowed_val) != NULL) {
>> +            TRACE("%s\t Got scAbsenceAllowed_val = %d", __FUNCTION__,
>> +                    scAbsenceAllowed_val);
>> +    }
>> +
>> +    lgs_cb->scAbsenceAllowed = scAbsenceAllowed_val;
>> +
>> +    TRACE_LEAVE();
>> +}
>> +
>> +/**
>> + * Initiate recovery handling.
>> + * Note1: This must be done during init before any streams are
>> created
>> + * Note2: Recovery state timer is started in the main() function
>> + *
>> + * If absence is allowed configuration is set:
>> + * - Create a list of recoverable streams
>> + * - If list is not empty set recovery state to LGS_RECOVERY
>> + */
>> +static void init_recovery()
>> +{
>> +    int list_num = 0;
>> +
>> +    TRACE_ENTER();
>> +
>> +    /* Set default state */
>> +    lgs_cb->lgs_recovery_state = LGS_NORMAL;
>> +
>> +    /* Get the value of the scAbsenceAllowed IMM attribute for
>> configuring
>> +     * SC node absence handling
>> +     */
>> +    init_scAbsenceAllowed();
>> +
>> +    if (lgs_cb->scAbsenceAllowed == 0) {
>> +            TRACE("%s Absence is not allowded", __FUNCTION__);
>> +            TRACE_LEAVE();
>> +            return;
>> +    }
>> +
>> +    /* Create a list of recoverable (IMM object exist) streams */
>> +    lgs_search_stream_objects();
>> +    list_num = log_rtobj_list_no();
>> +
>> +    TRACE("Number of runtime objects found = %d", list_num);
>> +
>> +    /* set recovery state if the list is not empty */
>> +    if (list_num != 0) {
>> +            /* There are objects in list */
>> +            lgs_cb->lgs_recovery_state = LGS_RECOVERY;
>> +    }
>> +
>> +    TRACE_LEAVE2();
>> +}
>> +
>> +/**
>>   * Initialize log
>>   *
>>   * @return uns32
>> @@ -254,6 +323,9 @@ static uint32_t log_initialize(void)
>>              goto done;
>>      }
>>
>> +    /* Initiate "headless" recovery handling */
>> +    init_recovery();
>> +
>>      /* Initialize configuration stream class
>>       * Configuration must have been initialized
>>       */
>> @@ -324,7 +396,11 @@ static uint32_t log_initialize(void)
>>              /* Create streams that has configuration objects and become
>>               * class implementer for the SaLogStreamConfig class
>>               */
>> -            if (lgs_imm_create_configStream(lgs_cb) != SA_AIS_OK) {
>> +
>> +            /* Note1: lgs_cb->immOiHandle is set in lgs_imm_init()
>> +             * Note2: lgs_cb->logsv_root_dir must be set
>> +             */
>> +            if (lgs_imm_init_configStreams(lgs_cb) != SA_AIS_OK) {
>>                      LOG_ER("lgs_imm_create_configStream FAILED");
>>                      rc = NCSCC_RC_FAILURE;
>>                      goto done;
>> @@ -362,6 +438,18 @@ int main(int argc, char *argv[])
>>      uint32_t rc;
>>      int term_fd;
>>
>> +    /* File descriptor for timeout to delete not used stream runtime
>> objects.
>> +     * May exist after 'headless' state.
>> +     */
>> +    int cltimer_fd = -1;
>> +
>> +    /* Timeout time in seconds before clean up of runtime objects that
>> may
>> +     * still exist after a "headless" situation. After timeout recovery
>> of
>> +     * "lost" streams is no longer possible.
>> +     */
>> +    const time_t CLEAN_TIMEOUT = 600; /* 10 min */
>> +    //const time_t CLEAN_TIMEOUT = 60; /* 1 min LLDTEST */
>> +
>>      daemonize(argc, argv);
>>
>>      if (log_initialize() != NCSCC_RC_SUCCESS) {
>> @@ -372,6 +460,13 @@ int main(int argc, char *argv[])
>>      mbx_fd = ncs_ipc_get_sel_obj(&lgs_mbx);
>>      daemon_sigterm_install(&term_fd);
>>
>> +    if (log_rtobj_list_no() != 0) {
>> +            /* Needed only if any "lost" objects are found
>> +             * See log_initialize */
>> +            cltimer_fd = lgs_init_timer(CLEAN_TIMEOUT);
>> +            TRACE("%s Recovery timeout started", __FUNCTION__);
>> +    }
>> +
>>      /* Set up all file descriptors to listen to */
>>      fds[FD_TERM].fd = term_fd;
>>      fds[FD_TERM].events = POLLIN;
>> @@ -382,6 +477,8 @@ int main(int argc, char *argv[])
>>      fds[FD_MBCSV].events = POLLIN;
>>      fds[FD_MBX].fd = mbx_fd.rmv_obj;
>>      fds[FD_MBX].events = POLLIN;
>> +    fds[FD_CLTIMER].fd = cltimer_fd;
>> +    fds[FD_CLTIMER].events = POLLIN;
>>      fds[FD_IMM].fd = lgs_cb->immSelectionObject;
>>      fds[FD_IMM].events = POLLIN;
>>
>> @@ -440,6 +537,25 @@ int main(int argc, char *argv[])
>>                      }
>>              }
>>
>> +            if (fds[FD_CLTIMER].revents & POLLIN) {
>> +                    /* To avoid 'stray objects', after a timeout all runtime
>> +                     * objects that has not been restored shall be deleted
>> +                     */
>> +                    TRACE("Recover state End. Clean objects");
>> +
>> +                    /* Close timer to free resources and stop timer poll */
>> +                    lgs_close_timer(cltimer_fd);
>> +                    fds[FD_CLTIMER].fd = -1;
>> +
>> +                    if (lgs_cb->ha_state == SA_AMF_HA_ACTIVE) {
>> +                            /* Delete objects left if active */
>> +                            lgs_clean_stream_objects();
>> +                    }
>> +
>> +                    /* Remove the found objects list */
>> +                    log_rtobj_list_free();
>> +            }
>> +
>>              if (fds[FD_MBX].revents & POLLIN)
>>                      lgs_process_mbx(&lgs_mbx);
>>
>> diff --git a/osaf/services/saf/logsv/lgs/lgs_mbcsv.cc
>> b/osaf/services/saf/logsv/lgs/lgs_mbcsv.cc
>> --- a/osaf/services/saf/logsv/lgs/lgs_mbcsv.cc
>> +++ b/osaf/services/saf/logsv/lgs/lgs_mbcsv.cc
>> @@ -24,6 +24,7 @@
>>  #include "lgs_mbcsv_v3.h"
>>  #include "lgs_mbcsv_v2.h"
>>  #include "lgs_mbcsv_v1.h"
>> +#include "lgs_recov.h"
>>
>>  /*
>>  LGS_CKPT_DATA_HEADER
>> @@ -1856,6 +1857,7 @@ uint32_t ckpt_proc_open_stream(lgs_cb_t
>>  {
>>      lgs_ckpt_stream_open_t *param;
>>      log_stream_t *stream;
>> +    int pos = 0;
>>
>>      TRACE_ENTER();
>>
>> @@ -1871,7 +1873,8 @@ uint32_t ckpt_proc_open_stream(lgs_cb_t
>>      /* Check that client still exist */
>>      if ((param->clientId != invalidClient) &&
>>              (lgs_client_get_by_id(param->clientId) == NULL)) {
>> -            LOG_WA("\tClient %u does not exist, failed to create stream
>'%s'",
>> param->clientId, param->logStreamName);
>> +            LOG_WA("\tClient %u does not exist, failed to create stream
>'%s'",
>> +                       param->clientId, param->logStreamName);
>>              goto done;
>>      }
>>
>> @@ -1890,7 +1893,7 @@ uint32_t ckpt_proc_open_stream(lgs_cb_t
>>              strcpy((char *)name.value, param->logStreamName);
>>              name.length = strlen(param->logStreamName);
>>
>> -            stream = log_stream_new(&name,
>> +            stream = log_stream_new_1(&name,
>>                              param->logFile,
>>                              param->logPath,
>>                              param->maxFileSize,
>> @@ -1901,11 +1904,12 @@ uint32_t ckpt_proc_open_stream(lgs_cb_t
>>                              param->streamType,
>>                              param->streamId,
>>                              SA_FALSE,       // FIX sync or calculate?
>> -                            param->logRecordId);
>> +                            param->logRecordId,
>> +                            0);
>>
>>              if (stream == NULL) {
>>                      /* Do not allow standby to get out of sync */
>> -                    LOG_ER("%s - Failed to create stream
>'%s'",__FUNCTION__,
>> +                    LOG_ER("%s - Failed to create stream '%s'",
>__FUNCTION__,
>>                                      param->logStreamName);
>>                      goto done;
>>              }
>> @@ -1923,6 +1927,9 @@ uint32_t ckpt_proc_open_stream(lgs_cb_t
>>       */
>>      if (lgs_is_split_file_system()) {
>>              if (stream->numOpeners <= 1) {
>> +                    TRACE("%s: log_initiate_stream_files(%s)",
>> +                              __FUNCTION__, stream->fileName.c_str());
>> +
>>                      log_initiate_stream_files(stream);
>>              }
>>      }
>> @@ -1935,11 +1942,16 @@ uint32_t ckpt_proc_open_stream(lgs_cb_t
>>      if ((param->clientId != invalidClient) &&
>>              lgs_client_stream_add(param->clientId, stream->streamId) !=
>0) {
>>              /* Do not allow standby to get out of sync */
>> -            LOG_ER("%s - Failed to add stream '%s' to client
>%u",__FUNCTION__,
>> +            LOG_ER("%s - Failed to add stream '%s' to client %u",
>> __FUNCTION__,
>>                              param->logStreamName, param->clientId);
>>              lgs_exit("Could not add stream to client",
>> SA_AMF_COMPONENT_RESTART);
>>      }
>>
>> +    /* Stream is opened  on standby. Remove from rtobj list if exist */
>> +    pos = log_rtobj_list_find(param->logStreamName);
>> +    if (pos != -1)
>> +            log_rtobj_list_erase_one_pos(pos);
>> +
>>   done:
>>      /* Free strings allocated by the EDU encoder */
>>      lgs_free_edu_mem(param->logFile);
>> diff --git a/osaf/services/saf/logsv/lgs/lgs_recov.cc
>> b/osaf/services/saf/logsv/lgs/lgs_recov.cc
>> new file mode 100644
>> --- /dev/null
>> +++ b/osaf/services/saf/logsv/lgs/lgs_recov.cc
>> @@ -0,0 +1,758 @@
>> +/*      -*- OpenSAF  -*-
>> + *
>> + * (C) Copyright 2016 The OpenSAF Foundation
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> but
>> + * WITHOUT ANY WARRANTY; without even the implied warranty of
>> MERCHANTABILITY
>> + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are
>> licensed
>> + * under the GNU Lesser General Public License Version 2.1, February
>> 1999.
>> + * The complete license can be accessed from the following location:
>> + * http://opensource.org/licenses/lgpl-license.php
>> + * See the Copying file included with the OpenSAF distribution for
>> full
>> + * licensing terms.
>> + *
>> + * Author(s): Ericsson AB
>> + *
>> + */
>> +
>> +#include "lgs_recov.h"
>> +#include "lgs_file.h"
>> +#include "lgs_filehdl.h"
>> +
>> +/***
>> + * The following functions are used to handle a list of runtime
>> stream objects
>> + * (application streams with runtime objects) that may be found
>> during start of
>> + * the log server.
>> + * The list consists of a vector of strings containing runtime stream
>> object
>> + * dn:s
>> + */
>> +
>> +static char **rtobj_list = NULL;
>> +static bool rtobj_list_init_f = false;
>> +static uint32_t rtobj_cnt = 0; /* Number of object names in list */
>> +static SaUint32T rtobj_list_len = 0; /* Also the length of the list
>> */
>> +
>> +/**
>> + * Initiate the list by allocating memory for a vector of pointers to
>> strings
>> + * (char *). The number of elements will be
>> "logMaxApplicationStreams", see log
>> + * configuration object.
>> + *
>> + * @return true if initiated (list exist)
>> + */
>> +static bool log_rtobj_list_init()
>> +{
>> +    TRACE_ENTER();
>> +
>> +    if (rtobj_list_init_f == true)
>> +            goto done; /* Already initiated */
>> +
>> +    rtobj_list_len = *static_cast<const SaUint32T *>(
>> +            lgs_cfg_get(LGS_IMM_LOG_MAX_APPLICATION_STREAMS));
>> +
>> +    rtobj_list = static_cast<char **>(calloc(rtobj_list_len, sizeof(char
>> *)));
>> +    if (rtobj_list != NULL) {
>> +            rtobj_list_init_f = true;
>> +    } else {
>> +            TRACE("%s\tFail to alloc memory for rtobj_list",
>__FUNCTION__);
>> +    }
>> +
>> +done:
>> +    TRACE_LEAVE2("rtobj_list_init_f = %d", rtobj_list_init_f);
>> +    return rtobj_list_init_f;
>> +}
>> +
>> +/**
>> + * Free an initialized rtobj list
>> + *
>> + */
>> +void log_rtobj_list_free()
>> +{
>> +    TRACE_ENTER();
>> +
>> +    if (rtobj_list == NULL)
>> +            return; /* No list to free */
>> +
>> +    /* Free positions in the list if needed */
>> +    uint32_t pos;
>> +    for (pos = 0; pos < rtobj_list_len; pos++) {
>> +            if (rtobj_list[pos] != NULL)
>> +                    free(rtobj_list[pos]);
>> +    }
>> +
>> +    free(rtobj_list);
>> +    rtobj_cnt = 0;
>> +    rtobj_list_len = 0;
>> +    rtobj_list = NULL;
>> +
>> +    TRACE_LEAVE();
>> +}
>> +
>> +/**
>> + * Add a dn name of an rt-object
>> + *
>> + * @param dn_str[in] '\0' terminated string containing a dn
>> + * @return -1 on error
>> + */
>> +int log_rtobj_list_add(char *dn_str)
>> +{
>> +    char *str_ptr = NULL;
>> +    size_t len = 0;
>> +    int rc = 0;
>> +
>> +    TRACE_ENTER();
>> +
>> +    if (log_rtobj_list_init() == false) {
>> +            TRACE("%s\trtobj_list not initiated!", __FUNCTION__);
>> +            rc = -1;
>> +            goto done;
>> +    }
>> +
>> +    if (rtobj_cnt >= rtobj_list_len) {
>> +            /* Should be impossible */
>> +            LOG_WA("%s\trtobj_cnt >= maxApplicationStreams!",
>> +                    __FUNCTION__);
>> +            rc = -1;
>> +            goto done;
>> +    }
>> +
>> +    /* Save dn string */
>> +    len = strlen(dn_str) + 1; /* Including '\0' */
>> +    if (len > SA_MAX_NAME_LENGTH) {
>> +            /* Should never happen */
>> +            LOG_WA("%s\tToo long dn string!",__FUNCTION__);
>> +            rc = -1;
>> +            goto done;
>> +    }
>> +
>> +    str_ptr = static_cast<char *>(calloc(1, len));
>> +    if (str_ptr == NULL) {
>> +            LOG_WA("%s\tcalloc Fail",__FUNCTION__);
>> +            rc = -1;
>> +            goto done;
>> +    }
>> +
>> +    strcpy(str_ptr, dn_str);
>> +
>> +    /* Add dn to list */
>> +    rtobj_list[rtobj_cnt] = str_ptr;
>> +    rtobj_cnt++;
>> +
>> +    done:
>> +    TRACE_LEAVE2("rc = %d", rc);
>> +    return rc;
>> +}
>> +
>> +/**
>> + * Return number of names in list
>> + *
>> + * @return Number of names
>> + */
>> +int log_rtobj_list_no()
>> +{
>> +    return rtobj_cnt;
>> +}
>> +
>> +/**
>> + * Find pos of the given given name in list
>> + *
>> + * @param dn_str[in] '\0' terminated string with dn to find
>> + * @return Position of found name or -1 if name not found
>> + */
>> +int log_rtobj_list_find(char *dn_str)
>> +{
>> +    uint32_t i = 0;
>> +    int pos = -1;
>> +
>> +    TRACE_ENTER2("dn_str \"%s\"", dn_str);
>> +
>> +    if (rtobj_list == NULL) {
>> +            TRACE("\t No rtobj_list exist");
>> +            goto done;
>> +    }
>> +
>> +    for (i = 0; i < rtobj_list_len; i++) {
>> +            if (rtobj_list[i] == NULL)
>> +                    continue;
>> +            if (strcmp(rtobj_list[i], dn_str) == 0) {
>> +                    /* Found! */
>> +                    pos = (int) i;
>> +                    break;
>> +            }
>> +    }
>> +
>> +done:
>> +    TRACE_LEAVE2("pos = %d", pos);
>> +    return pos;
>> +}
>> +
>> +/**
>> + * Get pos of first name found in list.
>> + *
>> + * @return Position of found name or -1 if no name found
>> + */
>> +int log_rtobj_list_getnamepos()
>> +{
>> +    uint32_t i = 0;
>> +    int pos = -1;
>> +
>> +    for (i = 0; i < rtobj_list_len; i++) {
>> +            if (rtobj_list[i] == NULL) {
>> +                    continue;
>> +            } else {
>> +                    pos = static_cast<int>(i);
>> +                    break;
>> +            }
>> +    }
>> +
>> +    return pos;
>> +}
>> +
>> +/**
>> + * Get name at given pos in list.
>> + *
>> + * @param pos[in] Position for name to get
>> + * @return A pointer to the string in given pos.
>> + *         If there is no string in pos or pos is outside the list
>> + *         NULL is returned.
>> + */
>> +char *log_rtobj_list_getname(int pos)
>> +{
>> +    if (pos >= static_cast<int>(rtobj_list_len))
>> +            return NULL;
>> +
>> +    return rtobj_list[pos];
>> +}
>> +
>> +/**
>> + * "Erase" dn name at pos in list
>> + *
>> + * @param pos[in] Position in list to erase
>> + */
>> +void log_rtobj_list_erase_one_pos(int pos)
>> +{
>> +    TRACE_ENTER2("pos = %d", pos);
>> +    if (pos > static_cast<int>(rtobj_list_len)) {
>> +            TRACE_LEAVE2("%s\tPosition %d outside list!", __FUNCTION__,
>pos);
>> +            return;
>> +    }
>> +
>> +    if (rtobj_list[pos] == NULL) {
>> +            TRACE_LEAVE2("%s\tNo string in pos %d", __FUNCTION__,
>pos);
>> +            return;
>> +    }
>> +
>> +    free(rtobj_list[pos]);
>> +    rtobj_list[pos] = NULL;
>> +
>> +    if (rtobj_cnt > 0)
>> +            rtobj_cnt--;
>> +
>> +    TRACE_LEAVE();
>> +}
>> +
>> +/***
>> + * Restore a lost runtime stream.
>> + * Get attributes from given runtime object (if exists).
>> + * Find the last open logfile. From the file get number of log
>> records written
>> + * and latest used log record id
>> + * If fail delete the stream IMM object (if exist)
>> + * Always delete the object name from the rtobj list
>> + */
>> +
>> +/**
>> + * Local help function
>> + * Find the file that was current log file before server down.
>> + * Get file size
>> + * Get last written record Id by reading the first characters of the
>> last
>> + * log record in the file
>> + *
>> + * NOTE:
>> + * All file handling must be done in the file thread
>> + * See lgs_get_file_params_hdl() in lgs_filehdl.c
>> + *
>> + * @param fileName[in]   The name in saLogStreamFileName e.g. "app1"
>> + * @param pathName[in]       Full path to the dir where the log file can
>> be found
>> + *                       root path + relative path
>> + * @param logFileCurrent[out]
>> + * @param curFileSize[out]
>> + * @param logRecordId[out]
>> + *
>> + * @return -1 on error
>> + */
>> +//static int lgs_get_file_params_h(gfp_in_t *par_in, gfp_out_t
>> *par_out)
>> +static int lgs_get_file_params_h(gfp_in_t *par_in, gfp_out_t
>> *par_out)
>> +{
>> +    lgsf_retcode_t api_rc;
>> +    lgsf_apipar_t apipar;
>> +    int rc = 0;
>> +
>> +    TRACE_ENTER();
>> +
>> +    /* Fill in API structure */
>> +    apipar.req_code_in = LGSF_GET_FILE_PAR;
>> +    apipar.data_in_size = sizeof(gfp_in_t);
>> +    apipar.data_in = par_in;
>> +    apipar.data_out_size = sizeof(gfp_out_t);
>> +    apipar.data_out = par_out;
>> +
>> +    api_rc = log_file_api(&apipar);
>> +    if (api_rc != LGSF_SUCESS) {
>> +            TRACE("%s - API error %s", __FUNCTION__,
>> +                  lgsf_retcode_str(api_rc));
>> +            rc = -1;
>> +    } else {
>> +            rc = apipar.hdl_ret_code_out;
>> +            TRACE("\t hdl_ret_code_out = %d", rc);
>> +    }
>> +
>> +    TRACE_LEAVE();
>> +    return rc;
>> +}
>> +
>> +static void lgs_remove_stream(uint32_t client_id, log_stream_t
>> *log_stream)
>> +{
>> +    TRACE_ENTER();
>> +
>> +    /* Remove the stream handle and
>> +     * remove the stream resources
>> +     */
>> +       if (lgs_client_stream_rmv(client_id, log_stream->streamId) <
>> 0) {
>> +           TRACE("%s lgs_client_stream_rmv Fail", __FUNCTION__);
>> +       }
>> +
>> +       log_free_stream_resources(log_stream);
>> +
>> +       log_stream = NULL;
>> +
>> +       TRACE_LEAVE();
>> +}
>> +
>> +/**
>> + * Restore parameters for a lost runtime (application) stream, create
>> the
>> + * stream in the local stream list and associate with a client.
>> + * Remove the stream object name from the found objects list.
>> + *
>> + * @param stream_name[in]  The name of the stream
>> + * @param client_id[in]    Client to recover stream for
>> + * @param o_stream[out]    The recovered stream
>> + *                         stream
>> + * @return -1 on error
>> + */
>> +int lgs_restore_one_app_stream(
>> +    char *stream_name, uint32_t client_id,
>> +    log_stream_t **o_stream)
>> +{
>> +    int int_rc = 0;
>> +    int rc_out = 0;
>> +    SaAisErrorT ais_rc = SA_AIS_OK;
>> +    SaImmHandleT immOmHandle;
>> +    SaImmAttrValuesT_2 *attribute;
>> +    SaImmAttrValuesT_2 **attributes;
>> +    gfp_in_t par_in;
>> +    gfp_out_t par_out;
>> +    int list_pos;
>> +    int n;
>> +    int i = 0;
>> +
>> +    lgsv_stream_open_req_t open_stream_param;
>> +    log_stream_t *log_stream = NULL;
>> +    SaTimeT restored_creationTimeStamp = 0;
>> +    SaUint32T restored_severityFilter = 0;
>> +
>> +    std::string fileName;
>> +    std::string pathName;
>> +
>> +    // Make it safe for free
>> +    par_out.curFileName = NULL;
>> +
>> +    TRACE_ENTER2("object_name \"%s\", client_id=%d", stream_name,
>> client_id);
>> +
>> +    memset(&open_stream_param, 0, sizeof(open_stream_param));
>> +
>> +    /* Check and save stream file name */
>> +    if (stream_name == NULL) {
>> +            TRACE("%s: No object name <NULL>", __FUNCTION__);
>> +            rc_out = -1;
>> +            goto done;
>> +    }
>> +    n = snprintf(reinterpret_cast<char
>> *>(open_stream_param.lstr_name.value),
>> +            SA_MAX_NAME_LENGTH, "%s", stream_name);
>> +
>> +    open_stream_param.lstr_name.length = strlen(stream_name) + 1;
>> +    if (n >= SA_MAX_NAME_LENGTH) {
>> +            TRACE("Log stream name \"%s\" is truncated",
>> +                    open_stream_param.lstr_name.value);
>> +            rc_out = -1;
>> +            goto done;
>> +    }
>> +
>> +    /* Check if in found objects list */
>> +    list_pos = log_rtobj_list_find(stream_name);
>> +    if (list_pos == -1) {
>> +            TRACE("%s: No stream \"%s\" found to restore",
>__FUNCTION__,
>> stream_name);
>> +            rc_out = -1;
>> +            goto done;
>> +    }
>> +
>> +    /* Remove from list */
>> +    log_rtobj_list_erase_one_pos(list_pos);
>> +
>> +    /* Get the cached attributes for the object
>> +     */
>> +    int_rc = lgs_get_streamobj_attr(&attributes, stream_name,
>> &immOmHandle);
>> +    if (int_rc == -1) {
>> +            TRACE("%s:\t lgs_get_streamobj_attr Fail", __FUNCTION__);
>> +            rc_out = -1;
>> +            goto done;
>> +    }
>> +
>> +    /* Fill in the "lgsv_stream_open_req_t open_stream_param" struct
>> with
>> +     * recovered parameters, re-create the stream and add it to the
>> client
>> +     * Note: Before restoring a stream the client to own the stream
>> must
>> +     *       exist.
>> +     */
>> +    i = 0;
>> +    while ((attribute = attributes[i++]) != NULL) {
>> +            void *value;
>> +            char *name;
>> +            char *str_val;
>> +
>> +            /* Fill in parameters read from the app stream object
>> +             */
>> +            name = attribute->attrName;
>> +            if (attribute->attrValuesNumber != 0)
>> +                    value = attribute->attrValues[0];
>> +            else {
>> +                    value = NULL;
>> +            }
>> +
>> +            TRACE("\t attribute name \"%s\"", name);
>> +            if (!strcmp(name, "saLogStreamFileName")) {
>> +                    if (value == NULL) {
>> +                            TRACE("%s: Fail, has empty value", name);
>> +                            rc_out = -1;
>> +                            goto done_free_attr;
>> +                    }
>> +
>> +                    fileName = *(static_cast<char **>(value));
>> +                    TRACE("\t saLogStreamFileName \"%s\"",
>fileName.c_str());
>> +            } else if (!strcmp(name, "saLogStreamPathName")) {
>> +                    if (value == NULL) {
>> +                            TRACE("%s: Fail, has empty value", name);
>> +                            rc_out = -1;
>> +                            goto done_free_attr;
>> +                    }
>> +
>> +                    pathName = *(static_cast<char **>(value));
>> +                    TRACE("\t saLogStreamPathName \"%s\"",
>pathName.c_str());
>> +            } else if (!strcmp(name, "saLogStreamMaxLogFileSize")) {
>> +                    if (value == NULL) {
>> +                            TRACE("%s: Fail, has empty value", name);
>> +                            rc_out = -1;
>> +                            goto done_free_attr;
>> +                    }
>> +
>> +                    open_stream_param.maxLogFileSize =
>*(static_cast<SaUint64T
>> *>(value));
>> +                    TRACE("\t saLogStreamMaxLogFileSize = %lld",
>> +                            open_stream_param.maxLogFileSize);
>> +
>> +            } else if (!strcmp(name, "saLogStreamFixedLogRecordSize")) {
>> +                    if (value == NULL) {
>> +                            TRACE("%s: Fail, has empty value", name);
>> +                            rc_out = -1;
>> +                            goto done_free_attr;
>> +                    }
>> +                    open_stream_param.maxLogRecordSize =
>*(static_cast<SaUint32T
>> *>(value));
>> +                    TRACE("\t saLogStreamFixedLogRecordSize = %d",
>> +                            open_stream_param.maxLogRecordSize);
>> +
>> +            } else if (!strcmp(name, "saLogStreamHaProperty")) {
>> +                    if (value == NULL) {
>> +                            TRACE("%s: Fail, has empty value", name);
>> +                            rc_out = -1;
>> +                            goto done_free_attr;
>> +                    }
>> +                    open_stream_param.haProperty =
>*(static_cast<SaBoolT *>(value));
>> +                    TRACE("\t saLogStreamHaProperty=%d",
>> +                            open_stream_param.haProperty);
>> +
>> +            } else if (!strcmp(name, "saLogStreamLogFullAction")) {
>> +                    if (value == NULL) {
>> +                            TRACE("%s: Fail, has empty value", name);
>> +                            rc_out = -1;
>> +                            goto done_free_attr;
>> +                    }
>> +                    open_stream_param.logFileFullAction =
>> *(static_cast<SaLogFileFullActionT *>(value));
>> +                    TRACE("\t saLogStreamLogFullAction=%d",
>> +                            open_stream_param.logFileFullAction);
>> +
>> +            } else if (!strcmp(name, "saLogStreamMaxFilesRotated")) {
>> +                    if (value == NULL) {
>> +                            TRACE("%s: Fail, has empty value", name);
>> +                            rc_out = -1;
>> +                            goto done_free_attr;
>> +                    }
>> +                    open_stream_param.maxFilesRotated =
>*(static_cast<SaUint16T
>> *>(value));
>> +                    TRACE("\t saLogStreamMaxFilesRotated=%d",
>> +                            open_stream_param.maxFilesRotated);
>> +
>> +            } else if (!strcmp(name, "saLogStreamLogFileFormat")) {
>> +                    /*TBD Is this correct way of handling format?
>> +                     * - Must be checked!
>> +                     * - Use better max length than PATH_MAX!
>> +                     */
>> +                    if (value == NULL) {
>> +                            TRACE("%s: Fail, has empty value", name);
>> +                            rc_out = -1;
>> +                            goto done_free_attr;
>> +                    }
>> +                    str_val = *(static_cast<char **>(value));
>> +                    open_stream_param.logFileFmt = NULL;
>> +                    open_stream_param.logFileFmt = static_cast<char *>(
>> +                            calloc(1, strlen(str_val) + 1));
>> +                    if (open_stream_param.logFileFmt == NULL) {
>> +                            TRACE("%s [%d] calloc Fail",
>> +                                    __FUNCTION__, __LINE__);
>> +                            rc_out = -1;
>> +                            goto done_free_attr;
>> +                    }
>> +                    n = snprintf(open_stream_param.logFileFmt,
>> +                            PATH_MAX, "%s", str_val);
>> +                    open_stream_param.logFileFmtLength =
>> +                            strlen(open_stream_param.logFileFmt);
>> +                    if (n >= PATH_MAX) {
>> +                            TRACE("Format string \"%s\" too long",
>> +                                    str_val);
>> +                            rc_out = -1;
>> +                            goto done_free_attr;
>> +                    }
>> +                    TRACE("\t saLogStreamLogFileFormat \"%s\"",
>> +                            open_stream_param.logFileFmt);
>> +
>> +            } else if (!strcmp(name, "saLogStreamCreationTimestamp")) {
>> +                    if (value == NULL) {
>> +                            TRACE("%s: Fail, has empty value", name);
>> +                            rc_out = -1;
>> +                            goto done_free_attr;
>> +                    }
>> +                    restored_creationTimeStamp = *(static_cast<SaTimeT
>*>(value));
>> +                    TRACE("\t saLogStreamCreationTimestamp=%lld",
>> +                            restored_creationTimeStamp);
>> +
>> +            } else if (!strcmp(name, "saLogStreamSeverityFilter")) {
>> +                    if (value == NULL) {
>> +                            TRACE("%s: Fail, has empty value", name);
>> +                            rc_out = -1;
>> +                            goto done_free_attr;
>> +                    }
>> +                    restored_severityFilter = *(static_cast<SaUint32T
>*>(value));
>> +                    TRACE("\t saLogStreamSeverityFilter=%d",
>> +                            restored_severityFilter);
>> +            }
>> +    }
>> +
>> +    /* Fill in the rest of the stream open parameters
>> +     * and create the stream. Do not create an IMM object
>> +     */
>> +    open_stream_param.client_id = client_id;
>> +    open_stream_param.lstr_open_flags = 0; /* Dummy not used here */
>> +
>> +    open_stream_param.logFileName = const_cast<char
>> *>(fileName.c_str());
>> +    open_stream_param.logFilePathName = const_cast<char
>> *>(pathName.c_str());
>> +
>> +    ais_rc = create_new_app_stream(&open_stream_param, &log_stream,
>0);
>> +    if ( ais_rc != SA_AIS_OK) {
>> +            TRACE("%s: create_new_app_stream Fail %s",
>> +                    __FUNCTION__, saf_error(ais_rc));
>> +            rc_out = -1;
>> +            goto done_free_attr;
>> +    }
>> +
>> +    /* Create an association between this client and the stream */
>> +    int_rc = lgs_client_stream_add(client_id, log_stream->streamId);
>> +    if (int_rc == -1) {
>> +            TRACE("%s: lgs_client_stream_add Fail", __FUNCTION__);
>> +            log_free_stream_resources(log_stream); /* Undo create new
>stream
>> */
>> +            rc_out = -1;
>> +            goto done_free_attr;
>> +    }
>> +
>> +    /* Set values for attributes not restored when creating a stream.
>> +     * The value must be set after the stream is created.
>> +     * Cached:
>> +     * - saLogStreamSeverityFilter (cached)
>> +     * - saLogStreamCreationTimestamp (cached)
>> +     *
>> +     * Pure runtime:
>> +     * - saLogStreamNumOpeners
>> +     *   Handled when streams are opened. No recovery needed
>> +     * - logStreamDiscardedCounter
>> +     *   Cannot be restored. Initialized with 0
>> +     */
>> +    log_stream->creationTimeStamp = restored_creationTimeStamp;
>> +    log_stream->severityFilter = restored_severityFilter;
>> +    log_stream->filtered = 0;
>> +
>> +    TRACE("\t Stream obj attributes handled and stream is created");
>> +
>> +    /* Get recovery data from the log file and update the stream
>> +     */
>> +    pathName = static_cast<const char *>(
>> +            lgs_cfg_get(LGS_IMM_LOG_ROOT_DIRECTORY));
>> +    pathName = pathName + "/" + open_stream_param.logFilePathName;
>> +
>> +    par_in.file_name = open_stream_param.logFileName;
>> +    par_in.file_path = const_cast<char *>(pathName.c_str());
>> +
>> +    int_rc = lgs_get_file_params_h(&par_in, &par_out);
>> +    if (int_rc == -1) {
>> +            TRACE("%s:\t lgs_get_file_params_h Fail", __FUNCTION__);
>> +             /* Remove the stream handle and
>> +              * remove the stream resources
>> +              */
>> +            lgs_remove_stream(client_id, log_stream);
>> +            rc_out = -1;
>> +            goto done_free_attr;
>> +    }
>> +
>> +    /* If no current log file create a file name
>> +     */
>> +    if (par_out.curFileName == NULL) {
>> +            /* There is no current log file. Create a file name */
>> +            log_stream->logFileCurrent = log_stream->fileName + "_" +
>> lgs_get_time(NULL);
>> +            TRACE("\t A new file name for current log file is created");
>> +    } else {
>> +            log_stream->logFileCurrent = par_out.curFileName;
>> +    }
>> +
>> +    TRACE("\t Current log file \"%s\"",
>> log_stream->logFileCurrent.c_str());
>> +
>> +    log_stream->curFileSize = par_out.curFileSize;
>> +    log_stream->logRecordId = par_out.logRecordId;
>> +
>> +    /* The stream is open again and opened for the first time so far */
>> +    log_stream->numOpeners = 1;
>> +
>> +    /* Set the stream file descriptor to -1. The file will then be
>> opened
>> +     * at next write.
>> +     */
>> +    *log_stream->p_fd = -1;
>> +
>> +done_free_attr:
>> +    /* Free resources used for finding attribute values */
>> +    int_rc = lgs_free_streamobj_attr(immOmHandle);
>> +    if (int_rc == -1) {
>> +            TRACE("%s:\t lgs_free_streamobj_attr Fail", __FUNCTION__);
>> +            rc_out = -1;
>> +    }
>> +
>> +done:
>> +    free(open_stream_param.logFileFmt);
>> +    if (par_out.curFileName != NULL) {
>> +            // This memory is allocated in lgs_get_file_params_hdl()
>> +            free(par_out.curFileName);
>> +    }
>> +
>> +    /* Return recovered stream. Will be NULL if not recovered (rc_out =
>> -1) */
>> +    *o_stream = log_stream;
>> +    TRACE_LEAVE2("rc_out = %d", rc_out);
>> +    return rc_out;
>> +}
>> +
>> +/**
>> + * Restore lost files for a configuration stream.
>> + * Update the stream with current log file and log record Id
>> + *
>> + *
>> + * @param log_stream[in/out]
>> + * Will/May modify the following stream parameters:
>> + *   logFileCurrent
>> + *   curFileSize
>> + *   logRecordId
>> + *   creationTimeStamp
>> + *   *p_fd
>> + *   numOpeners
>> + *
>> + * @return -1 on error
>> + */
>> +int log_stream_open_file_restore(log_stream_t *stream)
>> +{
>> +    int int_rc = 0;
>> +    int rc_out = 0;
>> +    gfp_in_t par_in;
>> +    gfp_out_t par_out;
>> +    std::string pathName, log_root_path;
>> +    size_t name_length = lgs_max_nlength();
>> +
>> +    TRACE_ENTER();
>> +
>> +    pathName = static_cast<const char
>> *>(lgs_cfg_get(LGS_IMM_LOG_ROOT_DIRECTORY));
>> +    pathName = pathName + "/" + stream->pathName;
>> +
>> +    par_in.file_name = const_cast<char *>(stream->fileName.c_str());
>> +    par_in.file_path = const_cast<char *>(pathName.c_str());
>> +
>> +    TRACE("pathName = %s, fileName = %s, name_length = %zu",
>> +          pathName.c_str(), stream->fileName.c_str(), name_length);
>> +
>> +    // Initialize the output
>> +    par_out.curFileSize = 0;
>> +    par_out.logRecordId = 0;
>> +    par_out.curFileName = NULL;
>> +
>> +    int_rc = lgs_get_file_params_h(&par_in, &par_out);
>> +
>> +    /****
>> +     * Rules for lgs_get_file_params_h():
>> +     * - If current log file not empty: Name = cur log file, Size = file
>> size,
>> +     *                                  Id = fr file, rc = OK
>> +     * - If current log file empty no rotated: Name = cur log file, Size
>> = 0,
>> +     *                                         Id = 1, rc = OK
>> +     * - If current log file empty is rotated: Name = cur log file, Size
>> = 0,
>> +     *                                         Id = fr last rotated, rc
>> = OK
>> +     * - If no log file at all:  Name = NULL, Size = 0, Id = 1, rc = OK
>> +     * - If only rotated log file: Name = NULL, Size = 0, Id = fr
>> rotated file,
>> +     *                             rc = OK
>> +     */
>> +
>> +    if (int_rc == -1) {
>> +            /* No relevant file info found. Recovery fail */
>> +            TRACE("%s: lgs_get_file_params_h Fail", __FUNCTION__);
>> +            rc_out = -1;
>> +            goto done;
>> +    }
>> +
>> +    stream->logFileCurrent = par_out.curFileName;
>> +    stream->curFileSize = par_out.curFileSize;
>> +    stream->logRecordId = par_out.logRecordId;
>> +
>> +    TRACE("Out: curFileSize = %u, logRecordId = %u, logFileCurrent =
>> %s",
>> +          stream->curFileSize, stream->logRecordId,
>> stream->logFileCurrent.c_str());
>> +
>> +    if (stream->numOpeners != 0) {
>> +            TRACE("%s: numOpeners = %u Fail", __FUNCTION__,
>> stream->numOpeners);
>> +            rc_out = -1;
>> +            goto done;
>> +    }
>> +
>> +    int errno_save;
>> +    log_root_path = static_cast<const char
>> *>(lgs_cfg_get(LGS_IMM_LOG_ROOT_DIRECTORY));
>> +    *stream->p_fd = -1;
>> +
>> +    if ((*stream->p_fd = log_file_open(log_root_path, stream,
>> +                                       stream->logFileCurrent,
>> +                                       &errno_save)) == -1) {
>> +            TRACE("%s - Could not open '%s' - %s", __FUNCTION__,
>> +                  stream->logFileCurrent.c_str(), strerror(errno_save));
>> +    }
>> +
>> +    stream->numOpeners++;
>> +
>> +done:
>> +    // This memory is allocated in lgs_get_file_params_hdl()
>> +    if (par_out.curFileName != NULL)
>> +            free(par_out.curFileName);
>> +
>> +    TRACE_LEAVE2("rc_out = %d", rc_out);
>> +    return rc_out;
>> +}
>> diff --git a/osaf/services/saf/logsv/lgs/lgs_recov.h
>> b/osaf/services/saf/logsv/lgs/lgs_recov.h
>> new file mode 100644
>> --- /dev/null
>> +++ b/osaf/services/saf/logsv/lgs/lgs_recov.h
>> @@ -0,0 +1,37 @@
>> +/*      -*- OpenSAF  -*-
>> + *
>> + * (C) Copyright 2016 The OpenSAF Foundation
>> + *
>> + * This program is distributed in the hope that it will be useful,
>> but
>> + * WITHOUT ANY WARRANTY; without even the implied warranty of
>> MERCHANTABILITY
>> + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are
>> licensed
>> + * under the GNU Lesser General Public License Version 2.1, February
>> 1999.
>> + * The complete license can be accessed from the following location:
>> + * http://opensource.org/licenses/lgpl-license.php
>> + * See the Copying file included with the OpenSAF distribution for
>> full
>> + * licensing terms.
>> + *
>> + * Author(s): Ericsson AB
>> + *
>> + */
>> +
>> +#ifndef LGS_STATE_H
>> +#define     LGS_STATE_H
>> +
>> +#include "lgs.h"
>> +
>> +int log_rtobj_list_add(char *dn_str);
>> +int log_rtobj_list_no();
>> +int log_rtobj_list_find(char *stream_name);
>> +int log_rtobj_list_getnamepos();
>> +char *log_rtobj_list_getname(int pos);
>> +void log_rtobj_list_erase_one_pos(int pos);
>> +void log_rtobj_list_free();
>> +int lgs_restore_one_app_stream(
>> +    char *stream_name,
>> +    uint32_t client_id,
>> +    log_stream_t **o_stream
>> +    );
>> +int log_stream_open_file_restore(log_stream_t *log_stream);
>> +
>> +#endif      /* LGS_STATE_H */
>> diff --git a/osaf/services/saf/logsv/lgs/lgs_stream.cc
>> b/osaf/services/saf/logsv/lgs/lgs_stream.cc
>> --- a/osaf/services/saf/logsv/lgs/lgs_stream.cc
>> +++ b/osaf/services/saf/logsv/lgs/lgs_stream.cc
>> @@ -409,6 +409,33 @@ void log_stream_print(log_stream_t *stre
>>      TRACE_2("  filtered:             %llu", stream->filtered);
>>  }
>>
>> +/**
>> + * Free stream resources
>> + *
>> + * @param stream[in]
>> + */
>> +void log_free_stream_resources(log_stream_t *stream)
>> +{
>> +    if (stream->streamId != 0)
>> +            lgs_stream_array_remove(stream->streamId);
>> +
>> +    if (stream->pat_node.key_info != NULL)
>> +            log_stream_remove(stream->name);
>> +
>> +    if (stream->logFileFormat != NULL)
>> +            free(stream->logFileFormat);
>> +
>> +    delete stream;
>> +    stream = NULL;
>> +}
>> +
>> +/**
>> + * Remove a log stream including:
>> + * - Runtime object if application stream and active
>> + * - Remove stream resources (allocated memory)
>> + *
>> + * @param s[in] Pointer to the array of streams
>> + */
>>  void log_stream_delete(log_stream_t **s)
>>  {
>>      log_stream_t *stream;
>> @@ -469,6 +496,12 @@ static void init_log_stream_fd(log_strea
>>   * Create a new stream object. If HA state active, create the
>>   * correspronding IMM runtime object.
>>   *
>> + * Note: log_stream_new() is replaced by this function.
>> + *       The new function is doing the same as the old but the
>> possibility
>> + *       to create a stream without creating a corresponding runtime
>> object
>> + *       is added. See creationFlag parameter
>> + *
>> + * Stream attributes[in]:
>>   * @param name
>>   * @param filename
>>   * @param pathname
>> @@ -484,17 +517,21 @@ static void init_log_stream_fd(log_strea
>>   *
>>   * @return log_stream_t*
>>   */
>> -log_stream_t *log_stream_new(SaNameT *dn,
>> -                             const std::string &filename,
>> -                             const std::string &pathname,
>> -                         SaUint64T maxLogFileSize,
>> -                         SaUint32T fixedLogRecordSize,
>> -                         SaLogFileFullActionT logFullAction,
>> -                         SaUint32T maxFilesRotated,
>> -                         const char *logFileFormat,
>> -                         logStreamTypeT streamType, int stream_id,
>> -                             SaBoolT twelveHourModeFlag,
>> -                             uint32_t logRecordId)
>> +log_stream_t *log_stream_new_1(
>> +    SaNameT *dn,
>> +    const std::string &filename,
>> +    const std::string &pathname,
>> +    SaUint64T maxLogFileSize,
>> +    SaUint32T fixedLogRecordSize,
>> +    SaLogFileFullActionT logFullAction,
>> +    SaUint32T maxFilesRotated,
>> +    const char *logFileFormat,
>> +    logStreamTypeT streamType,
>> +    int stream_id,
>> +    SaBoolT twelveHourModeFlag,
>> +    uint32_t logRecordId,
>> +    int creationFlag
>> +    )
>>  {
>>      int rc;
>>      log_stream_t *stream = NULL;
>> @@ -690,10 +727,10 @@ log_stream_t *log_stream_new(SaNameT *dn
>>  }
>>
>>  /**
>> - * Create a new stream object. Do not create an IMM runtime object.
>> + * Create a new default stream. Do not create an IMM runtime object.
>>   * @param name
>>   * @param stream_id
>> - *
>> + *
>>   * @return log_stream_t*
>>   */
>>  log_stream_t *log_stream_new_2(SaNameT *name, int stream_id)
>> @@ -704,7 +741,7 @@ log_stream_t *log_stream_new_2(SaNameT *
>>      osafassert(name != NULL);
>>      TRACE_ENTER2("%s, l: %u", name->value, (unsigned int)name->length);
>>
>> -    stream = new (std::nothrow) (log_stream_t)();
>> +    stream = new (std::nothrow) log_stream_t();
>>      if (stream == NULL) {
>>              LOG_WA("calloc FAILED");
>>              goto done;
>> diff --git a/osaf/services/saf/logsv/lgs/lgs_stream.h
>> b/osaf/services/saf/logsv/lgs/lgs_stream.h
>> --- a/osaf/services/saf/logsv/lgs/lgs_stream.h
>> +++ b/osaf/services/saf/logsv/lgs/lgs_stream.h
>> @@ -79,18 +79,21 @@ extern uint32_t log_stream_init();
>>  extern void log_stream_delete(log_stream_t **s);
>>
>>  #define STREAM_NEW -1
>> -extern log_stream_t *log_stream_new(SaNameT *name,
>> -                                const std::string &filename,
>> -                                const std::string &pathname,
>> -                                SaUint64T maxLogFileSize,
>> -                                SaUint32T fixedLogRecordSize,
>> -                                SaLogFileFullActionT logFullAction,
>> -                                SaUint32T maxFilesRotated,
>> -                                const char *logFileFormat,
>> -                                logStreamTypeT streamType,
>> -                                int stream_id,
>> -                                SaBoolT twelveHourModeFlag,
>> -                                uint32_t logRecordId);
>> +extern log_stream_t *log_stream_new_1(
>> +    SaNameT *name,
>> +    const std::string &filename,
>> +    const std::string &pathname,
>> +    SaUint64T maxLogFileSize,
>> +    SaUint32T fixedLogRecordSize,
>> +    SaLogFileFullActionT logFullAction,
>> +    SaUint32T maxFilesRotated,
>> +    const char *logFileFormat,
>> +    logStreamTypeT streamType,
>> +    int stream_id,
>> +    SaBoolT twelveHourModeFlag,
>> +    uint32_t logRecordId,
>> +    int creationFlag
>> +    );
>>
>>  extern log_stream_t *log_stream_new_2(SaNameT *name, int stream_id);
>>
>> @@ -118,5 +121,6 @@ extern log_stream_t *log_stream_get_by_n
>>  extern log_stream_t *log_stream_getnext_by_name(const char *name);
>>  extern void log_stream_print(log_stream_t *stream);
>>  extern log_stream_t *log_stream_get_by_id(uint32_t id);
>> +void log_free_stream_resources(log_stream_t *stream);
>>
>>  #endif
>> diff --git a/osaf/services/saf/logsv/lgs/lgs_util.cc
>> b/osaf/services/saf/logsv/lgs/lgs_util.cc
>> --- a/osaf/services/saf/logsv/lgs/lgs_util.cc
>> +++ b/osaf/services/saf/logsv/lgs/lgs_util.cc
>> @@ -30,12 +30,13 @@
>>
>>  #include <stdlib.h>
>>  #include <grp.h>
>> +#include <osaf_time.h>
>>
>>  #include "immutil.h"
>>  #include "lgs.h"
>>  #include "lgs_file.h"
>>  #include "lgs_filehdl.h"
>> -#include "osaf_time.h"
>> +#include "osaf_timerfd.h"
>>
>>  #define ALARM_STREAM_ENV_PREFIX "ALARM"
>>  #define NOTIFICATION_STREAM_ENV_PREFIX "NOTIFICATION"
>> @@ -239,14 +240,14 @@ SaTimeT lgs_get_SaTime()
>>   * @param root_path[in]
>>   * @param rel_path[in]
>>   * @param old_name[in]
>> - * @param time_stamp[in]
>> + * @param time_stamp[in]
>>   *        Can be set to NULL but then new_name must be the complete
>> new name
>>   *        including time stamps but without suffix
>>   * @param suffix[in]
>> - * @param new_name[in/out]
>> - *        Pointer to char string of NAME_MAX size
>> + * @param new_name[in/out]
>> + *        Pointer to char string
>>   *        Filename of renamed file. Can be set to NULL
>> - *
>> + *
>>   * @return -1 if error
>>   */
>>  int lgs_file_rename_h(
>> @@ -638,6 +639,45 @@ done:
>>  }
>>
>>  /**
>> + * Initiate a timer:
>> + * Creates a timeout timer, set timeout time and starts the timer
>> + * returns a file descriptor to the timer that can be used with
>> poll()
>> + * See also osaf_timerfd.h
>> + *
>> + * @param timeout_s[in] Timeout time in seconds
>> + * @return fd  File descriptor referring to the created timer
>> + */
>> +int lgs_init_timer(time_t timeout_s)
>> +{
>> +    int fd;
>> +    struct itimerspec lgs_cltimer;
>> +
>> +    fd = osaf_timerfd_create(CLOCK_MONOTONIC, 0);
>> +
>> +    /* Set timeout time. Do not use as interval timer */
>> +    lgs_cltimer.it_interval.tv_sec = 0;
>> +    lgs_cltimer.it_interval.tv_nsec = 0;
>> +    /* Set timeout in seconds */
>> +    lgs_cltimer.it_value.tv_sec = timeout_s;
>> +    lgs_cltimer.it_value.tv_nsec = 0;
>> +
>> +    osaf_timerfd_settime(fd, 0, &lgs_cltimer, NULL);
>> +
>> +    return fd;
>> +}
>> +
>> +/**
>> + * Close a timer created with lgs_init_timer()
>> + * See also osaf_timerfd.h
>> + *
>> + * @param ufd[in]
>> + */
>> +void lgs_close_timer(int ufd)
>> +{
>> +    osaf_timerfd_close(ufd);
>> +}
>> +
>> +/**
>>   * Validate if string contains special characters or not
>>   *
>>   * @param: str [in] input string for checking
>> diff --git a/osaf/services/saf/logsv/lgs/lgs_util.h
>> b/osaf/services/saf/logsv/lgs/lgs_util.h
>> --- a/osaf/services/saf/logsv/lgs/lgs_util.h
>> +++ b/osaf/services/saf/logsv/lgs/lgs_util.h
>> @@ -77,4 +77,8 @@ bool lgs_is_valid_pathlength(const std::
>>                               const std::string &fileName,
>>                           const std::string &rootPath = "");
>>
>> +/* Timer functions */
>> +int lgs_init_timer(time_t timeout_s);
>> +void lgs_close_timer(int ufd);
>> +
>>  #endif   /* ifndef __LGS_UTIL_H */

Attachment: lgsv_cloud_fix_rvcomment_p2.patch
Description: Binary data

------------------------------------------------------------------------------
Site24x7 APM Insight: Get Deep Visibility into Application Performance
APM + Mobile APM + RUM: Monitor 3 App instances at just $35/Month
Monitor end-to-end web transactions and take corrective actions now
Troubleshoot faster and improve end-user experience. Signup Now!
http://pubads.g.doubleclick.net/gampad/clk?id=272487151&iu=/4140
_______________________________________________
Opensaf-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to