Hi Vu

Ack with comments:

I have not done a complete deep review of all the resilience code I have mostly 
looked at stream close during headless which is an addition to the original 
resilience patch. Also I have only been able to test the "legacy" functionality 
of the log service so eventual problem when running in resilience mode have to 
show up in tests after the patch is pushed.

Comments:
1.
Have not tested any of the resilience code but I have listed the resilience 
test cases.
I cannot find any test case that test that it is possible to close a stream 
when headless. Such a test case should fail if fix making it possible to close 
streams is not included. With fix a close request shall return OK. Without fix 
a close request shall return TRY AGAIN. A message asking the tester to check 
that there is no log file without an end timestamp should be written when 
testing in "manual" mode.
2.
README-HEADLESS is not updated/incorrect regarding the possibility to close 
streams when headless
Example of incorrect text:
" No server state:
* Return TRY AGAIN for all APIs except Finalize and Write"
3.
Remove LLDTEST tagged out commented code on line 451 in lgs_main.cc
4.
The lgs_clean_stream_objects() function in lgs_imm.cc is "secretly" doing 
"Append the close time to log file and configuration file"
It should be clear to a reader of the code that this function both deletes the 
stream objects in the  list and renames log files that may have been open when 
the stream was "abandoned".
You should at least write this information in the function header and it would 
also be good to give the function a new name that gives better information 
about what it is actually doing e.g. lgs_cleanup_abandoned_streams(). Maybe you 
can come up with a better name...
5.
The log_close_rtstream_files() (lgs_recov.cc) function has a return value. If 
not used the function should be casted to (void) log_close_rtstream_files().
6.
Remove outcommented line 282 in lgs_imm.c

Thanks
Lennart

> -----Original Message-----
> From: Vu Minh Nguyen [mailto:[email protected]]
> Sent: den 25 februari 2016 03:28
> To: 'Mathivanan Naickan Palanivelu'; Lennart Lund
> Cc: [email protected]
> Subject: RE: [devel] [PATCH 1 of 4] log: add support for cloud resilience
> feature (service part) [#1179]
> 
> Sorry. Please take this attach.
> 
> Regards, Vu.
> 
> 
> >-----Original Message-----
> >From: Vu Minh Nguyen [mailto:[email protected]]
> >Sent: Thursday, February 25, 2016 9:23 AM
> >To: 'Mathivanan Naickan Palanivelu'; [email protected]
> >Cc: [email protected]
> >Subject: Re: [devel] [PATCH 1 of 4] log: add support for cloud resilience
> feature
> >(service part) [#1179]
> >
> >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>("saLogStreamCreationTimesta
> mp"),
> >>> +                 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 */
------------------------------------------------------------------------------
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