Hi Vu

Mathi has a point here. It is actually possible to serve stream close also when 
headless.
If in state LGA_NO_SERVER the stream can be removed from the agent client 
database without sending a message to the (not existing) server.
In IMM there will exist a stream object and if this was the only client the 
stream object should have been removed by the server. This means that we now 
have a "dead" stream object. However there is a mechanism in the server that 
will clean up such objects after a timeout.

Regards
Lennart

> -----Original Message-----
> From: Mathivanan Naickan Palanivelu [mailto:[email protected]]
> Sent: den 23 februari 2016 13:44
> To: Vu Minh Nguyen
> Cc: Lennart Lund; [email protected]; Anders Widell
> Subject: Re: [PATCH 2 of 4] log: add support for cloud resilience feature
> (agent part) [#1179]
> 
> Hi Vu,
> 
> Ack for patch 2.
> 
> B.T.w, What is the idea behind returning try_again for streamclose(), i.e. as
> below?
> 
> +       if (lga_state == LGA_NO_SERVER) {
> +               /* We have no server and cannot write. The client may try 
> again
> +                */
> +               TRACE("%s No server", __FUNCTION__);
> +               ais_rc = SA_AIS_ERR_TRY_AGAIN;
> +               goto done_give_hdl_stream;
> +       }
> +
> 
> 
> 
> Mathi.
> 
> ----- [email protected] wrote:
> 
> > osaf/libs/agents/saf/lga/Makefile.am |    6 +-
> >  osaf/libs/agents/saf/lga/lga.h       |   53 +-
> >  osaf/libs/agents/saf/lga/lga_api.c   |  858
> > ++++++++++++++++++++++++----------
> >  osaf/libs/agents/saf/lga/lga_mds.c   |   46 +-
> >  osaf/libs/agents/saf/lga/lga_state.c |  670
> > +++++++++++++++++++++++++++
> >  osaf/libs/agents/saf/lga/lga_state.h |   41 +
> >  osaf/libs/agents/saf/lga/lga_util.c  |   94 +++-
> >  7 files changed, 1479 insertions(+), 289 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/libs/agents/saf/lga/Makefile.am
> > b/osaf/libs/agents/saf/lga/Makefile.am
> > --- a/osaf/libs/agents/saf/lga/Makefile.am
> > +++ b/osaf/libs/agents/saf/lga/Makefile.am
> > @@ -20,7 +20,8 @@ include $(top_srcdir)/Makefile.common
> >  MAINTAINERCLEANFILES = Makefile.in
> >
> >  noinst_HEADERS = \
> > -   lga.h
> > +   lga.h \
> > +   lga_state.h
> >
> >  noinst_LTLIBRARIES = liblga.la
> >
> > @@ -31,6 +32,7 @@ liblga_la_CPPFLAGS = \
> >  liblga_la_SOURCES = \
> >     lga_api.c \
> >     lga_util.c \
> > -   lga_mds.c
> > +   lga_mds.c \
> > +   lga_state.c
> >
> >  liblga_la_LDFLAGS = -static
> > diff --git a/osaf/libs/agents/saf/lga/lga.h
> > b/osaf/libs/agents/saf/lga/lga.h
> > --- a/osaf/libs/agents/saf/lga/lga.h
> > +++ b/osaf/libs/agents/saf/lga/lga.h
> > @@ -29,6 +29,7 @@
> >  #include <ncsencdec_pub.h>
> >  #include <ncs_util.h>
> >  #include <logtrace.h>
> > +#include <osaf_time.h>
> >
> >  #include "lgsv_msg.h"
> >  #include "lgsv_defs.h"
> > @@ -49,6 +50,11 @@ typedef struct lga_log_stream_hdl_rec {
> >     unsigned int lgs_log_stream_id; /* server reference
> for this log
> > stream */
> >     struct lga_log_stream_hdl_rec *next;    /* next pointer for
> the list in
> > lga_client_hdl_rec_t */
> >     struct lga_client_hdl_rec *parent_hdl;  /* Back Pointer to
> the client
> > instantiation */
> > +   /* This flag is used with recovery handling. It is valid only
> > +    * after server down has happened (will be initiated when
> server
> > down
> > +    * event occurs). It's not valid in LGA_NORMAL state.
> > +    */
> > +   bool recovered_flag;
> >  } lga_log_stream_hdl_rec_t;
> >
> >  /* LGA client record */
> > @@ -59,8 +65,46 @@ typedef struct lga_client_hdl_rec {
> >     lga_log_stream_hdl_rec_t *stream_list;  /* List of open
> streams per
> > client */
> >     SYSF_MBX mbx;           /* priority q mbx
> b/w MDS & Library */
> >     struct lga_client_hdl_rec *next;        /* next pointer for
> the list in
> > lga_cb_t */
> > +   /* These flags are used with recovery handling. They are valid
> only
> > +    * after server down has happened (will be initiated when
> server
> > down
> > +    * event occurs). They are not valid in LGA_NORMAL state
> > +    */
> > +   bool initialized_flag;      /* Used with "headless" recovery
> > handling
> > +                                * Set when client
> is initialized. Streams
> > +                                * may not have
> been recovered
> > +                                */
> > +   bool recovered_flag;        /* Used with "headless" recovery
> > handling
> > +                                * Set when client
> is initialized an all
> > +                                * streams are
> recovered
> > +                                */
> >  } lga_client_hdl_rec_t;
> >
> > +/* States of the server */
> > +typedef enum {
> > +   LGS_START,      /* The state before agent is started
> > +                    */
> > +   LGS_DOWN,       /* Server is down (headless)
> > +                    */
> > +   LGS_NO_ACTIVE,  /* No active server (switch/fail - over)
> > +                    */
> > +   LGS_UP          /* Server is up
> > +                    */
> > +} lgs_state_t;
> > +
> > +/* Agent internal states */
> > +typedef enum {
> > +   LGA_NORMAL,     /* Server is up and no recovery is ongoing
> > +                    */
> > +   LGA_NO_SERVER,  /* No Server (Server down) state
> > +                    */
> > +   LGA_RECOVERY1,  /* Server is up. Recover clients and streams
> when
> > +                    * request from client.
> > +                    * Recovery1 timer is running
> > +                    */
> > +   LGA_RECOVERY2   /* Auto recover remaining clients and
> streams
> > +                    * After recovery1 timeout
> > +                    */
> > +} lga_state_t;
> >  /*
> >   * The LGA control block is the master anchor structure for all LGA
> >   * instantiations within a process.
> > @@ -70,8 +114,8 @@ typedef struct {
> >     lga_client_hdl_rec_t *client_list;      /* LGA client
> handle database */
> >     MDS_HDL mds_hdl;        /* MDS handle */
> >     MDS_DEST lgs_mds_dest;  /* LGS absolute/virtual address */
> > -   int lgs_up;             /* Indicate that MDS subscription
> > -                            * is complete */
> > +   lgs_state_t lgs_state;  /* Indicate current server MDS
> state */
> > +   lga_state_t lga_state;  /* Indicate current state of the agent */
> >     /* LGS LGA sync params */
> >     int lgs_sync_awaited;
> >     NCS_SEL_OBJ lgs_sync_sel;
> > @@ -88,8 +132,9 @@ extern uint32_t lga_mds_msg_async_send(l
> >  extern void lgsv_lga_evt_free(struct lgsv_msg *);
> >
> >  /* lga_init.c */
> > -extern unsigned int lga_startup(void);
> > -extern unsigned int lga_shutdown(void);
> > +unsigned int lga_startup(lga_cb_t *cb);
> > +extern unsigned int lga_shutdown_after_last_client(void);
> > +extern unsigned int lga_force_shutdown(void);
> >
> >  /* lga_hdl.c */
> >  extern SaAisErrorT lga_hdl_cbk_dispatch(lga_cb_t *,
> > lga_client_hdl_rec_t *, SaDispatchFlagsT);
> > diff --git a/osaf/libs/agents/saf/lga/lga_api.c
> > b/osaf/libs/agents/saf/lga/lga_api.c
> > --- a/osaf/libs/agents/saf/lga/lga_api.c
> > +++ b/osaf/libs/agents/saf/lga/lga_api.c
> > @@ -16,8 +16,11 @@
> >   */
> >
> >  #include <string.h>
> > +#include <saf_error.h>
> >  #include "lga.h"
> >
> > +#include "lga_state.h"
> > +
> >  #define NCS_SAF_MIN_ACCEPT_TIME 10
> >
> >  /* Macro to validate the dispatch flags */
> > @@ -38,6 +41,8 @@
> >  /* The main controle block */
> >  lga_cb_t lga_cb = {
> >     .cb_lock = PTHREAD_MUTEX_INITIALIZER,
> > +   .lga_state = LGA_NORMAL,
> > +   .lgs_state = LGS_START
> >  };
> >
> >  static void populate_open_params(lgsv_stream_open_req_t
> *open_param,
> > @@ -116,20 +121,16 @@ SaAisErrorT saLogInitialize(SaLogHandleT
> >  {
> >     lga_client_hdl_rec_t *lga_hdl_rec;
> >     lgsv_msg_t i_msg, *o_msg;
> > -   SaAisErrorT rc;
> > -   uint32_t client_id;
> > +   SaAisErrorT ais_rc = SA_AIS_OK;
> > +   int rc;
> > +   uint32_t client_id = 0;
> >
> >     TRACE_ENTER();
> >
> > +   /* Verify parameters (log handle and that version is given) */
> >     if ((logHandle == NULL) || (version == NULL)) {
> >             TRACE("version or handle FAILED");
> > -           rc = SA_AIS_ERR_INVALID_PARAM;
> > -           goto done;
> > -   }
> > -
> > -   if ((rc = lga_startup()) != NCSCC_RC_SUCCESS) {
> > -           TRACE("lga_startup FAILED: %u", rc);
> > -           rc = SA_AIS_ERR_LIBRARY;
> > +           ais_rc = SA_AIS_ERR_INVALID_PARAM;
> >             goto done;
> >     }
> >
> > @@ -144,15 +145,59 @@ SaAisErrorT saLogInitialize(SaLogHandleT
> >             version->releaseCode = LOG_RELEASE_CODE;
> >             version->majorVersion =
> LOG_MAJOR_VERSION;
> >             version->minorVersion =
> LOG_MINOR_VERSION;
> > -           lga_shutdown();
> > -           rc = SA_AIS_ERR_VERSION;
> > +           lga_shutdown_after_last_client();
> > +           ais_rc = SA_AIS_ERR_VERSION;
> >             goto done;
> >     }
> >
> > -   if (!lga_cb.lgs_up) {
> > -           lga_shutdown();
> > -           TRACE("LGS server is down");
> > -           rc = SA_AIS_ERR_TRY_AGAIN;
> > +   /***
> > +    * Handle states
> > +    * Synchronize with mds and recovery thread (mutex)
> > +    * NOTE: Nothing to handle if recovery state 1
> > +    */
> > +   pthread_mutex_lock(&lga_cb.cb_lock);
> > +   lgs_state_t lgs_state = lga_cb.lgs_state;
> > +   lga_state_t lga_state = lga_cb.lga_state;
> > +   pthread_mutex_unlock(&lga_cb.cb_lock);
> > +
> > +   if (lgs_state == LGS_NO_ACTIVE) {
> > +           /* We have a server but it is temporary
> unavailable. Client may
> > +            * try again
> > +            */
> > +           TRACE("%s LGS no active", __FUNCTION__);
> > +           ais_rc = SA_AIS_ERR_TRY_AGAIN;
> > +           goto done;
> > +   }
> > +
> > +   if (lga_state == LGA_NO_SERVER) {
> > +           /* We have no server and cannot initialize.
> > +            * The client may try again
> > +            */
> > +           TRACE("%s No server", __FUNCTION__);
> > +           ais_rc = SA_AIS_ERR_TRY_AGAIN;
> > +           goto done;
> > +   }
> > +
> > +   if (lga_state == LGA_RECOVERY2) {
> > +           /* Auto recovery is ongoing. We have to wait for
> it to finish.
> > +            * The client may try again
> > +            */
> > +           TRACE("%s LGA auto recovery ongoing (2)",
> __FUNCTION__);
> > +           ais_rc = SA_AIS_ERR_TRY_AGAIN;
> > +           goto done;
> > +   }
> > +
> > +   /***
> > +    * Do Initiate. It's ok to initiate in recovery state 1 since we
> > have a
> > +    * server and is not conflicting with auto recovery
> > +    */
> > +
> > +   /* Initiate the client in the agent and if first client also start
> > MDS
> > +    * etc.
> > +    */
> > +   if ((rc = lga_startup(&lga_cb)) != NCSCC_RC_SUCCESS) {
> > +           TRACE("lga_startup FAILED: %u", rc);
> > +           ais_rc = SA_AIS_ERR_LIBRARY;
> >             goto done;
> >     }
> >
> > @@ -165,18 +210,18 @@ SaAisErrorT saLogInitialize(SaLogHandleT
> >     /* Send a message to LGS to obtain a client_id/server ref id
> which
> > is cluster
> >      * wide unique.
> >      */
> > -   rc = lga_mds_msg_sync_send(&lga_cb, &i_msg, &o_msg,
> > LGS_WAIT_TIME,MDS_SEND_PRIORITY_HIGH);
> > +   rc = lga_mds_msg_sync_send(&lga_cb, &i_msg, &o_msg,
> LGS_WAIT_TIME,
> > MDS_SEND_PRIORITY_HIGH);
> >     if (rc != NCSCC_RC_SUCCESS) {
> > -           lga_shutdown();
> > -           rc = SA_AIS_ERR_TRY_AGAIN;
> > +           lga_shutdown_after_last_client();
> > +           ais_rc = SA_AIS_ERR_TRY_AGAIN;
> >             goto done;
> >     }
> >
> >      /** Make sure the LGS return status was SA_AIS_OK
> >       **/
> > -   if (SA_AIS_OK != o_msg->info.api_resp_info.rc) {
> > -           rc = o_msg->info.api_resp_info.rc;
> > -           TRACE("LGS return FAILED");
> > +   ais_rc = o_msg->info.api_resp_info.rc;
> > +   if (SA_AIS_OK != ais_rc) {
> > +           TRACE("%s LGS error response %s",
> __FUNCTION__,
> > saf_error(ais_rc));
> >             goto err;
> >     }
> >
> > @@ -189,27 +234,26 @@ SaAisErrorT saLogInitialize(SaLogHandleT
> >     /* create the hdl record & store the callbacks */
> >     lga_hdl_rec = lga_hdl_rec_add(&lga_cb, callbacks, client_id);
> >     if (lga_hdl_rec == NULL) {
> > -           rc = SA_AIS_ERR_NO_MEMORY;
> > +           ais_rc = SA_AIS_ERR_NO_MEMORY;
> >             goto err;
> >     }
> >
> >     /* pass the handle value to the appl */
> > -   if (SA_AIS_OK == rc)
> > -           *logHandle = lga_hdl_rec->local_hdl;
> > +   *logHandle = lga_hdl_rec->local_hdl;
> >
> >   err:
> >     /* free up the response message */
> >     if (o_msg)
> >             lga_msg_destroy(o_msg);
> >
> > -   if (rc != SA_AIS_OK) {
> > -           TRACE_2("LGA INIT FAILED\n");
> > -           lga_shutdown();
> > +   if (ais_rc != SA_AIS_OK) {
> > +           TRACE_2("%s LGA INIT FAILED\n",
> __FUNCTION__);
> > +           lga_shutdown_after_last_client();
> >     }
> >
> >   done:
> > -   TRACE_LEAVE();
> > -   return rc;
> > +   TRACE_LEAVE2("client_id = %d", client_id);
> > +   return ais_rc;
> >  }
> >
> >
> >
> /**********************************************************
> *****************
> > @@ -325,6 +369,61 @@ SaAisErrorT saLogDispatch(SaLogHandleT l
> >     return rc;
> >  }
> >
> >
> +/*********************************************************
> *********************
> > + * Finalize
> > + * API function and help functions
> > +
> >
> **********************************************************
> ********************/
> > +
> > +/**
> > + * Create and send a Finalize message to the server
> > + *
> > + * @param hdl_rec
> > + * @return AIS return code
> > + */
> > +static SaAisErrorT send_Finalize_msg(lga_client_hdl_rec_t *hdl_rec)
> > +{
> > +   uint32_t mds_rc;
> > +   lgsv_msg_t msg, *o_msg = NULL;
> > +   SaAisErrorT ais_rc = SA_AIS_OK;
> > +
> > +   TRACE_ENTER();
> > +
> > +   memset(&msg, 0, sizeof(lgsv_msg_t));
> > +   msg.type = LGSV_LGA_API_MSG;
> > +   msg.info.api_info.type = LGSV_FINALIZE_REQ;
> > +   msg.info.api_info.param.finalize.client_id =
> > hdl_rec->lgs_client_id;
> > +
> > +   mds_rc = lga_mds_msg_sync_send(
> > +           &lga_cb, &msg,
> > +           &o_msg,
> > +           LGS_WAIT_TIME,
> > +           MDS_SEND_PRIORITY_MEDIUM
> > +           );
> > +   switch (mds_rc) {
> > +   case NCSCC_RC_SUCCESS:
> > +           break;
> > +   case NCSCC_RC_REQ_TIMOUT:
> > +           ais_rc = SA_AIS_ERR_TIMEOUT;
> > +           TRACE("lga_mds_msg_sync_send FAILED: %s",
> saf_error(ais_rc));
> > +           goto done;
> > +   default:
> > +           TRACE("lga_mds_msg_sync_send FAILED: %s",
> saf_error(ais_rc));
> > +           ais_rc = SA_AIS_ERR_NO_RESOURCES;
> > +           goto done;
> > +   }
> > +
> > +   if (o_msg != NULL) {
> > +           ais_rc = o_msg->info.api_resp_info.rc;
> > +           lga_msg_destroy(o_msg);
> > +   } else
> > +           ais_rc = SA_AIS_ERR_NO_RESOURCES;
> > +
> > +   done:
> > +
> > +   TRACE_LEAVE();
> > +   return ais_rc;
> > +}
> > +
> >
> >
> /**********************************************************
> *****************
> >   * 8.4.4
> >   *
> > @@ -350,84 +449,119 @@ SaAisErrorT saLogDispatch(SaLogHandleT l
> >  SaAisErrorT saLogFinalize(SaLogHandleT logHandle)
> >  {
> >     lga_client_hdl_rec_t *hdl_rec;
> > -   lgsv_msg_t msg, *o_msg = NULL;
> > -   SaAisErrorT rc = SA_AIS_OK;
> > -   uint32_t mds_rc;
> > +   SaAisErrorT ais_rc = SA_AIS_OK;
> > +   uint32_t rc;
> >
> >     TRACE_ENTER();
> >
> >     /* retrieve hdl rec */
> >     hdl_rec = ncshm_take_hdl(NCS_SERVICE_ID_LGA, logHandle);
> >     if (hdl_rec == NULL) {
> > -           TRACE("ncshm_take_hdl failed");
> > -           rc = SA_AIS_ERR_BAD_HANDLE;
> > +           TRACE("%s ncshm_take_hdl failed",
> __FUNCTION__);
> > +           ais_rc = SA_AIS_ERR_BAD_HANDLE;
> >             goto done;
> >     }
> >
> > -   /* Check Whether LGS is up or not */
> > -   if (!lga_cb.lgs_up) {
> > -           TRACE("LGS down");
> > -           rc = SA_AIS_ERR_TRY_AGAIN;
> > +   /***
> > +    * Handle states
> > +    * Synchronize with mds and recovery thread (mutex)
> > +    */
> > +   pthread_mutex_lock(&lga_cb.cb_lock);
> > +   lgs_state_t lgs_state = lga_cb.lgs_state;
> > +   lga_state_t lga_state = lga_cb.lga_state;
> > +   pthread_mutex_unlock(&lga_cb.cb_lock);
> > +
> > +   if (lgs_state == LGS_NO_ACTIVE) {
> > +           /* We have a server but it is temporary
> unavailable. Client may
> > +            * try again
> > +            */
> > +           TRACE("%s lgs_state = LGS no active",
> __FUNCTION__);
> > +           ais_rc = SA_AIS_ERR_TRY_AGAIN;
> >             goto done_give_hdl;
> >     }
> >
> > -    /** populate & send the finalize message
> > -     ** and make sure the finalize from the server
> > -     ** end returned before deleting the local records.
> > -     **/
> > -   memset(&msg, 0, sizeof(lgsv_msg_t));
> > -   msg.type = LGSV_LGA_API_MSG;
> > -   msg.info.api_info.type = LGSV_FINALIZE_REQ;
> > -   msg.info.api_info.param.finalize.client_id =
> > hdl_rec->lgs_client_id;
> > -
> > -   mds_rc = lga_mds_msg_sync_send(&lga_cb, &msg, &o_msg,
> > LGS_WAIT_TIME,MDS_SEND_PRIORITY_MEDIUM);
> > -   switch (mds_rc) {
> > -   case NCSCC_RC_SUCCESS:
> > -           break;
> > -   case NCSCC_RC_REQ_TIMOUT:
> > -           rc = SA_AIS_ERR_TIMEOUT;
> > -           TRACE("lga_mds_msg_sync_send FAILED: %u",
> rc);
> > -           goto done_give_hdl;
> > -   default:
> > -           TRACE("lga_mds_msg_sync_send FAILED: %u",
> rc);
> > -           rc = SA_AIS_ERR_NO_RESOURCES;
> > +   if (lga_state == LGA_NO_SERVER) {
> > +           /* We have no server but can still finalize client.
> > +            * In this situation no message to server is sent
> > +            */
> > +           TRACE("%s lga_state = LGS down",
> __FUNCTION__);
> > +           ais_rc = SA_AIS_OK;
> >             goto done_give_hdl;
> >     }
> >
> > -   if (o_msg != NULL) {
> > -           rc = o_msg->info.api_resp_info.rc;
> > -           lga_msg_destroy(o_msg);
> > -   } else
> > -           rc = SA_AIS_ERR_NO_RESOURCES;
> > +   if (lga_state == LGA_RECOVERY2) {
> > +           /* Auto recovery is ongoing. We have to wait for
> it to finish.
> > +            * The client may try again
> > +            */
> > +           TRACE("%s lga_state = LGA auto recovery
> ongoing (2)",
> > __FUNCTION__);
> > +           ais_rc = SA_AIS_ERR_TRY_AGAIN;
> > +           goto done_give_hdl;
> > +   }
> >
> > -   if (rc == SA_AIS_OK) {
> > -           rc = lga_hdl_rec_del(&lga_cb.client_list,
> hdl_rec);
> > -           if (rc != NCSCC_RC_SUCCESS)
> > -                   rc = SA_AIS_ERR_BAD_HANDLE;
> > +   if (lga_state == LGA_RECOVERY1) {
> > +           /* We are in recovery state 1. Client may or may
> not have been
> > +            * initialized. If initialized a finalize request must
> be sent
> > +            * to the server else the client is finalized in the
> agent only
> > +            */
> > +           TRACE("%s lga_state = Recovery state (1)",
> __FUNCTION__);
> > +           if (hdl_rec->initialized_flag == false) {
> > +                   TRACE("\t Client is not
> initialized");
> > +                   goto done_give_hdl;
> > +           }
> > +           TRACE("\t Client is initialized");
> > +   }
> > +
> > +   /***
> > +    * Populate & send the finalize message
> > +    * and make sure the finalize from the server
> > +    * end returned before deleting the local records.
> > +    */
> > +   ais_rc = send_Finalize_msg(hdl_rec);
> > +
> > +   if (ais_rc == SA_AIS_OK) {
> > +           TRACE("%s delete_one_client",
> __FUNCTION__);
> > +           (void) delete_one_client(&lga_cb.client_list,
> hdl_rec);
> >     }
> >
> >   done_give_hdl:
> >     ncshm_give_hdl(logHandle);
> >
> > -   if (rc == SA_AIS_OK) {
> > -           rc = lga_shutdown();
> > +   if (ais_rc == SA_AIS_OK) {
> > +           rc = lga_shutdown_after_last_client();
> >             if (rc != NCSCC_RC_SUCCESS)
> >                     TRACE("lga_shutdown ");
> >     }
> >
> >   done:
> > -   TRACE_LEAVE2("rc = %u", rc);
> > -   return rc;
> > +   TRACE_LEAVE2("ais_rc = %s", saf_error(ais_rc));
> > +   return ais_rc;
> >  }
> >
> > -static SaAisErrorT validate_open_params(SaLogHandleT logHandle,
> > -                                   const
> SaNameT *logStreamName,
> > -                                   const
> SaLogFileCreateAttributesT_2 *logFileCreateAttributes,
> > -
>       SaLogStreamOpenFlagsT logStreamOpenFlags,
> > -
>       SaTimeT timeOut, SaLogStreamHandleT *logStreamHandle,
> uint32_t
> > *header_type)
> >
> +/*********************************************************
> *********************
> > + * Open a stream
> > + * API function and help functions
> > +
> >
> **********************************************************
> ********************/
> > +
> > +/**
> > + * Check input parameters for opening a stream
> > + *
> > + * @param logStreamName
> > + * @param logFileCreateAttributes
> > + * @param logStreamOpenFlags
> > + * @param logStreamHandle
> > + * @param header_type
> > + * @return
> > + */
> > +static SaAisErrorT validate_open_params(
> > +   const SaNameT *logStreamName,
> > +   const SaLogFileCreateAttributesT_2 *logFileCreateAttributes,
> > +   SaLogStreamOpenFlagsT logStreamOpenFlags,
> > +   SaLogStreamHandleT *logStreamHandle,
> > +   uint32_t *header_type
> > +   )
> >  {
> >     size_t len;
> > -   SaAisErrorT rc = SA_AIS_OK;
> > +   SaAisErrorT ais_rc = SA_AIS_OK;
> >
> >     TRACE_ENTER();
> >
> > @@ -435,7 +569,7 @@ static SaAisErrorT validate_open_params(
> >
> >     if ((NULL == logStreamName) || (NULL == logStreamHandle)) {
> >             TRACE("SA_AIS_ERR_INVALID_PARAM => NULL
> pointer check");
> > -           rc = SA_AIS_ERR_INVALID_PARAM;
> > +           ais_rc = SA_AIS_ERR_INVALID_PARAM;
> >             goto done;
> >     }
> >
> > @@ -450,7 +584,7 @@ static SaAisErrorT validate_open_params(
> >      */
> >     if (logStreamName->length >= SA_MAX_NAME_LENGTH) {
> >             TRACE("SA_AIS_ERR_INVALID_PARAM,
> logStreamName->length >
> > SA_MAX_NAME_LENGTH");
> > -           rc = SA_AIS_ERR_INVALID_PARAM;
> > +           ais_rc = SA_AIS_ERR_INVALID_PARAM;
> >             goto done;
> >     }
> >
> > @@ -575,10 +709,11 @@ static SaAisErrorT validate_open_params(
> >
> >   done:
> >     TRACE_LEAVE();
> > -   return rc;
> > +   return ais_rc;
> >  }
> >
> >  /**
> > + * API function for opening a stream
> >   *
> >   * @param logHandle
> >   * @param logStreamName
> > @@ -599,29 +734,85 @@ SaAisErrorT saLogStreamOpen_2(SaLogHandl
> >     lga_client_hdl_rec_t *hdl_rec;
> >     lgsv_msg_t msg, *o_msg = NULL;
> >     lgsv_stream_open_req_t *open_param;
> > -   SaAisErrorT rc;
> > +   SaAisErrorT ais_rc;
> > +   int rc = 0;
> > +   uint32_t ncs_rc;
> >     uint32_t timeout;
> >     uint32_t log_stream_id;
> >     uint32_t log_header_type = 0;
> >
> >     TRACE_ENTER();
> >
> > -   rc = validate_open_params(logHandle, logStreamName,
> > logFileCreateAttributes,
> > -
> logStreamOpenFlags, timeOut, logStreamHandle,
> > &log_header_type);
> > -   if (rc != SA_AIS_OK)
> > +   ais_rc = validate_open_params(logStreamName,
> > logFileCreateAttributes,
> > +
> logStreamOpenFlags, logStreamHandle, &log_header_type);
> > +   if (ais_rc != SA_AIS_OK)
> >             goto done;
> >
> >     /* retrieve log service hdl rec */
> >     hdl_rec = ncshm_take_hdl(NCS_SERVICE_ID_LGA, logHandle);
> >     if (hdl_rec == NULL) {
> >             TRACE("ncshm_take_hdl failed");
> > -           rc = SA_AIS_ERR_BAD_HANDLE;
> > +           ais_rc = SA_AIS_ERR_BAD_HANDLE;
> >             goto done;
> >     }
> >
> > +   /***
> > +    * Handle states
> > +    * Synchronize with mds and recovery thread (mutex)
> > +    */
> > +   pthread_mutex_lock(&lga_cb.cb_lock);
> > +   lgs_state_t lgs_state = lga_cb.lgs_state;
> > +   lga_state_t lga_state = lga_cb.lga_state;
> > +   pthread_mutex_unlock(&lga_cb.cb_lock);
> > +
> > +   if (lgs_state == LGS_NO_ACTIVE) {
> > +           /* We have a server but it is temporary
> unavailable. Client may
> > +            * try again
> > +            */
> > +           TRACE("%s LGS no active", __FUNCTION__);
> > +           ais_rc = SA_AIS_ERR_TRY_AGAIN;
> > +           goto done_give_hdl;
> > +   }
> > +
> > +   if (lga_state == LGA_NO_SERVER) {
> > +           /* We have no server and cannot open a
> stream.
> > +            * The client may try again
> > +            */
> > +           TRACE("%s No server", __FUNCTION__);
> > +           ais_rc = SA_AIS_ERR_TRY_AGAIN;
> > +           goto done_give_hdl;
> > +   }
> > +
> > +   if (lga_state == LGA_RECOVERY2) {
> > +           /* Auto recovery is ongoing. We have to wait for
> it to finish.
> > +            * The client may try again
> > +            */
> > +           TRACE("%s LGA auto recovery ongoing (2)",
> __FUNCTION__);
> > +           ais_rc = SA_AIS_ERR_TRY_AGAIN;
> > +           goto done_give_hdl;
> > +   }
> > +
> > +   if (lga_state == LGA_RECOVERY1) {
> > +           /* We are in recovery 1 state.
> > +            * Recover client and execute the request
> > +            */
> > +           rc = recover_one_client(hdl_rec);
> > +           if (rc == -1) {
> > +                   /* Client could not be recovered.
> Delete client and
> > +                    * return BAD HANDLE
> > +                    */
> > +                   TRACE("%s delete_one_client",
> __FUNCTION__);
> > +                   (void)
> delete_one_client(&lga_cb.client_list, hdl_rec);
> > +                   ais_rc =
> SA_AIS_ERR_BAD_HANDLE;
> > +                   /* Handles are destroyed so we
> shall not give handles */
> > +                   goto done;
> > +           }
> > +   }
> > +
> > +
> >      /** Populate a sync MDS message to obtain a log stream id and an
> > -     **  instance open id.
> > -     **/
> > +     *  instance open id.
> > +     */
> >     memset(&msg, 0, sizeof(lgsv_msg_t));
> >     msg.type = LGSV_LGA_API_MSG;
> >     msg.info.api_info.type = LGSV_STREAM_OPEN_REQ;
> > @@ -641,7 +832,7 @@ SaAisErrorT saLogStreamOpen_2(SaLogHandl
> >             /* Construct the logFileName */
> >             open_param->logFileName = (char *)
> > malloc(strlen(logFileCreateAttributes->logFileName) + 1);
> >             if (open_param->logFileName == NULL) {
> > -                   rc = SA_AIS_ERR_NO_MEMORY;
> > +                   ais_rc =
> SA_AIS_ERR_NO_MEMORY;
> >                     goto done_give_hdl;
> >             }
> >             strcpy(open_param->logFileName,
> > logFileCreateAttributes->logFileName);
> > @@ -653,7 +844,7 @@ SaAisErrorT saLogStreamOpen_2(SaLogHandl
> >
> >             open_param->logFilePathName = (char *)
> malloc(len);
> >             if (open_param->logFilePathName == NULL) {
> > -                   rc = SA_AIS_ERR_NO_MEMORY;
> > +                   ais_rc =
> SA_AIS_ERR_NO_MEMORY;
> >                     goto done_give_hdl;
> >             }
> >
> > @@ -668,31 +859,21 @@ SaAisErrorT saLogStreamOpen_2(SaLogHandl
> >
> >     if (timeout < NCS_SAF_MIN_ACCEPT_TIME) {
> >             TRACE("Timeout");
> > -           rc = SA_AIS_ERR_TIMEOUT;
> > -           goto done_give_hdl;
> > -   }
> > -
> > -   /* Check whether LGS is up or not */
> > -   if (!lga_cb.lgs_up) {
> > -           TRACE("LGS down");
> > -           rc = SA_AIS_ERR_TRY_AGAIN;
> > +           ais_rc = SA_AIS_ERR_TIMEOUT;
> >             goto done_give_hdl;
> >     }
> >
> >     /* Send a sync MDS message to obtain a log stream id */
> > -   rc = lga_mds_msg_sync_send(&lga_cb, &msg, &o_msg,
> > timeout,MDS_SEND_PRIORITY_HIGH);
> > -   if (rc != NCSCC_RC_SUCCESS) {
> > -           if (o_msg)
> > -                   lga_msg_destroy(o_msg);
> > -           rc = SA_AIS_ERR_TRY_AGAIN;
> > +   ncs_rc = lga_mds_msg_sync_send(&lga_cb, &msg, &o_msg,
> timeout,
> > MDS_SEND_PRIORITY_HIGH);
> > +   if (ncs_rc != NCSCC_RC_SUCCESS) {
> > +           ais_rc = SA_AIS_ERR_TRY_AGAIN;
> >             goto done_give_hdl;
> >     }
> >
> > -   if (SA_AIS_OK != o_msg->info.api_resp_info.rc) {
> > -           rc = o_msg->info.api_resp_info.rc;
> > -           TRACE("Bad return status!!! rc = %d", rc);
> > -           if (o_msg)
> > -                   lga_msg_destroy(o_msg);
> > +   ais_rc = o_msg->info.api_resp_info.rc;
> > +   if (SA_AIS_OK != ais_rc) {
> > +           TRACE("Bad return status!!! rc = %d", ais_rc);
> > +           lga_msg_destroy(o_msg);
> >             goto done_give_hdl;
> >     }
> >
> > @@ -708,25 +889,28 @@ SaAisErrorT saLogStreamOpen_2(SaLogHandl
> >      /** Allocate an LGA_LOG_STREAM_HDL_REC structure and insert this
> >       *  into the list of channel hdl record.
> >       **/
> > -   lstr_hdl_rec = lga_log_stream_hdl_rec_add(&hdl_rec,
> > -
>         log_stream_id, logStreamOpenFlags, logStreamName,
> > log_header_type);
> > +   lstr_hdl_rec = lga_log_stream_hdl_rec_add(
> > +           &hdl_rec,
> > +           log_stream_id, logStreamOpenFlags,
> > +           logStreamName, log_header_type
> > +           );
> >     if (lstr_hdl_rec == NULL) {
> >             pthread_mutex_unlock(&lga_cb.cb_lock);
> > -           if (o_msg)
> > -                   lga_msg_destroy(o_msg);
> > -           rc = SA_AIS_ERR_NO_MEMORY;
> > +           lga_msg_destroy(o_msg);
> > +           ais_rc = SA_AIS_ERR_NO_MEMORY;
> >             goto done_give_hdl;
> >     }
> > +
> >      /** UnLock LGA_CB
> >       **/
> >     pthread_mutex_unlock(&lga_cb.cb_lock);
> >
> > -    /** Give the hdl-mgr allocated hdl to the application.
> > -     **/
> > +    /** Give the hdl-mgr allocated hdl to the application and free
> the
> > response
> > +     *  message
> > +      **/
> >     *logStreamHandle =
> > (SaLogStreamHandleT)lstr_hdl_rec->log_stream_hdl;
> >
> > -   if (o_msg)
> > -           lga_msg_destroy(o_msg);
> > +   lga_msg_destroy(o_msg);
> >
> >   done_give_hdl:
> >     ncshm_give_hdl(logHandle);
> > @@ -735,7 +919,7 @@ SaAisErrorT saLogStreamOpen_2(SaLogHandl
> >
> >   done:
> >     TRACE_LEAVE();
> > -   return rc;
> > +   return ais_rc;
> >  }
> >
> >  /**
> > @@ -758,6 +942,136 @@ SaAisErrorT saLogStreamOpenAsync_2(SaLog
> >     return SA_AIS_ERR_NOT_SUPPORTED;
> >  }
> >
> >
> +/*********************************************************
> *********************
> > + * Write Log record
> > + * API function and help functions
> > +
> >
> **********************************************************
> ********************/
> > +
> > +/**
> > + * Validate the log record and if generic header add
> > + * logSvcUsrName from environment variable
> SA_AMF_COMPONENT_NAME
> > + *
> > + * @param logRecord[in]
> > + * @param logSvcUsrName[out]
> > + * @param write_param[out]
> > + * @return AIS return code
> > + */
> > +static SaAisErrorT handle_log_record(const SaLogRecordT *logRecord,
> > +   SaNameT *logSvcUsrName,
> > +   lgsv_write_log_async_req_t *write_param)
> > +{
> > +   SaAisErrorT ais_rc = SA_AIS_OK;
> > +   SaTimeT logTimeStamp;
> > +
> > +   TRACE_ENTER();
> > +
> > +   if (NULL == logRecord) {
> > +           TRACE("SA_AIS_ERR_INVALID_PARAM => NULL
> pointer check");
> > +           ais_rc = SA_AIS_ERR_INVALID_PARAM;
> > +           goto done;
> > +   }
> > +
> > +   if (logRecord->logHdrType == SA_LOG_GENERIC_HEADER) {
> > +           switch (logRecord-
> >logHeader.genericHdr.logSeverity) {
> > +           case SA_LOG_SEV_EMERGENCY:
> > +           case SA_LOG_SEV_ALERT:
> > +           case SA_LOG_SEV_CRITICAL:
> > +           case SA_LOG_SEV_ERROR:
> > +           case SA_LOG_SEV_WARNING:
> > +           case SA_LOG_SEV_NOTICE:
> > +           case SA_LOG_SEV_INFO:
> > +                   break;
> > +           default:
> > +                   TRACE("Invalid severity: %x",
> > +                           logRecord-
> >logHeader.genericHdr.logSeverity);
> > +                   ais_rc =
> SA_AIS_ERR_INVALID_PARAM;
> > +                   goto done;
> > +           }
> > +   }
> > +
> > +   if (logRecord->logBuffer != NULL) {
> > +           if ((logRecord->logBuffer->logBuf == NULL) &&
> > +                   (logRecord->logBuffer-
> >logBufSize != 0)) {
> > +                   TRACE("logBuf == NULL &&
> logBufSize != 0");
> > +                   ais_rc =
> SA_AIS_ERR_INVALID_PARAM;
> > +                   goto done;
> > +           }
> > +   }
> > +
> > +   /* Set timeStamp data if not provided by application user */
> > +   if (logRecord->logTimeStamp == SA_TIME_UNKNOWN) {
> > +           logTimeStamp = setLogTime();
> > +           write_param->logTimeStamp = &logTimeStamp;
> > +   } else {
> > +           write_param->logTimeStamp = (SaTimeT
> *)&logRecord->logTimeStamp;
> > +   }
> > +
> > +   /* SA_AIS_ERR_INVALID_PARAM, bullet 2 in SAI-AIS-LOG-
> A.02.01
> > +      Section 3.6.3, Return Values */
> > +   if (logRecord->logHdrType == SA_LOG_GENERIC_HEADER) {
> > +           if (logRecord-
> >logHeader.genericHdr.logSvcUsrName == NULL) {
> > +                   char *logSvcUsrChars = NULL;
> > +                   TRACE("logSvcUsrName ==
> NULL");
> > +                   logSvcUsrChars =
> getenv("SA_AMF_COMPONENT_NAME");
> > +                   if (logSvcUsrChars == NULL) {
> > +                           ais_rc =
> SA_AIS_ERR_INVALID_PARAM;
> > +                           goto done;
> > +                   }
> > +                   logSvcUsrName->length =
> strlen(logSvcUsrChars);
> > +                   if (logSvcUsrName->length >=
> SA_MAX_NAME_LENGTH) {
> > +
>       TRACE("SA_AMF_COMPONENT_NAME is too long");
> > +                           ais_rc =
> SA_AIS_ERR_INVALID_PARAM;
> > +                           goto done;
> > +                   }
> > +                   strcpy((char *)logSvcUsrName-
> >value, logSvcUsrChars);
> > +                   write_param->logSvcUsrName =
> logSvcUsrName;
> > +           } else {
> > +                   if (logRecord-
> >logHeader.genericHdr.logSvcUsrName->length >=
> > +
>       SA_MAX_NAME_LENGTH) {
> > +
>       TRACE("logSvcUsrName too long");
> > +                           ais_rc =
> SA_AIS_ERR_INVALID_PARAM;
> > +                           goto done;
> > +                   }
> > +                   logSvcUsrName->length =
> > +                           logRecord-
> >logHeader.genericHdr.logSvcUsrName->length;
> > +                   write_param->logSvcUsrName =
> > +                           (SaNameT
> *)logRecord->logHeader.genericHdr.logSvcUsrName;
> > +           }
> > +   }
> > +
> > +   if (logRecord->logHdrType == SA_LOG_NTF_HEADER) {
> > +           if (logRecord-
> >logHeader.ntfHdr.notificationObject == NULL) {
> > +                   TRACE("notificationObject ==
> NULL");
> > +                   ais_rc =
> SA_AIS_ERR_INVALID_PARAM;
> > +                   goto done;
> > +           }
> > +
> > +           if (logRecord-
> >logHeader.ntfHdr.notificationObject->length >=
> > +                   SA_MAX_NAME_LENGTH) {
> > +                   TRACE("notificationObject.length
> >= SA_MAX_NAME_LENGTH");
> > +                   ais_rc =
> SA_AIS_ERR_INVALID_PARAM;
> > +                   goto done;
> > +           }
> > +
> > +           if (logRecord->logHeader.ntfHdr.notifyingObject
> == NULL) {
> > +                   TRACE("notifyingObject ==
> NULL");
> > +                   ais_rc =
> SA_AIS_ERR_INVALID_PARAM;
> > +                   goto done;
> > +           }
> > +
> > +           if (logRecord-
> >logHeader.ntfHdr.notifyingObject->length >=
> > +                   SA_MAX_NAME_LENGTH) {
> > +                   TRACE("notifyingObject.length >=
> SA_MAX_NAME_LENGTH");
> > +                   ais_rc =
> SA_AIS_ERR_INVALID_PARAM;
> > +                   goto done;
> > +           }
> > +   }
> > +
> > +done:
> > +   TRACE_LEAVE();
> > +   return ais_rc;
> > +}
> > +
> >  /**
> >   *
> >   * @param logStreamHandle
> > @@ -788,158 +1102,125 @@ SaAisErrorT saLogWriteLogAsync(SaLogStre
> >     lga_log_stream_hdl_rec_t *lstr_hdl_rec;
> >     lga_client_hdl_rec_t *hdl_rec;
> >     lgsv_msg_t msg;
> > -   SaAisErrorT rc = SA_AIS_OK;
> > +   SaAisErrorT ais_rc = SA_AIS_OK;
> > +   lgsv_write_log_async_req_t *write_param;
> >     SaNameT logSvcUsrName;
> > -   SaTimeT logTimeStamp;
> > -   lgsv_write_log_async_req_t *write_param;
> > +   int rc;
> >
> >     memset(&(msg), 0, sizeof(lgsv_msg_t));
> >     write_param = &msg.info.api_info.param.write_log_async;
> >     TRACE_ENTER();
> >
> > -   if (NULL == logRecord) {
> > -           TRACE("SA_AIS_ERR_INVALID_PARAM => NULL
> pointer check");
> > -           rc = SA_AIS_ERR_INVALID_PARAM;
> > +   if ((ackFlags != 0) && (ackFlags !=
> SA_LOG_RECORD_WRITE_ACK)) {
> > +           TRACE("SA_AIS_ERR_BAD_FLAGS=> ackFlags");
> > +           ais_rc = SA_AIS_ERR_BAD_FLAGS;
> >             goto done;
> >     }
> >
> > -   if (logRecord->logHdrType == SA_LOG_GENERIC_HEADER) {
> > -           switch (logRecord-
> >logHeader.genericHdr.logSeverity) {
> > -           case SA_LOG_SEV_EMERGENCY:
> > -           case SA_LOG_SEV_ALERT:
> > -           case SA_LOG_SEV_CRITICAL:
> > -           case SA_LOG_SEV_ERROR:
> > -           case SA_LOG_SEV_WARNING:
> > -           case SA_LOG_SEV_NOTICE:
> > -           case SA_LOG_SEV_INFO:
> > -                   break;
> > -           default:
> > -                   TRACE("Invalid severity: %x",
> > logRecord->logHeader.genericHdr.logSeverity);
> > -                   rc =
> SA_AIS_ERR_INVALID_PARAM;
> > -                   goto done;
> > -           }
> > -   }
> > -
> > -   if (logRecord->logBuffer != NULL) {
> > -           if ((logRecord->logBuffer->logBuf == NULL) &&
> > (logRecord->logBuffer->logBufSize != 0)) {
> > -                   TRACE("logBuf == NULL &&
> logBufSize != 0");
> > -                   rc =
> SA_AIS_ERR_INVALID_PARAM;
> > -                   goto done;
> > -           }
> > -   }
> > -
> > -   if ((ackFlags != 0) && (ackFlags !=
> SA_LOG_RECORD_WRITE_ACK)) {
> > -           TRACE("SA_AIS_ERR_BAD_FLAGS=> ackFlags");
> > -           rc = SA_AIS_ERR_BAD_FLAGS;
> > +   /* Validate the log record and if generic header add
> > +    * logSvcUsrName from environment variable
> SA_AMF_COMPONENT_NAME
> > +    */
> > +   ais_rc = handle_log_record(logRecord, &logSvcUsrName,
> write_param);
> > +   if (ais_rc != SA_AIS_OK) {
> > +           TRACE("%s: Validate Log record Fail",
> __FUNCTION__);
> >             goto done;
> >     }
> >
> > -   /* Set timeStamp data if not provided by application user */
> > -   if (logRecord->logTimeStamp == SA_TIME_UNKNOWN) {
> > -           logTimeStamp = setLogTime();
> > -           write_param->logTimeStamp = &logTimeStamp;
> > -   } else {
> > -           write_param->logTimeStamp = (SaTimeT
> *)&logRecord->logTimeStamp;
> > -   }
> > -
> > -   /* SA_AIS_ERR_INVALID_PARAM, bullet 2 in SAI-AIS-LOG-
> A.02.01
> > -      Section 3.6.3, Return Values */
> > -   if (logRecord->logHdrType == SA_LOG_GENERIC_HEADER) {
> > -           if (logRecord-
> >logHeader.genericHdr.logSvcUsrName == NULL) {
> > -                   char *logSvcUsrChars = NULL;
> > -                   TRACE("logSvcUsrName ==
> NULL");
> > -                   logSvcUsrChars =
> getenv("SA_AMF_COMPONENT_NAME");
> > -                   if (logSvcUsrChars == NULL) {
> > -                           rc =
> SA_AIS_ERR_INVALID_PARAM;
> > -                           goto done;
> > -                   }
> > -                   logSvcUsrName.length =
> strlen(logSvcUsrChars);
> > -                   if (logSvcUsrName.length >=
> SA_MAX_NAME_LENGTH) {
> > -
>       TRACE("SA_AMF_COMPONENT_NAME is too long");
> > -                           rc =
> SA_AIS_ERR_INVALID_PARAM;
> > -                           goto done;
> > -                   }
> > -                   strcpy((char
> *)logSvcUsrName.value, logSvcUsrChars);
> > -                   write_param->logSvcUsrName =
> &logSvcUsrName;
> > -           } else {
> > -                   if (logRecord-
> >logHeader.genericHdr.logSvcUsrName->length >=
> > SA_MAX_NAME_LENGTH) {
> > -
>       TRACE("logSvcUsrName too long");
> > -                           rc =
> SA_AIS_ERR_INVALID_PARAM;
> > -                           goto done;
> > -                   }
> > -                   logSvcUsrName.length =
> > logRecord->logHeader.genericHdr.logSvcUsrName->length;
> > -                   write_param->logSvcUsrName =
> (SaNameT
> > *)logRecord->logHeader.genericHdr.logSvcUsrName;
> > -           }
> > -   }
> > -
> > -   if (logRecord->logHdrType == SA_LOG_NTF_HEADER) {
> > -           if (logRecord-
> >logHeader.ntfHdr.notificationObject == NULL) {
> > -                   TRACE("notificationObject ==
> NULL");
> > -                   rc =
> SA_AIS_ERR_INVALID_PARAM;
> > -                   goto done;
> > -           }
> > -
> > -           if (logRecord-
> >logHeader.ntfHdr.notificationObject->length >=
> > SA_MAX_NAME_LENGTH) {
> > -                   TRACE("notificationObject.length
> >= SA_MAX_NAME_LENGTH");
> > -                   rc =
> SA_AIS_ERR_INVALID_PARAM;
> > -                   goto done;
> > -           }
> > -
> > -           if (logRecord->logHeader.ntfHdr.notifyingObject
> == NULL) {
> > -                   TRACE("notifyingObject ==
> NULL");
> > -                   rc =
> SA_AIS_ERR_INVALID_PARAM;
> > -                   goto done;
> > -           }
> > -
> > -           if (logRecord-
> >logHeader.ntfHdr.notifyingObject->length >=
> > SA_MAX_NAME_LENGTH) {
> > -                   TRACE("notifyingObject.length >=
> SA_MAX_NAME_LENGTH");
> > -                   rc =
> SA_AIS_ERR_INVALID_PARAM;
> > -                   goto done;
> > -           }
> > -   }
> > -
> > -   /* retrieve log stream hdl record */
> > +   /* Retrieve log stream hdl record
> > +    * From now on we must give stream before return
> > +    */
> >     lstr_hdl_rec = ncshm_take_hdl(NCS_SERVICE_ID_LGA,
> logStreamHandle);
> >     if (lstr_hdl_rec == NULL) {
> > -           TRACE("ncshm_take_hdl logStreamHandle
> FAILED!");
> > -           rc = SA_AIS_ERR_BAD_HANDLE;
> > +           TRACE("%s: ncshm_take_hdl logStreamHandle
> FAILED!",
> > +                   __FUNCTION__);
> > +           ais_rc = SA_AIS_ERR_BAD_HANDLE;
> >             goto done;
> >     }
> >
> >     /* SA_AIS_ERR_INVALID_PARAM, bullet 1 in SAI-AIS-LOG-
> A.02.01
> >        Section 3.6.3, Return Values */
> >     if (lstr_hdl_rec->log_header_type != logRecord->logHdrType)
> {
> > -           TRACE("lstr_hdl_rec->log_header_type !=
> logRecord->logHdrType");
> > -           ncshm_give_hdl(logStreamHandle);
> > -           rc = SA_AIS_ERR_INVALID_PARAM;
> > -           goto done;
> > +           TRACE("%s: lstr_hdl_rec->log_header_type !=
> > logRecord->logHdrType",
> > +                   __FUNCTION__);
> > +           ais_rc = SA_AIS_ERR_INVALID_PARAM;
> > +           goto done_give_hdl_stream;
> >     }
> >
> > -   /* retrieve the lga client hdl record */
> > +   /* retrieve the lga client hdl record
> > +    * From now on we must give both stream and client (parent)
> handle
> > +    * before return
> > +    */
> >     hdl_rec = ncshm_take_hdl(NCS_SERVICE_ID_LGA,
> > lstr_hdl_rec->parent_hdl->local_hdl);
> >     if (hdl_rec == NULL) {
> > -           TRACE("ncshm_take_hdl logHandle FAILED!");
> > -           ncshm_give_hdl(logStreamHandle);
> > -           rc = SA_AIS_ERR_LIBRARY;
> > -           goto done;
> > +           TRACE("%s: ncshm_take_hdl logHandle
> FAILED!",
> > +                   __FUNCTION__);
> > +           ais_rc = SA_AIS_ERR_LIBRARY;
> > +           goto done_give_hdl_stream;
> >     }
> >
> >     if ((hdl_rec->reg_cbk.saLogWriteLogCallback == NULL) &&
> (ackFlags ==
> > SA_LOG_RECORD_WRITE_ACK)) {
> > -           TRACE("Write Callback not registered");
> > -           ncshm_give_hdl(logStreamHandle);
> > -           ncshm_give_hdl(hdl_rec->local_hdl);
> > -           rc = SA_AIS_ERR_INIT;
> > -           goto done;
> > +           TRACE("%s: Write Callback not registered",
> __FUNCTION__);
> > +           ais_rc = SA_AIS_ERR_INIT;
> > +           goto done_give_hdl_all;
> >     }
> >
> > +   /***
> > +    * Handle states
> > +    * Synchronize with mds and recovery thread (mutex)
> > +    */
> > +   pthread_mutex_lock(&lga_cb.cb_lock);
> > +   lgs_state_t lgs_state = lga_cb.lgs_state;
> > +   lga_state_t lga_state = lga_cb.lga_state;
> > +   pthread_mutex_unlock(&lga_cb.cb_lock);
> >
> > -   /* Check Whether LGS is up or not */
> > -   if (!lga_cb.lgs_up) {
> > -           ncshm_give_hdl(logStreamHandle);
> > -           ncshm_give_hdl(hdl_rec->local_hdl);
> > -           TRACE("LGS down");
> > -           rc = SA_AIS_ERR_TRY_AGAIN;
> > -           goto done;
> > +   if (lgs_state == LGS_NO_ACTIVE) {
> > +           /* We have a server but it is temporarily
> unavailable.
> > +            * Client may try again
> > +            */
> > +           TRACE("%s: LGS no active", __FUNCTION__);
> > +           ais_rc = SA_AIS_ERR_TRY_AGAIN;
> > +           goto done_give_hdl_all;
> > +   }
> > +
> > +   if (lga_state == LGA_NO_SERVER) {
> > +           /* We have no server and cannot write. The
> client may try again
> > +            */
> > +           TRACE("\t LGA_NO_SERVER");
> > +           ais_rc = SA_AIS_ERR_TRY_AGAIN;
> > +           goto done_give_hdl_all;
> > +   }
> > +
> > +   if (lga_state == LGA_RECOVERY2) {
> > +           /* Auto recovery is ongoing. We have to wait for
> it to finish.
> > +            * The client may try again
> > +            */
> > +           TRACE("\t LGA_RECOVERY2");
> > +           ais_rc = SA_AIS_ERR_TRY_AGAIN;
> > +           goto done_give_hdl_all;
> > +   }
> > +
> > +   if (lga_state == LGA_RECOVERY1) {
> > +           /* We are in recovery 1 state.
> > +            * Recover client and execute the request
> > +            */
> > +           TRACE("\t LGA_RECOVERY1");
> > +           rc = recover_one_client(hdl_rec);
> > +           if (rc == -1) {
> > +                   /* Client could not be recovered.
> Delete client and
> > +                    * return BAD HANDLE
> > +                    */
> > +                   TRACE("\t recover_one_client
> Fail");
> > +                   /* The log stream handle is not
> released in
> > +                    * delete_one_client()  so we
> have to do it here.
> > +                    * The function is used in other
> APIs that does not
> > +                    * take a log stream handle
> > +                    */
> > +
>       ncshm_give_hdl(logStreamHandle);
> > +                   (void)
> delete_one_client(&lga_cb.client_list, hdl_rec);
> > +                   ais_rc =
> SA_AIS_ERR_BAD_HANDLE;
> > +                   /* Handles are destroyed so we
> shall not give handles */
> > +                   goto done;
> > +           }
> >     }
> >
> >      /** populate the mds message to send across to the LGS
> > @@ -955,18 +1236,20 @@ SaAisErrorT saLogWriteLogAsync(SaLogStre
> >      /** Send the message out to the LGS
> >       **/
> >     if (NCSCC_RC_SUCCESS !=
> lga_mds_msg_async_send(&lga_cb, &msg,
> > MDS_SEND_PRIORITY_MEDIUM))
> > -           rc = SA_AIS_ERR_TRY_AGAIN;
> > +           ais_rc = SA_AIS_ERR_TRY_AGAIN;
> >
> > -    /** Give all the handles that were taken **/
> > -   ncshm_give_hdl(lstr_hdl_rec->log_stream_hdl);
> > + done_give_hdl_all:
> >     ncshm_give_hdl(hdl_rec->local_hdl);
> > + done_give_hdl_stream:
> > +   ncshm_give_hdl(logStreamHandle);
> >
> > - done:
> > +done:
> >     TRACE_LEAVE();
> > -   return rc;
> > +   return ais_rc;
> >  }
> >
> >  /**
> > + * API function for closing stream
> >   *
> >   * @param logStreamHandle
> >   *
> > @@ -977,34 +1260,85 @@ SaAisErrorT saLogStreamClose(SaLogStream
> >     lga_log_stream_hdl_rec_t *lstr_hdl_rec;
> >     lga_client_hdl_rec_t *hdl_rec;
> >     lgsv_msg_t msg, *o_msg = NULL;
> > -   SaAisErrorT rc = SA_AIS_OK;
> > +   SaAisErrorT ais_rc = SA_AIS_OK;
> >     uint32_t mds_rc;
> > +   int rc;
> >
> >     TRACE_ENTER();
> >
> >     lstr_hdl_rec = ncshm_take_hdl(NCS_SERVICE_ID_LGA,
> logStreamHandle);
> >     if (lstr_hdl_rec == NULL) {
> >             TRACE("ncshm_take_hdl logStreamHandle ");
> > -           rc = SA_AIS_ERR_BAD_HANDLE;
> > +           ais_rc = SA_AIS_ERR_BAD_HANDLE;
> >             goto done;
> >     }
> >
> > +   /***
> > +    * Handle states
> > +    * Synchronize with mds and recovery thread (mutex)
> > +    */
> > +   pthread_mutex_lock(&lga_cb.cb_lock);
> > +   lgs_state_t lgs_state = lga_cb.lgs_state;
> > +   lga_state_t lga_state = lga_cb.lga_state;
> > +   pthread_mutex_unlock(&lga_cb.cb_lock);
> > +
> > +   if (lgs_state == LGS_NO_ACTIVE) {
> > +           /* We have a server but it is temporarily
> unavailable. Client may
> > +            * try again
> > +            */
> > +           TRACE("%s LGS no active", __FUNCTION__);
> > +           ais_rc = SA_AIS_ERR_TRY_AGAIN;
> > +           goto done_give_hdl_stream;
> > +   }
> > +
> > +   if (lga_state == LGA_NO_SERVER) {
> > +           /* We have no server and cannot write. The
> client may try again
> > +            */
> > +           TRACE("%s No server", __FUNCTION__);
> > +           ais_rc = SA_AIS_ERR_TRY_AGAIN;
> > +           goto done_give_hdl_stream;
> > +   }
> > +
> > +   if (lga_state == LGA_RECOVERY2) {
> > +           /* Auto recovery is ongoing. We have to wait for
> it to finish.
> > +            * The client may try again
> > +            */
> > +           TRACE("%s LGA auto recovery ongoing (2)",
> __FUNCTION__);
> > +           ais_rc = SA_AIS_ERR_TRY_AGAIN;
> > +           goto done_give_hdl_stream;
> > +   }
> > +
> >     /* retrieve the client hdl record */
> >     hdl_rec = ncshm_take_hdl(NCS_SERVICE_ID_LGA,
> > lstr_hdl_rec->parent_hdl->local_hdl);
> >     if (hdl_rec == NULL) {
> >             TRACE("ncshm_take_hdl logHandle ");
> > -           rc = SA_AIS_ERR_LIBRARY;
> > +           ais_rc = SA_AIS_ERR_LIBRARY;
> >             goto done_give_hdl_stream;
> >     }
> >
> > -   /* Check Whether LGS is up or not */
> > -   if (!lga_cb.lgs_up) {
> > -           TRACE("LGS is down");
> > -           rc = SA_AIS_ERR_TRY_AGAIN;
> > -           goto done_give_hdl_all;
> > +   if (lga_state == LGA_RECOVERY1) {
> > +           /* We are in recovery 1 state.
> > +            * Recover client and execute the request
> > +            */
> > +           rc = recover_one_client(hdl_rec);
> > +           if (rc == -1) {
> > +                   /* Client could not be recovered.
> Delete client and
> > +                    * return BAD HANDLE
> > +                    */
> > +                   TRACE("%s Recover Fail
> delete_one_client", __FUNCTION__);
> > +                   /* The log stream handle is not
> released in
> > +                    * delete_one_client()  so we
> have to do it here.
> > +                    * The function is used in other
> APIs that does not
> > +                    * take a log stream handle
> > +                    */
> > +
>       ncshm_give_hdl(logStreamHandle);
> > +                   (void)
> delete_one_client(&lga_cb.client_list, hdl_rec);
> > +                   ais_rc =
> SA_AIS_ERR_BAD_HANDLE;
> > +                   /* Handles are destroyed so we
> shall not give handles */
> > +                   goto done;
> > +           }
> >     }
> >
> > -
> >      /** Populate a MDS message to send to the LGS for a channel
> >       *  close operation.
> >       **/
> > @@ -1018,22 +1352,22 @@ SaAisErrorT saLogStreamClose(SaLogStream
> >     case NCSCC_RC_SUCCESS:
> >             break;
> >     case NCSCC_RC_REQ_TIMOUT:
> > -           rc = SA_AIS_ERR_TIMEOUT;
> > -           TRACE("lga_mds_msg_sync_send FAILED: %u",
> rc);
> > +           ais_rc = SA_AIS_ERR_TIMEOUT;
> > +           TRACE("lga_mds_msg_sync_send FAILED: %s",
> saf_error(ais_rc));
> >             goto done_give_hdl_all;
> >     default:
> > -           TRACE("lga_mds_msg_sync_send FAILED: %u",
> rc);
> > -           rc = SA_AIS_ERR_NO_RESOURCES;
> > +           TRACE("lga_mds_msg_sync_send FAILED: %s",
> saf_error(ais_rc));
> > +           ais_rc = SA_AIS_ERR_NO_RESOURCES;
> >             goto done_give_hdl_all;
> >     }
> >
> >     if (o_msg != NULL) {
> > -           rc = o_msg->info.api_resp_info.rc;
> > +           ais_rc = o_msg->info.api_resp_info.rc;
> >             lga_msg_destroy(o_msg);
> >     } else
> > -           rc = SA_AIS_ERR_NO_RESOURCES;
> > +           ais_rc = SA_AIS_ERR_NO_RESOURCES;
> >
> > -   if (rc == SA_AIS_OK) {
> > +   if (ais_rc == SA_AIS_OK) {
> >             pthread_mutex_lock(&lga_cb.cb_lock);
> >
> >     /** Delete this log stream & the associated resources with this
> > @@ -1041,7 +1375,7 @@ SaAisErrorT saLogStreamClose(SaLogStream
> >          **/
> >             if (NCSCC_RC_SUCCESS !=
> > lga_log_stream_hdl_rec_del(&hdl_rec->stream_list, lstr_hdl_rec)) {
> >                     TRACE("Unable to delete log
> stream");
> > -                   rc = SA_AIS_ERR_LIBRARY;
> > +                   ais_rc = SA_AIS_ERR_LIBRARY;
> >             }
> >
> >             pthread_mutex_unlock(&lga_cb.cb_lock);
> > @@ -1054,7 +1388,7 @@ SaAisErrorT saLogStreamClose(SaLogStream
> >
> >   done:
> >     TRACE_LEAVE();
> > -   return rc;
> > +   return ais_rc;
> >  }
> >
> >  /**
> > diff --git a/osaf/libs/agents/saf/lga/lga_mds.c
> > b/osaf/libs/agents/saf/lga/lga_mds.c
> > --- a/osaf/libs/agents/saf/lga/lga_mds.c
> > +++ b/osaf/libs/agents/saf/lga/lga_mds.c
> > @@ -17,6 +17,7 @@
> >
> >  #include <stdlib.h>
> >  #include "lga.h"
> > +#include "lga_state.h"
> >
> >  static MDS_CLIENT_MSG_FORMAT_VER
> >
> LGA_WRT_LGS_MSG_FMT_ARRAY[LGA_WRT_LGS_SUBPART_VER_RANGE]
> = {
> > @@ -478,38 +479,56 @@ static uint32_t lga_lgs_msg_proc(lga_cb_
> >
> >
> **********************************************************
> ********************/
> >  static uint32_t lga_mds_svc_evt(struct ncsmds_callback_info
> > *mds_cb_info)
> >  {
> > -   TRACE_2("LGA Rcvd MDS subscribe evt from svc %d \n",
> > mds_cb_info->info.svc_evt.i_svc_id);
> > +   TRACE_ENTER();
> >
> >     switch (mds_cb_info->info.svc_evt.i_change) {
> >     case NCSMDS_NO_ACTIVE:
> > +           TRACE("%s\t NCSMDS_NO_ACTIVE",
> __FUNCTION__);
> > +           /* This is a temporary server down e.g. during
> switch/fail over*/
> > +           if (mds_cb_info->info.svc_evt.i_svc_id ==
> NCSMDS_SVC_ID_LGS) {
> > +
>       pthread_mutex_lock(&lga_cb.cb_lock);
> > +                   TRACE("NCSMDS_NO_ACTIVE");
> > +
> > +                   memset(&lga_cb.lgs_mds_dest,
> 0, sizeof(MDS_DEST));
> > +                   lga_cb.lgs_state =
> LGS_NO_ACTIVE;
> > +
>       pthread_mutex_unlock(&lga_cb.cb_lock);
> > +           }
> > +           break;
> >     case NCSMDS_DOWN:
> > +           TRACE("%s\t NCSMDS_DOWN",
> __FUNCTION__);
> > +           /* This may be a loss of server where all client
> and stream
> > information
> > +            * is lost on server side. In this situation client
> info in agent
> > is
> > +            * no longer valid and clients must register again
> (initialize)
> > +            */
> >             if (mds_cb_info->info.svc_evt.i_svc_id ==
> NCSMDS_SVC_ID_LGS) {
> > -           /** TBD what to do if LGS goes down
> > -                 ** Hold on to the subscription if possible
> > -                 ** to send them out if LGS comes back up
> > -                 **/
> > +
>       pthread_mutex_lock(&lga_cb.cb_lock);
> >                     TRACE("LGS down");
> > -
>       pthread_mutex_lock(&lga_cb.cb_lock);
> >                     memset(&lga_cb.lgs_mds_dest,
> 0, sizeof(MDS_DEST));
> > -                   lga_cb.lgs_up = 0;
> > +                   lga_cb.lgs_state = LGS_DOWN;
> >
>       pthread_mutex_unlock(&lga_cb.cb_lock);
> > +
> > +                   /* The log server is lost */
> > +                   lga_no_server_state_set();
> >             }
> >             break;
> >     case NCSMDS_NEW_ACTIVE:
> >     case NCSMDS_UP:
> >             switch (mds_cb_info->info.svc_evt.i_svc_id) {
> >             case NCSMDS_SVC_ID_LGS:
> > +                   TRACE("%s\t NCSMDS_UP" ,
> __FUNCTION__);
> >                 /** Store the MDS DEST of the LGS
> >                       **/
> > -                   TRACE_2("MSG from LGS
> NCSMDS_NEW_ACTIVE/UP");
> >
>       pthread_mutex_lock(&lga_cb.cb_lock);
> >                     lga_cb.lgs_mds_dest =
> mds_cb_info->info.svc_evt.i_dest;
> > -                   lga_cb.lgs_up = 1;
> > +                   lga_cb.lgs_state = LGS_UP;
> >                     if (lga_cb.lgs_sync_awaited) {
> >                             /* signal waiting
> thread */
> >
>       m_NCS_SEL_OBJ_IND(&lga_cb.lgs_sync_sel);
> >                     }
> >
>       pthread_mutex_unlock(&lga_cb.cb_lock);
> > +
> > +                   /* The log server is up */
> > +                   lga_serv_recov1state_set();
> >                     break;
> >             default:
> >                     break;
> > @@ -519,6 +538,7 @@ static uint32_t lga_mds_svc_evt(struct n
> >             break;
> >     }
> >
> > +   TRACE_LEAVE();
> >     return NCSCC_RC_SUCCESS;
> >  }
> >
> > @@ -1141,8 +1161,9 @@ uint32_t lga_mds_msg_sync_send(lga_cb_t
> >             /* Retrieve the response and take ownership of
> the memory  */
> >             *o_msg = (lgsv_msg_t
> *)mds_info.info.svc_send.info.sndrsp.o_rsp;
> >             mds_info.info.svc_send.info.sndrsp.o_rsp =
> NULL;
> > -   } else
> > +   } else {
> >             TRACE("lga_mds_msg_sync_send FAILED: %u",
> rc);
> > +   }
> >
> >     TRACE_LEAVE();
> >     return rc;
> > @@ -1184,8 +1205,9 @@ uint32_t lga_mds_msg_async_send(lga_cb_t
> >
> >     /* send the message */
> >     rc = ncsmds_api(&mds_info);
> > -   if (rc != NCSCC_RC_SUCCESS)
> > -           TRACE("failed");
> > +   if (rc != NCSCC_RC_SUCCESS) {
> > +           TRACE("%s: async send failed",
> __FUNCTION__);
> > +   }
> >
> >     TRACE_LEAVE();
> >     return rc;
> > diff --git a/osaf/libs/agents/saf/lga/lga_state.c
> > b/osaf/libs/agents/saf/lga/lga_state.c
> > new file mode 100644
> > --- /dev/null
> > +++ b/osaf/libs/agents/saf/lga/lga_state.c
> > @@ -0,0 +1,670 @@
> > +/*      -*- 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 "lga_state.h"
> > +#include <stdlib.h>
> > +#include <syslog.h>
> > +#include <pthread.h>
> > +#include <osaf_poll.h>
> > +#include <ncs_osprm.h>
> > +#include <osaf_time.h>
> > +#include <saf_error.h>
> > +
> > +/***
> > + * Common data
> > + */
> > +
> > +/* Selection object for terminating recovery thread for state 2
> > (after timeout)
> > + * NOTE: Only for recovery2_thread
> > + */
> > +static NCS_SEL_OBJ state2_terminate_sel_obj;
> > +
> > +static pthread_t recovery2_thread_id = 0;
> > +static pthread_mutex_t lga_recov_mutex =
> PTHREAD_MUTEX_INITIALIZER;
> > +
> >
> +/*********************************************************
> *********************
> > + * Functions used with server down recovery handling
> > +
> >
> **********************************************************
> ********************/
> > +
> > +static int start_recovery2_thread(void);
> > +
> >
> +/*********************************************************
> *********************
> > + * Functions for sending messages to the server used in the recovery
> > functions
> > + * Handles TRY AGAIN
> > +
> >
> **********************************************************
> ********************/
> > +
> > +/**
> > + * Send an initialize message to the server. A number of retries is
> > done if
> > + * return code is TRY AGAIN
> > + * The server returns a client id
> > + *
> > + * @param client_id[out]
> > + * @return -1 on error (client id not valid)
> > + */
> > +static int send_initialize_msg(uint32_t *client_id)
> > +{
> > +   SaVersionT version = {
> > +           .releaseCode = LOG_RELEASE_CODE,
> > +           .majorVersion = LOG_MAJOR_VERSION,
> > +           .minorVersion = LOG_MINOR_VERSION
> > +   };
> > +
> > +   SaAisErrorT ais_rc = SA_AIS_ERR_TRY_AGAIN;
> > +   uint32_t ncs_rc = NCSCC_RC_SUCCESS;
> > +   int rc = 0;
> > +   lgsv_msg_t i_msg, *o_msg = NULL;
> > +   uint32_t try_again_cnt = 10;
> > +   const uint32_t sleep_delay_ms = 100;
> > +
> > +   TRACE_ENTER();
> > +
> > +   /* Populate the message to be sent to the LGS */
> > +   memset(&i_msg, 0, sizeof(lgsv_msg_t));
> > +   i_msg.type = LGSV_LGA_API_MSG;
> > +   i_msg.info.api_info.type = LGSV_INITIALIZE_REQ;
> > +   i_msg.info.api_info.param.init.version = version;
> > +
> > +   /* Send a message to LGS to obtain a client_id
> > +    */
> > +   while(try_again_cnt > 0) {
> > +           ncs_rc = lga_mds_msg_sync_send(&lga_cb,
> &i_msg, &o_msg,
> > +
>       LGS_WAIT_TIME,MDS_SEND_PRIORITY_HIGH);
> > +           if (ncs_rc != NCSCC_RC_SUCCESS) {
> > +                   LOG_NO("%s
> lga_mds_msg_sync_send() Fail %d",
> > +                           __FUNCTION__,
> ncs_rc);
> > +                   rc = -1;
> > +                   goto done;
> > +           }
> > +
> > +           ais_rc = o_msg->info.api_resp_info.rc;
> > +           if (ais_rc == SA_AIS_ERR_TRY_AGAIN) {
> > +                   usleep(sleep_delay_ms * 1000);
> > +           } else {
> > +                   break;
> > +           }
> > +           try_again_cnt--;
> > +   }
> > +   if (SA_AIS_OK != ais_rc) {
> > +           TRACE("%s LGS error response %s",
> __FUNCTION__,
> > saf_error(ais_rc));
> > +           rc = -1;
> > +           goto free_done;
> > +   }
> > +
> > +   /* Initialize succeeded */
> > +   *client_id = o_msg-
> >info.api_resp_info.param.init_rsp.client_id;
> > +
> > +free_done:
> > +   /* Free up the response message */
> > +   lga_msg_destroy(o_msg);
> > +
> > +done:
> > +   TRACE_LEAVE2("rc = %d", rc);
> > +   return rc;
> > +}
> > +
> > +/**
> > + * Send an open message to the server. A number of retries is done
> > if
> > + * return code is TRY AGAIN
> > + * The server returns client id and a stream id
> > + *
> > + * @param lstream_id[out] Log stream id received from server
> > + * @param p_stream[in]    Pointer to a stream record
> > + * @return -1 on error (stream id not valid)
> > + */
> > +static int send_stream_open_msg(uint32_t *lstream_id,
> > +   lga_log_stream_hdl_rec_t *p_stream)
> > +{
> > +   SaAisErrorT ais_rc = SA_AIS_OK;
> > +   uint32_t ncs_rc = NCSCC_RC_SUCCESS;
> > +   int rc = 0;
> > +   lgsv_msg_t i_msg, *o_msg;
> > +   lgsv_stream_open_req_t *open_param;
> > +   lga_client_hdl_rec_t *p_client = p_stream->parent_hdl;
> > +   uint32_t try_again_cnt = 10;
> > +   const uint32_t sleep_delay_ms = 100;
> > +
> > +   TRACE_ENTER();
> > +   TRACE("\t log_stream_name \"%s\", lgs_client_id=%d",
> > +           p_stream->log_stream_name.value, p_client-
> >lgs_client_id);
> > +
> > +   /* Populate a stream open message to the LGS
> > +    */
> > +   memset(&i_msg, 0, sizeof(lgsv_msg_t));
> > +   open_param = &i_msg.info.api_info.param.lstr_open_sync;
> > +
> > +   /* Set the open parameters to open a stream for recovery */
> > +   open_param->client_id = p_client->lgs_client_id;
> > +   open_param->lstr_name = p_stream->log_stream_name;
> > +   open_param->logFileFmt = NULL;
> > +   open_param->logFileFmtLength = 0;
> > +   open_param->maxLogFileSize = 0;
> > +   open_param->maxLogRecordSize = 0;
> > +   open_param->haProperty = SA_FALSE;
> > +   open_param->logFileFullAction = 0;
> > +   open_param->maxFilesRotated = 0;
> > +   open_param->lstr_open_flags = 0;
> > +
> > +   i_msg.type = LGSV_LGA_API_MSG;
> > +   i_msg.info.api_info.type = LGSV_STREAM_OPEN_REQ;
> > +
> > +   /* Send a message to LGS to obtain a stream_id
> > +    */
> > +   while(try_again_cnt > 0) {
> > +           ncs_rc = lga_mds_msg_sync_send(&lga_cb,
> &i_msg, &o_msg,
> > +                   LGS_WAIT_TIME,
> MDS_SEND_PRIORITY_HIGH);
> > +           if (ncs_rc != NCSCC_RC_SUCCESS) {
> > +                   rc = -1;
> > +                   TRACE("%s
> lga_mds_msg_sync_send() Fail %d", __FUNCTION__,
> > ncs_rc);
> > +                   goto done;
> > +           }
> > +
> > +           ais_rc = o_msg->info.api_resp_info.rc;
> > +           if (ais_rc == SA_AIS_ERR_TRY_AGAIN) {
> > +                   usleep(sleep_delay_ms * 1000);
> > +           } else {
> > +                   break;
> > +           }
> > +           try_again_cnt--;
> > +   }
> > +   if (SA_AIS_OK != ais_rc) {
> > +           TRACE("%s LGS error response %s",
> __FUNCTION__,
> > saf_error(ais_rc));
> > +           rc = -1;
> > +           goto free_done;
> > +   }
> > +
> > +   /* Open succeeded */
> > +   *lstream_id =
> > o_msg->info.api_resp_info.param.lstr_open_rsp.lstr_id;
> > +
> > +free_done:
> > +   /* Free up the response message */
> > +   lga_msg_destroy(o_msg);
> > +
> > +done:
> > +   TRACE_LEAVE2("rc = %d", rc);
> > +   return rc;
> > +}
> > +
> >
> +/*********************************************************
> *********************
> > + * Recovery functions
> > +
> >
> **********************************************************
> ********************/
> > +
> > +/**
> > + * Register an existing client with the server
> > + *  - Send an initialize request to the server
> > + *  - A new client id is received replacing the old no longer valid
> > one
> > + *
> > + * This function shall only be used in recovery. It is assumed that
> > + * lga_serv_downstate_set() has been called
> > + *
> > + * @param p_client[in] Pointer to a client record
> > + * @return -1 on error
> > + *          0 client is successfully initialized
> > + *          1 client was already initialized
> > + */
> > +static int initialize_one_client(lga_client_hdl_rec_t *p_client)
> > +{
> > +   int rc = 0;
> > +   uint32_t client_id;
> > +
> > +   TRACE_ENTER();
> > +
> > +   if (p_client->initialized_flag == true) {
> > +           /* The client is already initialized */
> > +           rc = 1;
> > +           goto done;
> > +   }
> > +
> > +   rc = send_initialize_msg(&client_id);
> > +   if (rc == -1) {
> > +           TRACE("%s initialize_msg_send Fail",
> __FUNCTION__);
> > +   }
> > +
> > +   /* Restore the client Id with the one returned by the LGS and
> > +    * set the initialized flag
> > +    */
> > +   osaf_mutex_lock_ordie(&lga_cb.cb_lock);
> > +   p_client->lgs_client_id = client_id;
> > +   p_client->initialized_flag = true;
> > +   osaf_mutex_unlock_ordie(&lga_cb.cb_lock);
> > +
> > +done:
> > +   TRACE_LEAVE2("rc = %d", rc);
> > +   return rc;
> > +}
> > +
> > +/**
> > + * Register a stream that was opened by the client with the server
> > + *  - Send a stream open request to the server (no parameter list)
> > + *  - A new stream id is received replacing the old no longer valid
> > one
> > + *
> > + * @param p_stream[in] Pointer to a stream record
> > + * @return -1 on error
> > + *          0 The stream was successfully recovered
> > + *          1 The stream was already recovered
> > + */
> > +static int recover_one_stream(lga_log_stream_hdl_rec_t *p_stream)
> > +{
> > +   int rc = 0;
> > +   uint32_t stream_id;
> > +
> > +   TRACE_ENTER();
> > +
> > +   if (p_stream->recovered_flag == true) {
> > +           /* The stream is already recovered */
> > +           rc = 1;
> > +           goto done;
> > +   }
> > +
> > +   rc = send_stream_open_msg(&stream_id, p_stream);
> > +   if (rc == -1) {
> > +           TRACE("%s open_stream_msg_send Fail",
> __FUNCTION__);
> > +           goto done;
> > +   }
> > +
> > +   /* Restore the stream Id with the Id returned by the LGS and
> > +    * set the recovered flag
> > +    */
> > +   osaf_mutex_lock_ordie(&lga_cb.cb_lock);
> > +   p_stream->lgs_log_stream_id = stream_id;
> > +   p_stream->recovered_flag = true;
> > +   osaf_mutex_unlock_ordie(&lga_cb.cb_lock);
> > +
> > +done:
> > +   TRACE_LEAVE2("rc = %d", rc);
> > +   return rc;
> > +}
> > +
> >
> +/*********************************************************
> *********************
> > + * Recovery 2 thread handling functions
> > +
> >
> **********************************************************
> ********************/
> > +
> > +/**
> > + * Thread for handling recovery step 2
> > + * Wait for timeout or stop request
> > + * After timeout, recover all not already recovered clients
> > + *
> > + * @param int timeout_time_in Timeout time in s
> > + * @return NULL
> > + */
> > +static void *recovery2_thread(void *dummy)
> > +{
> > +   int rc = 0;
> > +   struct timespec seed_ts;
> > +   int timeout_ms;
> > +
> > +   TRACE_ENTER();
> > +
> > +   /* Create a random timeout time in msec within an interval
> > +    */
> > +   /* Set seed. Use nanoseconds from clock */
> > +   osaf_clock_gettime(CLOCK_MONOTONIC, &seed_ts);
> > +   srandom((unsigned int) seed_ts.tv_nsec);
> > +   /* Interval 400 - 500 sec */
> > +   timeout_ms = (int) (random() % 100 + 400) * 1000;
> > +
> > +   /* Wait for timeout or a signal to terminate
> > +    */
> > +   rc = osaf_poll_one_fd(state2_terminate_sel_obj.rmv_obj,
> > timeout_ms);
> > +   if (rc == -1) {
> > +           TRACE("%s osaf_poll_one_fd Fail %s",
> __FUNCTION__,
> > strerror(errno));
> > +           goto done;
> > +   }
> > +
> > +   if (rc == 0) {
> > +           /* Timeout; Set recovery state 2 */
> > +           osaf_mutex_lock_ordie(&lga_cb.cb_lock);
> > +           lga_cb.lga_state = LGA_RECOVERY2;
> > +           osaf_mutex_unlock_ordie(&lga_cb.cb_lock);
> > +           TRACE("%s Poll timeout. Enter LGA_RECOVERY2
> state", __FUNCTION__);
> > +   } else {
> > +           /* Stop signal received */
> > +           TRACE("%s Stop signal received",
> __FUNCTION__);
> > +           goto done;
> > +   }
> > +
> > +   /* Execute recovery 2
> > +    * Recover one client at the time
> > +    * If fail to recover remove the client. This means that the
> client
> > +    * handle is invalidated
> > +    * When all clients are recovered or if exit is requested exit the
> > +    * thread
> > +    */
> > +   TRACE("%s Execute recovery 2", __FUNCTION__);
> > +   /* First client */
> > +   lga_client_hdl_rec_t *p_client;
> > +   p_client = lga_cb.client_list;
> > +
> > +   while (p_client != NULL) {
> > +           /* Exit if requested to */
> > +           rc =
> osaf_poll_one_fd(state2_terminate_sel_obj.rmv_obj, 0);
> > +           if (rc > 0) {
> > +                   /* We have been signaled to exit
> */
> > +                   goto done;
> > +           }
> > +           /* Recover clients one at a time */
> > +           rc = recover_one_client(p_client);
> > +           TRACE("\t Client %d is recovered", p_client-
> >lgs_client_id);
> > +           if (rc == -1) {
> > +                   TRACE("%s recover_one_client
> Fail Deleting cllient (id %d)",
> > +                           __FUNCTION__,
> p_client->lgs_client_id);
> > +                   /* Fail to recover this client
> > +                    * Remove (handle invalidated)
> > +                    */
> > +
>       osaf_mutex_lock_ordie(&lga_cb.cb_lock);
> > +                   (void)
> delete_one_client(&lga_cb.client_list, p_client);
> > +
>       osaf_mutex_unlock_ordie(&lga_cb.cb_lock);
> > +           }
> > +
> > +           /* Next client */
> > +           p_client = p_client->next;
> > +   }
> > +
> > +   /* All clients are recovered (or removed).
> > +    * Or recovery is aborted
> > +    * Change to not recovering state
> > +    * LGA_NORMAL
> > +    */
> > +   osaf_mutex_lock_ordie(&lga_cb.cb_lock);
> > +   lga_cb.lga_state = LGA_NORMAL;
> > +   TRACE("\t Setting lga_state = LGA_NORMAL");
> > +   osaf_mutex_unlock_ordie(&lga_cb.cb_lock);
> > +
> > +done:
> > +   /* Cleanup and Exit thread */
> > +   (void) ncs_sel_obj_destroy(&state2_terminate_sel_obj);
> > +
> > +   TRACE_LEAVE();
> > +   return NULL;
> > +}
> > +
> > +/**
> > + * Setup and start the thread for recovery state 2
> > + *
> > + * @return -1 on error
> > + */
> > +static int start_recovery2_thread(void)
> > +{
> > +   int rc = 0;
> > +   uint32_t ncs_rc = NCSCC_RC_SUCCESS;
> > +   pthread_attr_t attr;
> > +
> > +   TRACE_ENTER();
> > +
> > +   pthread_attr_init(&attr);
> > +   pthread_attr_setdetachstate(&attr,
> PTHREAD_CREATE_DETACHED);
> > +
> > +   /* Create a selection object for signaling the recovery2 thread
> */
> > +   ncs_rc = ncs_sel_obj_create(&state2_terminate_sel_obj);
> > +   if (ncs_rc != NCSCC_RC_SUCCESS) {
> > +           TRACE("%s ncs_sel_obj_create Fail",
> __FUNCTION__);
> > +           rc = -1;
> > +           goto done;
> > +   }
> > +
> > +   /* Create the thread
> > +    */
> > +   if (pthread_create(&recovery2_thread_id, &attr,
> recovery2_thread,
> > NULL)       != 0) {
> > +           /* pthread_create() error handling */
> > +           TRACE("\t pthread_create FAILED: %s",
> strerror(errno));
> > +           rc = -1;
> > +           (void)
> ncs_sel_obj_destroy(&state2_terminate_sel_obj);
> > +           goto done;
> > +   }
> > +   pthread_attr_destroy(&attr);
> > +
> > +done:
> > +   TRACE_LEAVE2("rc = %d", rc);
> > +   return rc;
> > +}
> > +
> > +/**
> > + * Stops the recovery 2 thread
> > + * It is safe to call this function also if the thread is not
> > running
> > + */
> > +static void stop_recovery2_thread(void)
> > +{
> > +   uint32_t ncs_rc = 0;
> > +
> > +   TRACE_ENTER();
> > +
> > +   /* Check if the thread is running */
> > +   osaf_mutex_lock_ordie(&lga_cb.cb_lock);
> > +   lga_state_t lga_state = lga_cb.lga_state;
> > +   osaf_mutex_unlock_ordie(&lga_cb.cb_lock);
> > +
> > +   if (lga_state == LGA_NORMAL) {
> > +           /* No thread to stop */
> > +           TRACE("%s LGA_NORMAL no thread to stop",
> __FUNCTION__);
> > +           goto done;
> > +   }
> > +
> > +   /* Signal the thread to stop */
> > +   ncs_rc = ncs_sel_obj_ind(&state2_terminate_sel_obj);
> > +   if (ncs_rc != NCSCC_RC_SUCCESS) {
> > +           TRACE("%s ncs_sel_obj_ind Fail",
> __FUNCTION__);
> > +   }
> > +
> > +   done:
> > +   TRACE_LEAVE();
> > +   return;
> > +}
> > +
> >
> +/*********************************************************
> *********************
> > + * Recovery state handling functions
> > +
> >
> **********************************************************
> ********************/
> > +
> >
> +/*********************************************************
> *********************
> > + * Server Down
> > + *
> > + * Initiate recovery handling and set LGA_NO_SERVER state
> > + * LGA_NO_SERVER: State set in MDS event handler when server down
> > event
> > + *                lga_no_server_state_set()
> > +
> >
> **********************************************************
> ********************/
> > +
> > +/**
> > + * Recovery state LGA_NO_SERVER
> > + *
> > + * Setup server down state
> > + * - Mark all clients and their streams as not recovered
> > + * - Remove recovery thread if exist
> > + * - Set LGA_NO_SERVER state
> > + *
> > + */
> > +void lga_no_server_state_set(void)
> > +{
> > +   lga_client_hdl_rec_t *p_client = lga_cb.client_list;
> > +   lga_log_stream_hdl_rec_t *p_stream;
> > +
> > +   TRACE_ENTER();
> > +
> > +   /* Stop recovery thread for state 2 if exist */
> > +   stop_recovery2_thread();
> > +
> > +   /* Set LGA_NO_SERVER state */
> > +   osaf_mutex_lock_ordie(&lga_cb.cb_lock);
> > +   lga_cb.lga_state = LGA_NO_SERVER;
> > +   TRACE("\t lga_state = LGA_NO_SERVER");
> > +   osaf_mutex_unlock_ordie(&lga_cb.cb_lock);
> > +
> > +   while (p_client != NULL) {
> > +           /* Set Client flags for all clients */
> > +           p_client->initialized_flag = false;
> > +           p_client->recovered_flag = false;
> > +
> > +           /* Set stream flags for all streams in every client
> */
> > +           p_stream = p_client->stream_list;
> > +           while (p_stream != NULL) {
> > +                   p_stream->recovered_flag =
> false;
> > +
> > +                   p_stream = p_stream->next;
> > +           }
> > +
> > +           p_client = p_client->next;
> > +   }
> > +
> > +   TRACE_LEAVE();
> > +}
> > +
> >
> +/*********************************************************
> *********************
> > + * Recovery state 1
> > + *
> > + * Recover when needed. This means that when a client requests a
> > service
> > + * the client and all its open streams is recovered in server.
> > + * Handler functions for this can be found in this section.
> > + * LGA_RECOVERY1: State set in MDS event handler when server up
> > event
> > + *                lga_serv_recov1state_set(). Starting recovery
> > thread
> > + *
> > + * LGA_RECOVERY2: State set in recovery thread after timeout
> > + *                lga_serv_recov2state_set()
> > + *
> > + * LGA_NORMAL:    State set when all clients are recovered. This is
> > done in
> > + *                recovery thread when done. After setting this state
> > the
> > + *                thread will exit
> > +
> >
> **********************************************************
> ********************/
> > +
> > +/**
> > + * If previous state was LGA_NO_SERVER (headless)
> > + * Start the recovery2_thread. This will start timeout timer for
> > recovery 2
> > + * state.
> > + * Set state to LGA_RECOVERY1
> > + */
> > +void lga_serv_recov1state_set(void)
> > +{
> > +   TRACE_ENTER();
> > +
> > +   osaf_mutex_lock_ordie(&lga_cb.cb_lock);
> > +   if (lga_cb.lga_state != LGA_NO_SERVER) {
> > +           /* We have not been headless. No recovery
> shall be done */
> > +           TRACE("%s Previous state was not
> LGA_NO_SERVER lga_stat = %d",
> > +                   __FUNCTION__,
> lga_cb.lga_state);
> > +           osaf_mutex_unlock_ordie(&lga_cb.cb_lock);
> > +           goto done;
> > +   } else {
> > +           lga_cb.lga_state = LGA_RECOVERY1;
> > +           TRACE("lga_state = %d (2->RECOVERY1)",
> > +                   lga_cb.lga_state);
> > +           osaf_mutex_unlock_ordie(&lga_cb.cb_lock);
> > +   }
> > +
> > +   start_recovery2_thread();
> > +
> > +done:
> > +   TRACE_LEAVE();
> > +   return;
> > +}
> > +
> > +/**
> > + * Recover the client and all streams in its stream list
> > + *  - Send an initialize request to the server
> > + *  - Send a stream open request with no parameters to the server
> > + *    for each stream.
> > + *  - If success mark the stream and client as recovered
> > + *  - If fail to initiate the client or recover one of its streams
> > the
> > + *    client shall be finalized. A finalize request is sent to the
> > server.
> > + *    If error return code from server it is ignored. This may happen
> > e.g. if
> > + *    the client was never initialized.
> > + *
> > + * The reason for finalizing the whole client if only one stream
> > cannot be
> > + * recovered is that the client will get BAD_HANDLE when requesting a
> > service
> > + * for that stream. This may cause the client to initialize a new
> > client and
> > + * the old client will remain as a resource leek.
> > + *
> > + * @param p_client[in] Pointer to a client record
> > + * @return -1 on error
> > + */
> > +int recover_one_client(lga_client_hdl_rec_t *p_client)
> > +{
> > +   int rc = 0;
> > +   lga_log_stream_hdl_rec_t *p_stream;
> > +
> > +   TRACE_ENTER();
> > +
> > +   /* This function may be called both in the recovery thread and
> in
> > the
> > +    * client thread. A possible scenario is that the recovery 2
> thread
> > +    * times out and calls this function in recovery mode 2 while
> there
> > +    * a client recovery is still ongoing started in mode 1. The
> > recovery 2
> > +    * thread must wait until ongoing recovery is done
> > +    */
> > +   osaf_mutex_lock_ordie(&lga_recov_mutex);
> > +   /* We may have been waiting at mutex while the client was
> recovered
> > +    * so it may already been recovered.
> > +    */
> > +   if (p_client->recovered_flag == true) {
> > +           /* Client is already recovered */
> > +           TRACE("\t Already recovered");
> > +           goto done;
> > +   }
> > +
> > +   rc = initialize_one_client(p_client);
> > +   if (rc == -1) {
> > +           TRACE("%s initialize_one_client() Fail client Id
> %d",
> > +                   __FUNCTION__, p_client-
> >lgs_client_id);
> > +           goto done;
> > +   }
> > +
> > +   /* Recover all streams registered with this client */
> > +   p_stream = p_client->stream_list;
> > +   while (p_stream != NULL) {
> > +           TRACE("\t Recover client=%d, stream=%d",
> > +                   p_client->lgs_client_id, p_stream-
> >lgs_log_stream_id);
> > +           rc = recover_one_stream(p_stream);
> > +           if (rc == -1) {
> > +                   TRACE("%s
> recover_one_stream() Fail "
> > +                   "client Id %d stream Id %d",
> __FUNCTION__,
> > +                           p_client-
> >lgs_client_id,
> > +                           p_stream-
> >lgs_log_stream_id);
> > +                   goto done;
> > +           }
> > +
> > +           p_stream = p_stream->next;
> > +   }
> > +
> > +   osaf_mutex_lock_ordie(&lga_cb.cb_lock);
> > +   p_client->recovered_flag = true;
> > +   osaf_mutex_unlock_ordie(&lga_cb.cb_lock);
> > +
> > +done:
> > +   osaf_mutex_unlock_ordie(&lga_recov_mutex);
> > +
> > +   TRACE_LEAVE();
> > +   return rc;
> > +}
> > +
> > +/**
> > + * Delete one client
> > + * Wrapper for function lga_hdl_rec_del() is used (lga_utol.c)
> > + * This wrapper adds a control to make sure that the function cannot
> > + * be used by the recovery 2 thread and the client thread at the same
> > time
> > + *
> > + * @param list_head
> > + * @param rm_node
> > + */
> > +uint32_t delete_one_client(
> > +   lga_client_hdl_rec_t **list_head,
> > +   lga_client_hdl_rec_t *rm_node
> > +   )
> > +{
> > +   TRACE_ENTER2();
> > +   uint32_t ncs_rc;
> > +
> > +   osaf_mutex_lock_ordie(&lga_recov_mutex);
> > +   ncs_rc = lga_hdl_rec_del(list_head, rm_node);
> > +   osaf_mutex_unlock_ordie(&lga_recov_mutex);
> > +
> > +   TRACE_LEAVE();
> > +   return ncs_rc;
> > +}
> > diff --git a/osaf/libs/agents/saf/lga/lga_state.h
> > b/osaf/libs/agents/saf/lga/lga_state.h
> > new file mode 100644
> > --- /dev/null
> > +++ b/osaf/libs/agents/saf/lga/lga_state.h
> > @@ -0,0 +1,41 @@
> > +/*      -*- 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 LGA_STATE_H
> > +#define    LGA_STATE_H
> > +
> > +#ifdef     __cplusplus
> > +extern "C" {
> > +#endif
> > +
> > +#include "lga.h"
> > +
> > +/* Recovery functions */
> > +void lga_no_server_state_set(void);
> > +void lga_serv_recov1state_set(void);
> > +int recover_one_client(lga_client_hdl_rec_t *p_client);
> > +uint32_t delete_one_client(
> > +   lga_client_hdl_rec_t **list_head,
> > +   lga_client_hdl_rec_t *rm_node
> > +   );
> > +
> > +#ifdef     __cplusplus
> > +}
> > +#endif
> > +
> > +#endif     /* LGA_STATE_H */
> > +
> > diff --git a/osaf/libs/agents/saf/lga/lga_util.c
> > b/osaf/libs/agents/saf/lga/lga_util.c
> > --- a/osaf/libs/agents/saf/lga/lga_util.c
> > +++ b/osaf/libs/agents/saf/lga/lga_util.c
> > @@ -44,7 +44,11 @@ static unsigned int lga_create(void)
> >     }
> >
> >     /* Block and wait for indication from MDS meaning LGS is up */
> > -
>       osaf_poll_one_fd(m_GET_FD_FROM_SEL_OBJ(lga_cb.lgs_syn
> c_sel),
> > 30000);
> > +
> > +   /* #1179 Change timeout from 30 sec (30000) to 10 sec (10000)
> > +    * 30 sec is probably too long for a synchronous API function
> > +    */
> > +
>       osaf_poll_one_fd(m_GET_FD_FROM_SEL_OBJ(lga_cb.lgs_syn
> c_sel),
> > 10000);
> >
> >     pthread_mutex_lock(&lga_cb.cb_lock);
> >     lga_cb.lgs_sync_awaited = 0;
> > @@ -118,12 +122,16 @@ static bool lga_clear_mbx(NCSCONTEXT arg
> >  static void lga_log_stream_hdl_rec_list_del(lga_log_stream_hdl_rec_t
> > **plstr_hdl)
> >  {
> >     lga_log_stream_hdl_rec_t *lstr_hdl;
> > +   TRACE_ENTER();
> >     while ((lstr_hdl = *plstr_hdl) != NULL) {
> >             *plstr_hdl = lstr_hdl->next;
> > +           TRACE("%s stream \"%s\", hdl =
> %d",__FUNCTION__,
> > +                   lstr_hdl-
> >log_stream_name.value, lstr_hdl->log_stream_hdl);
> >             ncshm_destroy_hdl(NCS_SERVICE_ID_LGA,
> lstr_hdl->log_stream_hdl);
> >             free(lstr_hdl);
> >             lstr_hdl = NULL;
> >     }
> > +   TRACE_LEAVE();
> >  }
> >
> >
> >
> /**********************************************************
> ******************
> > @@ -264,11 +272,13 @@ static uint32_t lga_hdl_cbk_dispatch_blo
> >  }
> >
> >  /**
> > - *
> > + * Initiate the agent when first used.
> > + * Start NCS service
> > + * Register with MDS
> >   *
> >   * @return unsigned int
> >   */
> > -unsigned int lga_startup(void)
> > +unsigned int lga_startup(lga_cb_t *cb)
> >  {
> >     unsigned int rc = NCSCC_RC_SUCCESS;
> >     pthread_mutex_lock(&lga_lock);
> > @@ -287,8 +297,14 @@ unsigned int lga_startup(void)
> >             if ((rc = lga_create()) != NCSCC_RC_SUCCESS) {
> >                     ncs_agents_shutdown();
> >                     goto done;
> > -           } else
> > +           } else {
> >                     lga_use_count = 1;
> > +           }
> > +
> > +           /* Agent has successfully been started including
> communication
> > +            * with server
> > +            */
> > +           cb->lga_state = LGA_NORMAL;
> >     }
> >
> >   done:
> > @@ -299,11 +315,18 @@ unsigned int lga_startup(void)
> >  }
> >
> >  /**
> > + * If called when only one (the last) client for this agent the
> > client list a
> > + * complete 'shut down' of the agent is done.
> > + *  - Erase the clients list. Frees all memory including list of
> > open
> > + *    streams.
> > + *  - Unregister with MDS
> > + *  - Shut down ncs agents
> >   *
> > + * Global lga_use_count Conatins number of registered clients
> >   *
> > - * @return unsigned int
> > + * @return unsigned int (always NCSCC_RC_SUCCESS)
> >   */
> > -unsigned int lga_shutdown(void)
> > +unsigned int lga_shutdown_after_last_client(void)
> >  {
> >     unsigned int rc = NCSCC_RC_SUCCESS;
> >
> > @@ -325,6 +348,37 @@ unsigned int lga_shutdown(void)
> >     return rc;
> >  }
> >
> > +/**
> > + * Makes a forced shut down of the agent if there are registered
> > clients
> > + * Makes all handles invalid and frees all resources (memory, mds)
> > + *
> > + * clients and the log server is down and no other recovery is
> > possible.
> > + *  - Erase the clients list. Frees all memory including list of
> > open
> > + *    streams.
> > + *  - Unregister with MDS
> > + *  - Shut down ncs agents
> > + *  - Set
> > + *
> > + * Global lga_use_count [in/out] = 0
> > + *
> > + * @return always NCSCC_RC_SUCCESS
> > + */
> > +unsigned int lga_force_shutdown(void)
> > +{
> > +   unsigned int rc = NCSCC_RC_SUCCESS;
> > +   TRACE_ENTER();
> > +   pthread_mutex_lock(&lga_lock);
> > +   if (lga_use_count > 0) {
> > +           lga_destroy();
> > +           rc = ncs_agents_shutdown(); /* Always returns
> NCSCC_RC_SUCCESS */
> > +           lga_use_count = 0;
> > +           TRACE("%s: Forced shutdown. Handles
> invalidated\n",__FUNCTION__);
> > +   }
> > +   pthread_mutex_unlock(&lga_lock);
> > +   TRACE_LEAVE();
> > +   return rc;
> > +}
> > +
> >
> >
> /**********************************************************
> ******************
> >   * Name          : lga_msg_destroy
> >   *
> > @@ -387,6 +441,8 @@ void lga_hdl_list_del(lga_client_hdl_rec
> >  {
> >     lga_client_hdl_rec_t *client_hdl;
> >
> > +   TRACE_ENTER();
> > +
> >     while ((client_hdl = *p_client_hdl) != NULL) {
> >             *p_client_hdl = client_hdl->next;
> >             ncshm_destroy_hdl(NCS_SERVICE_ID_LGA,
> client_hdl->local_hdl);
> > @@ -398,6 +454,7 @@ void lga_hdl_list_del(lga_client_hdl_rec
> >             free(client_hdl);
> >             client_hdl = 0;
> >     }
> > +   TRACE_LEAVE();
> >  }
> >
> >
> >
> /**********************************************************
> ******************
> > @@ -416,6 +473,7 @@ void lga_hdl_list_del(lga_client_hdl_rec
> >
> >
> **********************************************************
> ********************/
> >  uint32_t lga_log_stream_hdl_rec_del(lga_log_stream_hdl_rec_t
> > **list_head, lga_log_stream_hdl_rec_t *rm_node)
> >  {
> > +   TRACE_ENTER();
> >     /* Find the channel hdl record in the list of records */
> >     lga_log_stream_hdl_rec_t *list_iter = *list_head;
> >
> > @@ -427,6 +485,7 @@ uint32_t lga_log_stream_hdl_rec_del(lga_
> >             ncshm_give_hdl(rm_node->log_stream_hdl);
> >             ncshm_destroy_hdl(NCS_SERVICE_ID_LGA,
> rm_node->log_stream_hdl);
> >             free(rm_node);
> > +           TRACE_LEAVE();
> >             return NCSCC_RC_SUCCESS;
> >     } else {                /* find the rec */
> >
> > @@ -438,6 +497,7 @@ uint32_t lga_log_stream_hdl_rec_del(lga_
> >
>       ncshm_give_hdl(rm_node->log_stream_hdl);
> >
>       ncshm_destroy_hdl(NCS_SERVICE_ID_LGA, rm_node-
> >log_stream_hdl);
> >                             free(rm_node);
> > +                           TRACE_LEAVE();
> >                             return
> NCSCC_RC_SUCCESS;
> >                     }
> >                     /* move onto the next one */
> > @@ -493,7 +553,6 @@ uint32_t lga_hdl_rec_del(lga_client_hdl_
> >             rc = NCSCC_RC_SUCCESS;
> >             goto out;
> >     } else {                /* find the rec */
> > -
> >             while (NULL != list_iter) {
> >                     if (list_iter->next == rm_node) {
> >                             list_iter->next =
> rm_node->next;
> > @@ -517,10 +576,9 @@ uint32_t lga_hdl_rec_del(lga_client_hdl_
> >                     list_iter = list_iter->next;
> >             }
> >     }
> > -   TRACE("failed");
> >
> >   out:
> > -   TRACE_LEAVE();
> > +   TRACE_LEAVE2("rc = %d (2 <=> fail)", rc);
> >     return rc;
> >  }
> >
> > @@ -566,6 +624,15 @@ lga_log_stream_hdl_rec_t *lga_log_stream
> >     rec->log_stream_name.length = logStreamName->length;
> >     memcpy((void *)rec->log_stream_name.value, (void
> > *)logStreamName->value, logStreamName->length);
> >     rec->log_header_type = log_header_type;
> > +
> > +   /***
> > +    * Initiate the recovery flag
> > +    * The setting means that the stream is initialized and that
> there
> > is
> > +    * no reason to recover. This setting will change if server down
> is
> > +    * detected
> > +    */
> > +   rec->recovered_flag = true;
> > +
> >      /** Initialize the parent handle **/
> >     rec->parent_hdl = *hdl_rec;
> >
> > @@ -616,6 +683,15 @@ lga_client_hdl_rec_t *lga_hdl_rec_add(lg
> >       **/
> >     rec->lgs_client_id = client_id;
> >
> > +   /***
> > +    * Initiate the recovery flags
> > +    * The setting means that the client is initialized and that there
> > is
> > +    * no reason to recover. This setting will change if server down
> is
> > +    * detected
> > +    */
> > +   rec->initialized_flag = true;
> > +   rec->recovered_flag = true;
> > +
> >      /** Initialize and attach the IPC/Priority queue
> >       **/
> >     if (m_NCS_IPC_CREATE(&rec->mbx) != NCSCC_RC_SUCCESS) {
------------------------------------------------------------------------------
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