Hi Lennart,
I see you make `oiCreationThread_` as a joinable thread, it means
`joinable()` always returns true until the thread has been joined (when
switch-over).
So, if LOGsv gets SA_AIS_BAD_HANDLE returned by IMM APIs second time, the
recovery job will not be activated due to below condition.
if ((oiCreationThread_.joinable() == true) || (stop_oi_create == true)) {
// Thread is executing. Do nothing
return;
}
That is not what we expect, I think.
Regards, Vu
> -----Original Message-----
> From: Lennart Lund [mailto:[email protected]]
> Sent: Wednesday, March 28, 2018 9:34 PM
> To: [email protected]; [email protected]
> Cc: [email protected]; Lennart Lund
> <[email protected]>
> Subject: [PATCH 1/1] log: Handling of IMM OI BAD HANDLE in log server is
> incorrect [#2799]
>
> Recovery of OI handle shall be started in all places where BAD HANDLE
> can be returned. Creation of OI must be done in background thread.
> Ongoing creation must be possible to stop e.g if server is becoming
> standby
> ---
> src/log/Makefile.am | 3 +
> src/log/logd/lgs.h | 24 ---
> src/log/logd/lgs_amf.cc | 26 ++-
> src/log/logd/lgs_cb.h | 3 -
> src/log/logd/lgs_config.cc | 22 ++-
> src/log/logd/lgs_config.h | 5 +-
> src/log/logd/lgs_evt.cc | 60 +++---
> src/log/logd/lgs_imm.cc | 312 +++--------------------------
> src/log/logd/lgs_imm.h | 53 +++++
> src/log/logd/lgs_main.cc | 116 ++++-------
> src/log/logd/lgs_mbcsv_v2.cc | 7 +-
> src/log/logd/lgs_mbcsv_v3.cc | 7 +-
> src/log/logd/lgs_mbcsv_v5.cc | 3 +-
> src/log/logd/lgs_oi_admin.cc | 461
> +++++++++++++++++++++++++++++++++++++++++++
> src/log/logd/lgs_oi_admin.h | 105 ++++++++++
> src/log/logd/lgs_recov.cc | 4 +-
> src/log/logd/lgs_stream.cc | 85 ++++++--
> 17 files changed, 837 insertions(+), 459 deletions(-)
> create mode 100644 src/log/logd/lgs_imm.h
> create mode 100644 src/log/logd/lgs_oi_admin.cc
> create mode 100644 src/log/logd/lgs_oi_admin.h
>
> diff --git a/src/log/Makefile.am b/src/log/Makefile.am
> index 3d951eb5d..5d33d355b 100644
> --- a/src/log/Makefile.am
> +++ b/src/log/Makefile.am
> @@ -79,6 +79,7 @@ noinst_HEADERS += \
> src/log/logd/lgs_file.h \
> src/log/logd/lgs_filehdl.h \
> src/log/logd/lgs_fmt.h \
> + src/log/logd/lgs_imm.h \
> src/log/logd/lgs_imm_gcfg.h \
> src/log/logd/lgs_mbcsv.h \
> src/log/logd/lgs_mbcsv_v1.h \
> @@ -86,6 +87,7 @@ noinst_HEADERS += \
> src/log/logd/lgs_mbcsv_v3.h \
> src/log/logd/lgs_mbcsv_v5.h \
> src/log/logd/lgs_mbcsv_v6.h \
> + src/log/logd/lgs_oi_admin.h \
> src/log/logd/lgs_recov.h \
> src/log/logd/lgs_stream.h \
> src/log/logd/lgs_util.h \
> @@ -139,6 +141,7 @@ bin_osaflogd_SOURCES = \
> src/log/logd/lgs_mbcsv_v5.cc \
> src/log/logd/lgs_mbcsv_v6.cc \
> src/log/logd/lgs_mds.cc \
> + src/log/logd/lgs_oi_admin.cc \
> src/log/logd/lgs_recov.cc \
> src/log/logd/lgs_stream.cc \
> src/log/logd/lgs_util.cc \
> diff --git a/src/log/logd/lgs.h b/src/log/logd/lgs.h
> index 18e6d9281..b1d773375 100644
> --- a/src/log/logd/lgs.h
> +++ b/src/log/logd/lgs.h
> @@ -95,7 +95,6 @@ extern uint32_t mbox_msgs[NCS_IPC_PRIORITY_MAX];
> extern bool mbox_full[NCS_IPC_PRIORITY_MAX];
> extern uint32_t mbox_low[NCS_IPC_PRIORITY_MAX];
> extern pthread_mutex_t lgs_mbox_init_mutex;
> -extern pthread_mutex_t lgs_OI_init_mutex;
>
> extern uint32_t initialize_for_assignment(lgs_cb_t *cb, SaAmfHAStateT
> ha_state);
>
> @@ -108,27 +107,4 @@ extern uint32_t lgs_mds_msg_send(lgs_cb_t *cb,
> lgsv_msg_t *msg, MDS_DEST *dest,
> MDS_SYNC_SND_CTXT *mds_ctxt,
> MDS_SEND_PRIORITY_TYPE prio);
>
> -extern SaAisErrorT lgs_imm_create_configStream(lgs_cb_t *cb);
> -extern void logRootDirectory_filemove(const std::string
> &new_logRootDirectory,
> - const std::string
&old_logRootDirectory,
> - time_t *cur_time_in);
> -extern void logDataGroupname_fileown(const char
> *new_logDataGroupname);
> -
> -extern void lgs_imm_impl_reinit_nonblocking(lgs_cb_t *cb);
> -extern void lgs_imm_init_OI_handle(SaImmOiHandleT *immOiHandle,
> - SaSelectionObjectT
*immSelectionObject);
> -extern void lgs_imm_impl_set(SaImmOiHandleT *immOiHandle,
> - SaSelectionObjectT *immSelectionObject);
> -extern SaAisErrorT lgs_imm_init_configStreams(lgs_cb_t *cb);
> -
> -// Functions for recovery handling
> -void lgs_cleanup_abandoned_streams();
> -void lgs_delete_one_stream_object(const std::string &name_str);
> -void lgs_search_stream_objects();
> -SaUint32T *lgs_get_scAbsenceAllowed_attr(SaUint32T *attr_val);
> -int lgs_get_streamobj_attr(SaImmAttrValuesT_2 ***attrib_out,
> - const std::string &object_name,
> - SaImmHandleT *immOmHandle);
> -int lgs_free_streamobj_attr(SaImmHandleT immHandle);
> -
> #endif // LOG_LOGD_LGS_H_
> diff --git a/src/log/logd/lgs_amf.cc b/src/log/logd/lgs_amf.cc
> index 6fa044ff2..3f0de8c1c 100644
> --- a/src/log/logd/lgs_amf.cc
> +++ b/src/log/logd/lgs_amf.cc
> @@ -23,6 +23,7 @@
> #include "osaf/immutil/immutil.h"
> #include "log/logd/lgs.h"
> #include "log/logd/lgs_config.h"
> +#include "log/logd/lgs_oi_admin.h"
>
> static void close_all_files() {
> log_stream_t *stream;
> @@ -63,8 +64,7 @@ static SaAisErrorT amf_active_state_handler(lgs_cb_t
> *cb,
> goto done;
> }
>
> - lgs_imm_impl_set(&cb->immOiHandle, &cb->immSelectionObject);
> - conf_runtime_obj_create(cb->immOiHandle);
> + lgsOiStart();
> lgs_start_gcfg_applier();
>
> // Iterate all existing log streams in cluster.
> @@ -127,12 +127,8 @@ static SaAisErrorT
> amf_quiescing_state_handler(lgs_cb_t *cb,
> TRACE_ENTER2("HA QUIESCING request");
> close_all_files();
>
> - /* Give up our IMM OI implementer role */
> - SaAisErrorT ais_rc = immutil_saImmOiImplementerClear(cb-
> >immOiHandle);
> - if (ais_rc != SA_AIS_OK) {
> - LOG_WA("immutil_saImmOiImplementerClear failed: %s",
> saf_error(ais_rc));
> - }
> -
> + // Give up our IMM OI implementer role and the OpensafConfig class
> applier
> + lgsOiStop();
> lgs_stop_gcfg_applier();
>
> return saAmfCSIQuiescingComplete(cb->amf_hdl, invocation, SA_AIS_OK);
> @@ -158,11 +154,7 @@ static SaAisErrorT
> amf_quiesced_state_handler(lgs_cb_t *cb,
> close_all_files();
>
> /* Give up our IMM OI implementer role */
> - SaAisErrorT rc = immutil_saImmOiImplementerClear(cb->immOiHandle);
> - if (rc != SA_AIS_OK) {
> - LOG_WA("immutil_saImmOiImplementerClear failed: %s", saf_error(rc));
> - }
> -
> + lgsOiStop();
> lgs_stop_gcfg_applier();
>
> /*
> @@ -171,11 +163,13 @@ static SaAisErrorT
> amf_quiesced_state_handler(lgs_cb_t *cb,
> ** cb->ha_state now.
> */
>
> +
> mds_role = cb->mds_role;
> cb->mds_role = V_DEST_RL_QUIESCED;
> + SaAisErrorT ais_rc = SA_AIS_OK;
> if (lgs_mds_change_role(cb) != NCSCC_RC_SUCCESS) {
> LOG_ER("lgs_mds_change_role FAILED");
> - rc = SA_AIS_ERR_FAILED_OPERATION;
> + ais_rc = SA_AIS_ERR_FAILED_OPERATION;
> cb->mds_role = mds_role;
> goto done;
> }
> @@ -183,8 +177,9 @@ static SaAisErrorT
> amf_quiesced_state_handler(lgs_cb_t *cb,
> cb->amf_invocation_id = invocation;
> cb->is_quiesced_set = true;
> done:
> - return rc;
> + return ais_rc;
> }
> +
>
> /**************************************************************
> **************
> * Name : amf_health_chk_callback
> *
> @@ -207,6 +202,7 @@ static void amf_health_chk_callback(SaInvocationT
> invocation,
> SaAmfHealthcheckKeyT *checkType) {
> saAmfResponse(lgs_cb->amf_hdl, invocation, SA_AIS_OK);
> }
> +
>
> /**************************************************************
> **************
> * Name : amf_csi_set_callback
> *
> diff --git a/src/log/logd/lgs_cb.h b/src/log/logd/lgs_cb.h
> index f2602c2d8..1b1a67d9c 100644
> --- a/src/log/logd/lgs_cb.h
> +++ b/src/log/logd/lgs_cb.h
> @@ -81,9 +81,6 @@ typedef struct lgs_cb {
> SaInvocationT
> amf_invocation_id; /* AMF InvocationID - needed to handle Quiesed
> state */
> bool is_quiesced_set;
> - SaImmOiHandleT immOiHandle; /* IMM OI handle
*/
> - SaSelectionObjectT
> - immSelectionObject; /* Selection Object to wait for IMM events */
> SaSelectionObjectT
> clmSelectionObject; /* Selection Object to wait for clms events */
> SaClmHandleT clm_hdl; /* CLM handle, obtained through CLM init
*/
> diff --git a/src/log/logd/lgs_config.cc b/src/log/logd/lgs_config.cc
> index 4190e3048..7be92a6fa 100644
> --- a/src/log/logd/lgs_config.cc
> +++ b/src/log/logd/lgs_config.cc
> @@ -41,6 +41,7 @@
> #include "log/logd/lgs_file.h"
> #include "log/logd/lgs.h"
> #include "log/logd/lgs_common.h"
> +#include "log/logd/lgs_oi_admin.h"
>
>
> /* Mutex for making read and write of configuration data thread safe */
> @@ -1338,8 +1339,8 @@ static void read_log_config_environ_var_2() {
> * Public functions for handling configuration information
>
> **************************************************************
> ****************/
>
> -void lgs_cfg_init(SaImmOiHandleT immOiHandle, SaAmfHAStateT ha_state) {
> - TRACE_ENTER2("immOiHandle = %lld", immOiHandle);
> +void lgs_cfg_init() {
> + TRACE_ENTER();
>
> /* Read configuration step 1
> * Read all values from the log service configuration object
> @@ -1585,6 +1586,10 @@ void conf_runtime_obj_create(SaImmOiHandleT
> immOiHandle) {
>
> if (rc == SA_AIS_ERR_EXIST) {
> TRACE("Server runtime configuration object already exist");
> + } else if (rc == SA_AIS_ERR_BAD_HANDLE) {
> + LOG_NO("%s: saImmOiRtObjectCreate_2 BAD_HANDLE, start re-create",
> + __FUNCTION__);
> + lgsOiCreateBackground();
> } else if (rc != SA_AIS_OK) {
> LOG_NO("%s: Cannot create config runtime object %s", __FUNCTION__,
> saf_error(rc));
> @@ -1667,6 +1672,14 @@ static SaAisErrorT update_runtime_attrValues(
> attrMod.modAttr.attrValueType = attrValueType;
> attrMod.modAttr.attrValues = values_array;
> ais_rc = immutil_saImmOiRtObjectUpdate_2(immOiHandle, &objectName,
> attrMods);
> + if (ais_rc == SA_AIS_ERR_BAD_HANDLE) {
> + LOG_NO("%s: saImmOiRtObjectUpdate_2() Fail, %s", __FUNCTION__,
> + saf_error(ais_rc));
> + lgsOiCreateBackground();
> + } else if (ais_rc != SA_AIS_OK) {
> + LOG_NO("%s: saImmOiRtObjectUpdate_2() Fail, %s", __FUNCTION__,
> + saf_error(ais_rc));
> + }
> free(values_array);
> TRACE_LEAVE();
> return ais_rc;
> @@ -1692,8 +1705,7 @@ static SaAisErrorT
> update_lgs_cfg_runtime_multivalue(
> immOiHandle, LGS_CFG_RUNTIME_OBJECT, attributeName, valueType,
> attrValuesNumber, attrValues);
> if (ais_rc != SA_AIS_OK) {
> - LOG_NO("%s: update_runtime_attrValues Fail %s", __FUNCTION__,
> - saf_error(ais_rc));
> + LOG_NO("%s: update_runtime_attrValues Fail", __FUNCTION__);
> }
>
> // Free the memory allocated by vector_of_strings_to_attrValues()
> @@ -1712,7 +1724,7 @@ static SaAisErrorT
> update_lgs_cfg_runtime_multivalue(
> * @param immOiHandle[in]
> * @param attributeNames[in]
> */
> -void conf_runtime_obj_hdl(SaImmOiHandleT immOiHandle,
> +void conf_runtime_obj_handler(SaImmOiHandleT immOiHandle,
> const SaImmAttrNameT *attributeNames) {
> SaImmAttrNameT attributeName;
> int i = 0;
> diff --git a/src/log/logd/lgs_config.h b/src/log/logd/lgs_config.h
> index 6885271a4..3f1b05e51 100644
> --- a/src/log/logd/lgs_config.h
> +++ b/src/log/logd/lgs_config.h
> @@ -135,7 +135,7 @@ typedef struct config_chkpt {
> * Read the log service configuration data verify and update
configuration
> * data structure
> */
> -void lgs_cfg_init(SaImmOiHandleT immOiHandle, SaAmfHAStateT ha_state);
> +void lgs_cfg_init();
>
> /**
> * Get value of log service configuration parameter from the
configuration
> data
> @@ -316,8 +316,9 @@ void lgs_groupnameconf_set(const char
> *data_groupname_str);
> * Handle runtime object for showing actual configuration and
configuration
> * related information
> */
> +
> void conf_runtime_obj_create(SaImmOiHandleT immOiHandle);
> -void conf_runtime_obj_hdl(SaImmOiHandleT immOiHandle,
> +void conf_runtime_obj_handler(SaImmOiHandleT immOiHandle,
> const SaImmAttrNameT *attributeNames);
>
> /*
> diff --git a/src/log/logd/lgs_evt.cc b/src/log/logd/lgs_evt.cc
> index 4b735875d..d0c3161a4 100644
> --- a/src/log/logd/lgs_evt.cc
> +++ b/src/log/logd/lgs_evt.cc
> @@ -31,6 +31,7 @@
> #include "log/logd/lgs_imm_gcfg.h"
> #include "log/logd/lgs_clm.h"
> #include "log/logd/lgs_dest.h"
> +#include "log/logd/lgs_oi_admin.h"
>
> void *client_db = nullptr; /* used for C++ STL map */
>
> @@ -569,7 +570,7 @@ static uint32_t proc_rda_cb_msg(lgsv_lgs_evt_t
> *evt) {
> }
>
> /* fail over, become implementer */
> - lgs_imm_impl_set(&lgs_cb->immOiHandle, &lgs_cb-
> >immSelectionObject);
> + lgsOiCreateBackground();
> lgs_start_gcfg_applier();
>
> /* Agent down list has to be processed first */
> @@ -613,7 +614,6 @@ uint32_t lgs_cb_init(lgs_cb_t *lgs_cb) {
>
> lgs_cb->fully_initialized = false;
> lgs_cb->amfSelectionObject = -1;
> - lgs_cb->immSelectionObject = -1;
> lgs_cb->mbcsv_sel_obj = -1;
> lgs_cb->clm_hdl = 0;
> lgs_cb->clmSelectionObject = -1;
> @@ -835,7 +835,7 @@ snd_rsp:
> */
> SaAisErrorT create_new_app_stream(lgsv_stream_open_req_t
> *open_sync_param,
> log_stream_t **o_stream) {
> - SaAisErrorT rc = SA_AIS_OK;
> + SaAisErrorT ais_rc = SA_AIS_OK;
> log_stream_t *stream;
> SaBoolT twelveHourModeFlag;
> SaUint32T logMaxLogrecsize_conf = 0;
> @@ -848,13 +848,13 @@ SaAisErrorT
> create_new_app_stream(lgsv_stream_open_req_t *open_sync_param,
>
> if (lgs_is_extended_name_valid(&open_sync_param->lstr_name) == false) {
> TRACE("SaNameT is invalid");
> - rc = SA_AIS_ERR_INVALID_PARAM;
> + ais_rc = SA_AIS_ERR_INVALID_PARAM;
> goto done;
> }
>
> if (open_sync_param->logFileFullAction !=
> SA_LOG_FILE_FULL_ACTION_ROTATE) {
> TRACE("Unsupported logFileFullAction");
> - rc = SA_AIS_ERR_NOT_SUPPORTED;
> + ais_rc = SA_AIS_ERR_NOT_SUPPORTED;
> goto done;
> }
>
> @@ -864,7 +864,7 @@ SaAisErrorT
> create_new_app_stream(lgsv_stream_open_req_t *open_sync_param,
> ((open_sync_param->maxFilesRotated < 1) ||
> (open_sync_param->maxFilesRotated > 127))) {
> TRACE("Invalid maxFilesRotated. Valid Range = [1-127]");
> - rc = SA_AIS_ERR_INVALID_PARAM;
> + ais_rc = SA_AIS_ERR_INVALID_PARAM;
> goto done;
> }
>
> @@ -880,21 +880,21 @@ SaAisErrorT
> create_new_app_stream(lgsv_stream_open_req_t *open_sync_param,
> STREAM_TYPE_APPLICATION_RT,
> &twelveHourModeFlag)) {
> TRACE("format expression failure");
> - rc = SA_AIS_ERR_INVALID_PARAM;
> + ais_rc = SA_AIS_ERR_INVALID_PARAM;
> goto done;
> }
>
> /* Verify if there is any special character in logFileName */
> if (lgs_has_special_char(open_sync_param->logFileName) == true) {
> TRACE("Invalid logFileName - %s", open_sync_param->logFileName);
> - rc = SA_AIS_ERR_INVALID_PARAM;
> + ais_rc = SA_AIS_ERR_INVALID_PARAM;
> goto done;
> }
>
> /* Verify if logFileName length is valid */
> if (lgs_is_valid_filelength(open_sync_param->logFileName) == false) {
> TRACE("logFileName is invalid");
> - rc = SA_AIS_ERR_INVALID_PARAM;
> + ais_rc = SA_AIS_ERR_INVALID_PARAM;
> goto done;
> }
>
> @@ -902,7 +902,7 @@ SaAisErrorT
> create_new_app_stream(lgsv_stream_open_req_t *open_sync_param,
> if (lgs_is_valid_pathlength(open_sync_param->logFilePathName,
> open_sync_param->logFileName) == false) {
> TRACE("logFilePathName is invalid");
> - rc = SA_AIS_ERR_INVALID_PARAM;
> + ais_rc = SA_AIS_ERR_INVALID_PARAM;
> goto done;
> }
>
> @@ -913,7 +913,7 @@ SaAisErrorT
> create_new_app_stream(lgsv_stream_open_req_t *open_sync_param,
> if ((stream->fileName == open_sync_param->logFileName) &&
> (stream->pathName == open_sync_param->logFilePathName)) {
> TRACE("pathname already exist");
> - rc = SA_AIS_ERR_INVALID_PARAM;
> + ais_rc = SA_AIS_ERR_INVALID_PARAM;
> goto done;
> }
> }
> @@ -922,7 +922,7 @@ SaAisErrorT
> create_new_app_stream(lgsv_stream_open_req_t *open_sync_param,
> str_name = osaf_extended_name_borrow(&open_sync_param-
> >lstr_name);
> if (strncmp(dnPrefix, str_name, strlen(dnPrefix)) != 0) {
> TRACE("'%s' is not a valid stream name => invalid param", str_name);
> - rc = SA_AIS_ERR_INVALID_PARAM;
> + ais_rc = SA_AIS_ERR_INVALID_PARAM;
> goto done;
> }
>
> @@ -933,13 +933,13 @@ SaAisErrorT
> create_new_app_stream(lgsv_stream_open_req_t *open_sync_param,
> ((open_sync_param->maxLogRecordSize < SA_LOG_MIN_RECORD_SIZE)
> ||
> (open_sync_param->maxLogRecordSize > logMaxLogrecsize_conf))) {
> TRACE("maxLogRecordSize is invalid");
> - rc = SA_AIS_ERR_INVALID_PARAM;
> + ais_rc = SA_AIS_ERR_INVALID_PARAM;
> goto done;
> }
>
> *o_stream = log_stream_new(str_name, STREAM_NEW);
> if (*o_stream == nullptr) {
> - rc = SA_AIS_ERR_NO_MEMORY;
> + ais_rc = SA_AIS_ERR_NO_MEMORY;
> goto done;
> }
>
> @@ -951,16 +951,23 @@ SaAisErrorT
> create_new_app_stream(lgsv_stream_open_req_t *open_sync_param,
> twelveHourModeFlag, 0, *o_stream); // output
> if (err == -1) {
> log_stream_delete(o_stream);
> - rc = SA_AIS_ERR_NO_MEMORY;
> + ais_rc = SA_AIS_ERR_NO_MEMORY;
> goto done;
> }
>
> - rc = lgs_create_appstream_rt_object(*o_stream);
> - if (rc != SA_AIS_OK) log_stream_delete(o_stream);
> + ais_rc = lgs_create_appstream_rt_object(*o_stream);
> + if (ais_rc != SA_AIS_OK) log_stream_delete(o_stream);
> +
> + TRACE("%s: lgs_create_appstream_rt_object return, %s",
> + __FUNCTION__, saf_error(ais_rc));
> +
> + if (ais_rc == SA_AIS_ERR_BAD_HANDLE) {
> + lgsOiCreateBackground();
> + }
>
> done:
> TRACE_LEAVE();
> - return rc;
> + return ais_rc;
> }
>
> /**
> @@ -1069,15 +1076,7 @@ static uint32_t proc_stream_open_msg(lgs_cb_t
> *cb, lgsv_lgs_evt_t *evt) {
> }
> }
> } else {
> - /* Stream does not exist */
> -
> - // This check is to avoid the client getting SA_AIS_BAD_OPERATION
> - // as there is no IMM OI implementer set.
> - if (cb->immOiHandle == 0) {
> - TRACE("IMM service unavailable, open stream failed");
> - ais_rv = SA_AIS_ERR_TRY_AGAIN;
> - goto snd_rsp;
> - }
> + /* Stream does not exist. Create a new stream */
>
> /*
> * Check if the stream is in the list of stream objects
> @@ -1125,6 +1124,11 @@ static uint32_t proc_stream_open_msg(lgs_cb_t
> *cb, lgsv_lgs_evt_t *evt) {
> if (ais_rv != SA_AIS_OK) {
> TRACE("%s create_new_app_stream Fail \"%s\"", __FUNCTION__,
> saf_error(ais_rv));
> + if (ais_rv == SA_AIS_ERR_BAD_HANDLE) {
> + // This means that the stream RT object could not be created
because
> + // of a bad OI handle. Change to TRY AGAIN in the reply to the
agent
> + ais_rv = SA_AIS_ERR_TRY_AGAIN;
> + }
> goto snd_rsp;
> }
> }
> @@ -1218,7 +1222,7 @@ static uint32_t proc_stream_close_msg(lgs_cb_t
> *cb, lgsv_lgs_evt_t *evt) {
> // This check is to avoid the client getting SA_AIS_BAD_OPERATION
> // as there is no IMM OI implementer set.
> if ((stream->streamType == STREAM_TYPE_APPLICATION_RT) &&
> - (cb->immOiHandle == 0)) {
> + (lgsGetOiHandle() == 0)) {
> TRACE("IMM service unavailable, close stream failed");
> ais_rc = SA_AIS_ERR_TRY_AGAIN;
> goto snd_rsp;
> diff --git a/src/log/logd/lgs_imm.cc b/src/log/logd/lgs_imm.cc
> index 60870fa17..d23862172 100644
> --- a/src/log/logd/lgs_imm.cc
> +++ b/src/log/logd/lgs_imm.cc
> @@ -31,6 +31,8 @@
> #define _GNU_SOURCE
> #endif
>
> +#include "log/logd/lgs_imm.h"
> +
> #include <stdio.h>
> #include <errno.h>
> #include <string.h>
> @@ -46,6 +48,7 @@
> #include "log/logd/lgs_recov.h"
> #include "log/logd/lgs_config.h"
> #include "log/logd/lgs_dest.h"
> +#include "log/logd/lgs_oi_admin.h"
> #include "base/saf_error.h"
>
> #include "lgs_mbcsv_v1.h"
> @@ -58,11 +61,6 @@
> * ----------------
> */
>
> -/* Used for protecting global imm OI handle and selection object during
> - * initialize of OI
> - */
> -pthread_mutex_t lgs_OI_init_mutex = PTHREAD_MUTEX_INITIALIZER;
> -
> /* Used for checkpointing time when files are closed */
> static time_t chkp_file_close_time = 0;
>
> @@ -75,13 +73,6 @@ static const char *log_file_format[] = {
> DEFAULT_ALM_NOT_FORMAT_EXP, DEFAULT_ALM_NOT_FORMAT_EXP,
> DEFAULT_APP_SYS_FORMAT_EXP, DEFAULT_APP_SYS_FORMAT_EXP};
>
> -static const SaImmOiImplementerNameT implementerName =
> - const_cast<SaImmOiImplementerNameT>("safLogService");
> -static const SaImmClassNameT logConfig_str =
> - const_cast<SaImmClassNameT>("OpenSafLogConfig");
> -static const SaImmClassNameT streamConfig_str =
> - const_cast<SaImmClassNameT>("SaLogStreamConfig");
> -
> // The list contains path-file names when validating its name in CCB
> completed
> // callback. This help for log service prevents that creating any streams
> // in same CCB with duplicated log path-file name
> @@ -2375,7 +2366,7 @@ static SaAisErrorT stream_create_and_configure1(
>
> /* Update creation timestamp */
> rc = immutil_update_one_rattr(
> - lgs_cb->immOiHandle, objectName.c_str(),
> + lgsGetOiHandle(), objectName.c_str(),
> const_cast<SaImmAttrNameT>("saLogStreamCreationTimestamp"),
> SA_IMM_ATTR_SATIMET, &(*stream)->creationTimeStamp);
> if (rc != SA_AIS_OK) {
> @@ -2702,7 +2693,7 @@ static SaAisErrorT
> rtAttrUpdateCallback(SaImmOiHandleT immOiHandle,
> /* Handle configuration runtime object */
> if (strncmp(objName, LGS_CFG_RUNTIME_OBJECT, strlen(objName)) == 0) {
> /* Handle Runtome configuration object */
> - conf_runtime_obj_hdl(immOiHandle, attributeNames);
> + conf_runtime_obj_handler(immOiHandle, attributeNames);
> } else {
> /* Handle stream object if valid
> */
> @@ -2889,11 +2880,15 @@ static const SaImmOiCallbacksT_2 callbacks = {
> .saImmOiCcbObjectModifyCallback = ccbObjectModifyCallback,
> .saImmOiRtAttrUpdateCallback = rtAttrUpdateCallback};
>
> +// Export the callback structure. OI init is done in lgs_oi_admin
> +const SaImmOiCallbacksT_2* getImmOiCallbacks(void) {
> + return &callbacks;
> +}
> +
> /**
> * Retrieve the LOG stream configuration from IMM using the
> * IMM-OM interface and initialize the corresponding information
> - * in the LOG control block. Initialize the LOG IMM-OI
> - * interface. Become class implementer.
> + * in the LOG control block.
> *
> * @param cb[in] control block
> * @return
> @@ -2987,20 +2982,6 @@ SaAisErrorT lgs_imm_init_configStreams(lgs_cb_t
> *cb) {
> }
> }
>
> - /* 1.Become implementer
> - * 2.Update creation timestamp for all configure object, must be object
> - * implementer first 3.Open all streams Config file and log file will
be
> - * created. If this fails we give up without returning any error. A new
> - * attempt to create the files will be done when trying to write a log
> - * record to the stream.
> - */
> - ais_rc =
> - immutil_saImmOiClassImplementerSet(cb->immOiHandle,
> "SaLogStreamConfig");
> - if (ais_rc != SA_AIS_OK) {
> - LOG_ER("immutil_saImmOiClassImplementerSet failed %s",
> saf_error(ais_rc));
> - osaf_abort(0);
> - }
> -
> // Iterate all existing log streams in cluster.
> while ((stream = iterate_all_streams(endloop, jstart)) && !endloop) {
> jstart = SA_FALSE;
> @@ -3021,7 +3002,7 @@ SaAisErrorT lgs_imm_init_configStreams(lgs_cb_t
> *cb) {
> }
>
> ais_rc = immutil_update_one_rattr(
> - cb->immOiHandle, stream->name.c_str(),
> + lgsGetOiHandle(), stream->name.c_str(),
> const_cast<SaImmAttrNameT>("saLogStreamCreationTimestamp"),
> SA_IMM_ATTR_SATIMET, &stream->creationTimeStamp);
> if (ais_rc != SA_AIS_OK) {
> @@ -3046,255 +3027,6 @@ done:
> return ais_rc;
> }
>
> -/**
> - * Initialize the OI interface and get a selection object.
> - * Become OI for safLogService if Active
> - *
> - * @param immOiHandle[out]
> - * @param immSelectionObject[out]
> - */
> -void lgs_imm_init_OI_handle(SaImmOiHandleT *immOiHandle,
> - SaSelectionObjectT *immSelectionObject) {
> - SaAisErrorT rc;
> - uint32_t msecs_waited = 0;
> -
> - TRACE_ENTER();
> -
> - /* Initialize IMM OI service */
> - SaVersionT imm_version = kImmVersion;
> - rc = saImmOiInitialize_2(immOiHandle, &callbacks, &imm_version);
> - while ((rc == SA_AIS_ERR_TRY_AGAIN) &&
> - (msecs_waited < max_waiting_time_60s)) {
> - usleep(sleep_delay_ms * 1000);
> - msecs_waited += sleep_delay_ms;
> - imm_version = kImmVersion;
> - rc = saImmOiInitialize_2(immOiHandle, &callbacks, &imm_version);
> - }
> - if (rc != SA_AIS_OK) {
> - lgs_exit("saImmOiInitialize_2 failed", SA_AMF_COMPONENT_RESTART);
> - }
> -
> - /* Get selection object for event handling */
> - msecs_waited = 0;
> - rc = saImmOiSelectionObjectGet(*immOiHandle, immSelectionObject);
> - while ((rc == SA_AIS_ERR_TRY_AGAIN) &&
> - (msecs_waited < max_waiting_time_10s)) {
> - usleep(sleep_delay_ms * 1000);
> - msecs_waited += sleep_delay_ms;
> - rc = saImmOiSelectionObjectGet(*immOiHandle, immSelectionObject);
> - }
> - if (rc != SA_AIS_OK) {
> - lgs_exit("saImmOiSelectionObjectGet failed",
> SA_AMF_COMPONENT_RESTART);
> - }
> -
> - TRACE_LEAVE2("rc: %s", saf_error(rc));
> -}
> -
> -/**
> - * Does the sequence of setting an implementer name and class implementer
> - *
> - * @param immOiHandle[in]
> - * @return SaAisErrorT
> - */
> -static SaAisErrorT imm_impl_set_sequence(
> - SaImmOiHandleT *immOiHandle, SaSelectionObjectT
> *immSelectionObject) {
> - SaAisErrorT rc = SA_AIS_OK;
> - uint32_t msecs_waited = 0;
> -
> - TRACE_ENTER();
> -
> - for (;;) {
> - if (msecs_waited >= max_waiting_time_60s) {
> - TRACE("Timeout in imm_impl_set_sequence");
> - goto done;
> - }
> -
> - /* Become object implementer
> - */
> - rc = saImmOiImplementerSet(*immOiHandle, implementerName);
> - while (((rc == SA_AIS_ERR_TRY_AGAIN) || (rc == SA_AIS_ERR_EXIST)) &&
> - (msecs_waited < max_waiting_time_60s)) {
> - usleep(sleep_delay_ms * 1000);
> - msecs_waited += sleep_delay_ms;
> - rc = saImmOiImplementerSet(*immOiHandle, implementerName);
> - }
> - if (rc == SA_AIS_ERR_BAD_HANDLE || rc == SA_AIS_ERR_TIMEOUT) {
> - LOG_WA("saImmOiImplementerSet returned %s", saf_error(rc));
> - usleep(sleep_delay_ms * 1000);
> - msecs_waited += sleep_delay_ms;
> - saImmOiFinalize(*immOiHandle);
> - *immOiHandle = 0;
> - *immSelectionObject = -1;
> - lgs_imm_init_OI_handle(immOiHandle, immSelectionObject);
> - continue;
> - }
> - if (rc != SA_AIS_OK) {
> - TRACE("saImmOiImplementerSet failed %s", saf_error(rc));
> - goto done;
> - }
> -
> - /*
> - * Become class implementer for the OpenSafLogConfig class if it
exists
> - * Become class implementer for the SaLogStreamConfig class
> - */
> - if (true == *static_cast<const bool *>(
> -
> lgs_cfg_get(LGS_IMM_LOG_OPENSAFLOGCONFIG_CLASS_EXIST))) {
> - rc = saImmOiClassImplementerSet(*immOiHandle, logConfig_str);
> - while (((rc == SA_AIS_ERR_TRY_AGAIN) || (rc == SA_AIS_ERR_EXIST))
&&
> - (msecs_waited < max_waiting_time_60s)) {
> - usleep(sleep_delay_ms * 1000);
> - msecs_waited += sleep_delay_ms;
> - rc = saImmOiClassImplementerSet(*immOiHandle, logConfig_str);
> - }
> - if (rc == SA_AIS_ERR_BAD_HANDLE || rc == SA_AIS_ERR_TIMEOUT) {
> - LOG_WA("saImmOiClassImplementerSet returned %s", saf_error(rc));
> - usleep(sleep_delay_ms * 1000);
> - msecs_waited += sleep_delay_ms;
> - saImmOiFinalize(*immOiHandle);
> - *immOiHandle = 0;
> - *immSelectionObject = -1;
> - lgs_imm_init_OI_handle(immOiHandle, immSelectionObject);
> - continue;
> - }
> - if (rc != SA_AIS_OK) {
> - TRACE("saImmOiClassImplementerSet OpenSafLogConfig failed %s",
> - saf_error(rc));
> - goto done;
> - }
> - }
> -
> - rc = saImmOiClassImplementerSet(*immOiHandle, streamConfig_str);
> - while (((rc == SA_AIS_ERR_TRY_AGAIN) || (rc == SA_AIS_ERR_EXIST)) &&
> - (msecs_waited < max_waiting_time_60s)) {
> - usleep(sleep_delay_ms * 1000);
> - msecs_waited += sleep_delay_ms;
> - rc = saImmOiClassImplementerSet(*immOiHandle, streamConfig_str);
> - }
> - if (rc == SA_AIS_ERR_BAD_HANDLE || rc == SA_AIS_ERR_TIMEOUT) {
> - LOG_WA("saImmOiClassImplementerSet returned %s", saf_error(rc));
> - usleep(sleep_delay_ms * 1000);
> - msecs_waited += sleep_delay_ms;
> - saImmOiFinalize(*immOiHandle);
> - *immOiHandle = 0;
> - *immSelectionObject = -1;
> - lgs_imm_init_OI_handle(immOiHandle, immSelectionObject);
> - continue;
> - }
> - if (rc != SA_AIS_OK) {
> - TRACE("saImmOiClassImplementerSet SaLogStreamConfig failed %s",
> - saf_error(rc));
> - goto done;
> - }
> - break;
> - }
> -
> -done:
> - TRACE_LEAVE2("rc: %s", saf_error(rc));
> - return rc;
> -}
> -
> -/**
> - * Set implementer name and become class implementer.
> - * This function will block until done.
> - *
> - * @param cb
> - */
> -void lgs_imm_impl_set(SaImmOiHandleT *immOiHandle,
> - SaSelectionObjectT *immSelectionObject) {
> - SaAisErrorT rc = SA_AIS_OK;
> -
> - TRACE_ENTER();
> -
> - rc = imm_impl_set_sequence(immOiHandle, immSelectionObject);
> - if (rc != SA_AIS_OK) {
> - lgs_exit("Becoming OI implementer failed",
> SA_AMF_COMPONENT_RESTART);
> - }
> -
> - TRACE_LEAVE();
> -}
> -
> -/**
> - * Thread
> - * Restore object and class implementer/applier.
> - *
> - * @param _cb[in]
> - */
> -static void *imm_impl_init_thread(void *_cb) {
> - lgs_cb_t *cb = static_cast<lgs_cb_t *>(_cb);
> - SaSelectionObjectT immSelectionObject = 0;
> - SaImmOiHandleT immOiHandle = 0;
> - SaAisErrorT rc = SA_AIS_OK;
> -
> - TRACE_ENTER();
> -
> - /* Initialize handles and become implementer */
> - lgs_imm_init_OI_handle(&immOiHandle, &immSelectionObject);
> - rc = imm_impl_set_sequence(&immOiHandle, &immSelectionObject);
> - if (rc != SA_AIS_OK) {
> - lgs_exit("Becoming OI implementer failed",
> SA_AMF_COMPONENT_RESTART);
> - }
> -
> - /* Store handle and selection object.
> - * Protect if the poll loop in main is released during the storage
> - * sequence.
> - */
> - osaf_mutex_lock_ordie(&lgs_OI_init_mutex);
> - cb->immSelectionObject = immSelectionObject;
> - cb->immOiHandle = immOiHandle;
> - osaf_mutex_unlock_ordie(&lgs_OI_init_mutex);
> -
> - /* Activate the poll loop in main()
> - * This will reinstall IMM poll event handling
> - */
> - lgsv_lgs_evt_t *lgsv_evt;
> - lgsv_evt = static_cast<lgsv_lgs_evt_t *>(calloc(1,
sizeof(lgsv_lgs_evt_t)));
> - osafassert(lgsv_evt);
> - lgsv_evt->evt_type = LGSV_EVT_NO_OP;
> - if (m_NCS_IPC_SEND(&lgs_mbx, lgsv_evt, LGS_IPC_PRIO_CTRL_MSGS) !=
> - NCSCC_RC_SUCCESS) {
> - LOG_WA("imm_reinit_thread failed to send IPC message to main
thread");
> - /*
> - * Se no reason why this would happen. But if it does at least there
> - * is something in the syslog. The main thread should still pick up
> - * the new imm FD when there is a healthcheck, but it could take
> - *minutes.
> - */
> - free(lgsv_evt);
> - }
> -
> - TRACE_LEAVE();
> - return NULL;
> -}
> -
> -/**
> - * In a separate thread:
> - * Initiate IMM OI handle and selection object
> - * Create imm implementer for log IMM objects
> - * When complete:
> - * Store the new handle and selection object in the cb store.
> - * Activate the poll loop in main() by sending an empty mailbox message
> - *
> - * @param cb[out]
> - */
> -void lgs_imm_impl_reinit_nonblocking(lgs_cb_t *cb) {
> - pthread_t thread;
> - pthread_attr_t attr;
> -
> - TRACE_ENTER();
> -
> - pthread_attr_init(&attr);
> - pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
> -
> - if (pthread_create(&thread, &attr, imm_impl_init_thread, cb) != 0) {
> - LOG_ER("pthread_create FAILED: %s", strerror(errno));
> - exit(EXIT_FAILURE);
> - }
> -
> - pthread_attr_destroy(&attr);
> -
> - TRACE_LEAVE();
> -}
> -
>
> /**************************************************************
> ****************
> * Functions used for recovery handling
>
> **************************************************************
> ****************/
> @@ -3403,12 +3135,16 @@ void lgs_delete_one_stream_object(const
> std::string &name_str) {
> osaf_extended_name_lend(name_str.c_str(), &object_name);
>
> /* and delete the object */
> - ais_rc = immutil_saImmOiRtObjectDelete(lgs_cb->immOiHandle,
> &object_name);
> + ais_rc = immutil_saImmOiRtObjectDelete(lgsGetOiHandle(),
> &object_name);
> if (ais_rc == SA_AIS_OK) {
> TRACE("%s Object \"%s\" deleted", __FUNCTION__, name_str.c_str());
> + } else if (ais_rc == SA_AIS_ERR_BAD_HANDLE) {
> + LOG_NO("%s: saImmOiRtObjectDelete() Fail, %s", __FUNCTION__,
> + saf_error(ais_rc));
> + lgsOiCreateBackground();
> } else {
> - LOG_WA("%s saImmOiRtObjectDelete for \"%s\" FAILED %d",
> __FUNCTION__,
> - name_str.c_str(), ais_rc);
> + LOG_WA("%s saImmOiRtObjectDelete for \"%s\" FAILED %s",
> __FUNCTION__,
> + name_str.c_str(), saf_error(ais_rc));
> }
> }
>
> @@ -3444,12 +3180,16 @@ void lgs_cleanup_abandoned_streams() {
> /* Copy name to a SaNameT */
> osaf_extended_name_lend(name_str, &object_name);
> /* and delete the object */
> - ais_rc = immutil_saImmOiRtObjectDelete(lgs_cb->immOiHandle,
> &object_name);
> + ais_rc = immutil_saImmOiRtObjectDelete(lgsGetOiHandle(),
> &object_name);
> if (ais_rc == SA_AIS_OK) {
> TRACE("\tObject \"%s\" deleted", name_str);
> + } else if (ais_rc == SA_AIS_ERR_BAD_HANDLE) {
> + LOG_WA("%s saImmOiRtObjectDelete for \"%s\" FAILED %s",
> __FUNCTION__,
> + name_str, saf_error(ais_rc));
> + lgsOiCreateBackground();
> } else {
> - LOG_WA("%s saImmOiRtObjectDelete for \"%s\" FAILED %d",
> __FUNCTION__,
> - name_str, ais_rc);
> + LOG_WA("%s saImmOiRtObjectDelete for \"%s\" FAILED %s",
> __FUNCTION__,
> + name_str, saf_error(ais_rc));
> }
> } else {
> /* Should never happen! */
> diff --git a/src/log/logd/lgs_imm.h b/src/log/logd/lgs_imm.h
> new file mode 100644
> index 000000000..195d09380
> --- /dev/null
> +++ b/src/log/logd/lgs_imm.h
> @@ -0,0 +1,53 @@
> +/* -*- OpenSAF -*-
> + *
> + * (C) Copyright 2008 The OpenSAF Foundation
> + * Copyright Ericsson AB 2008, 2018 - All Rights Reserved.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are
> licensed
> + * under the GNU Lesser General Public License Version 2.1, February
1999.
> + * The complete license can be accessed from the following location:
> + * http://opensource.org/licenses/lgpl-license.php
> + * See the Copying file included with the OpenSAF distribution for full
> + * licensing terms.
> + *
> + * Author(s): Ericsson AB
> + *
> + */
> +
> +#ifndef LGS_IMM_H
> +#define LGS_IMM_H
> +
> +#include <time.h>
> +#include <string>
> +
> +#include "ais/include/saImmOi.h"
> +#include "ais/include/saImmOm.h"
> +
> +#include "log/logd/lgs_cb.h"
> +
> +// Get the callback structure used when initializing an OI handle
> +const SaImmOiCallbacksT_2* getImmOiCallbacks(void);
> +
> +void logRootDirectory_filemove(const std::string &new_logRootDirectory,
> + const std::string
&old_logRootDirectory,
> + time_t *cur_time_in);
> +void logDataGroupname_fileown(const char *new_logDataGroupname);
> +
> +SaAisErrorT lgs_imm_init_configStreams(lgs_cb_t *cb);
> +
> +// Functions for recovery handling
> +void lgs_cleanup_abandoned_streams();
> +void lgs_delete_one_stream_object(const std::string &name_str);
> +void lgs_search_stream_objects();
> +SaUint32T *lgs_get_scAbsenceAllowed_attr(SaUint32T *attr_val);
> +int lgs_get_streamobj_attr(SaImmAttrValuesT_2 ***attrib_out,
> + const std::string &object_name,
> + SaImmHandleT *immOmHandle);
> +int lgs_free_streamobj_attr(SaImmHandleT immHandle);
> +
> +
> +
> +#endif /* LGS_IMM_H */
> +
> diff --git a/src/log/logd/lgs_main.cc b/src/log/logd/lgs_main.cc
> index 988ebdd78..9767fe00d 100644
> --- a/src/log/logd/lgs_main.cc
> +++ b/src/log/logd/lgs_main.cc
> @@ -33,16 +33,18 @@
> #include "nid/agent/nid_api.h"
> #include "base/ncs_main_papi.h"
> #include "base/osaf_time.h"
> -
> -#include "log/logd/lgs.h"
> -#include "log/logd/lgs_file.h"
> #include "base/osaf_utility.h"
> #include "base/hash.h"
> -#include "lgs_recov.h"
> #include "osaf/immutil/immutil.h"
> +
> +#include "log/logd/lgs.h"
> +#include "log/logd/lgs_file.h"
> +#include "log/logd/lgs_recov.h"
> #include "lgs_clm.h"
> #include "log/logd/lgs_dest.h"
> #include "log/logd/lgs_amf.h"
> +#include "log/logd/lgs_oi_admin.h"
> +#include "log/logd/lgs_imm.h"
>
>
> /*
> ==============================================================
> ==========
> @@ -383,26 +385,21 @@ uint32_t initialize_for_assignment(lgs_cb_t *cb,
> SaAmfHAStateT ha_state) {
> if (cb->fully_initialized || ha_state == SA_AMF_HA_QUIESCED) goto done;
> cb->ha_state = ha_state;
>
> - /* Initialize IMM OI handle and selection object */
> - lgs_imm_init_OI_handle(&cb->immOiHandle, &cb->immSelectionObject);
> -
> - TRACE("IMM init done: cb->immOiHandle = %lld", cb->immOiHandle);
> -
> /* Initialize log configuration
> * Must be done after IMM OI is initialized
> */
> - lgs_cfg_init(cb->immOiHandle, cb->ha_state);
> + lgs_cfg_init();
> lgs_trace_config(); /* Show all configuration in TRACE */
>
> - /* Show some configurtion info in sysylog */
> - logsv_root_dir =
> - static_cast<const char
> *>(lgs_cfg_get(LGS_IMM_LOG_ROOT_DIRECTORY));
> - logsv_data_groupname =
> - static_cast<const char *>(lgs_cfg_get(LGS_IMM_DATA_GROUPNAME));
> + /* Show some configuration info in sysylog */
> + logsv_root_dir = static_cast<const char *>
> + (lgs_cfg_get(LGS_IMM_LOG_ROOT_DIRECTORY));
> + logsv_data_groupname = static_cast<const char *>
> + (lgs_cfg_get(LGS_IMM_DATA_GROUPNAME));
> LOG_NO("LOG root directory is: \"%s\"", logsv_root_dir);
> LOG_NO("LOG data group is: \"%s\"", logsv_data_groupname);
> - vdest = reinterpret_cast<const std::vector<std::string> *>(
> - lgs_cfg_get(LGS_IMM_LOG_RECORD_DESTINATION_CONFIGURATION));
> + vdest = reinterpret_cast<const std::vector<std::string> *>
> +
> (lgs_cfg_get(LGS_IMM_LOG_RECORD_DESTINATION_CONFIGURATION));
> osafassert(vdest != nullptr);
> if (vdest->size() > 0) {
> CfgDestination(*vdest, ModifyType::kAdd);
> @@ -445,20 +442,15 @@ uint32_t initialize_for_assignment(lgs_cb_t *cb,
> SaAmfHAStateT ha_state) {
> }
>
> if (ha_state == SA_AMF_HA_ACTIVE) {
> - /* Become OI. We will be blocked here until done */
> - lgs_imm_impl_set(&cb->immOiHandle, &cb->immSelectionObject);
> - conf_runtime_obj_create(cb->immOiHandle);
> + // Request an Object Implementer, a configuration object handler and
> + // an applier for opensafNetworkName change surveillance
> + lgsOiCreateSynchronous();
> + conf_runtime_obj_create(lgsGetOiHandle());
> lgs_start_gcfg_applier();
>
> - /* Create streams that has configuration objects and become
> - * class implementer for the SaLogStreamConfig class
> - */
> -
> - /* Note1: cb->immOiHandle is set in lgs_imm_init()
> - * Note2: cb->logsv_root_dir must be set
> - */
> + // Create streams that has configuration objects
> if (lgs_imm_init_configStreams(cb) != SA_AIS_OK) {
> - LOG_ER("lgs_imm_create_configStream FAILED");
> + LOG_ER("lgs_imm_create_configStreams FAILED");
> rc = NCSCC_RC_FAILURE;
> goto done;
> }
> @@ -479,7 +471,7 @@ done:
> */
> int main(int argc, char *argv[]) {
> NCS_SEL_OBJ mbx_fd;
> - SaAisErrorT error = SA_AIS_OK;
> + SaAisErrorT ais_rc = SA_AIS_OK;
> uint32_t rc;
> int term_fd;
>
> @@ -519,7 +511,7 @@ int main(int argc, char *argv[]) {
> fds[FD_AMF].events = POLLIN;
> fds[FD_MBX].fd = mbx_fd.rmv_obj;
> fds[FD_MBX].events = POLLIN;
> - fds[FD_IMM].fd = lgs_cb->immSelectionObject;
> + fds[FD_IMM].fd = lgsGetOiSelectionObject();
> fds[FD_IMM].events = POLLIN;
>
> lgs_cb->clmSelectionObject = lgs_cb->clm_init_sel_obj.rmv_obj;
> @@ -539,18 +531,16 @@ int main(int argc, char *argv[]) {
> fds[FD_CLM].fd = lgs_cb->clmSelectionObject;
> fds[FD_CLM].events = POLLIN;
>
> - /* Protect since the reinit thread may be in the process of
> - * changing the values
> - */
> - osaf_mutex_lock_ordie(&lgs_OI_init_mutex);
> - if (lgs_cb->immOiHandle != 0) {
> - fds[FD_IMM].fd = lgs_cb->immSelectionObject;
> + // Adds or removes the IMM fd depending on if there is an OI or not
> + SaImmOiHandleT oi_handle;
> + SaSelectionObjectT oi_selection_object =
> lgsGetOiFdsParams(&oi_handle);
> + if (oi_handle != 0) {
> + fds[FD_IMM].fd = oi_selection_object;
> fds[FD_IMM].events = POLLIN;
> nfds = FD_IMM + 1;
> } else {
> nfds = FD_IMM;
> }
> - osaf_mutex_unlock_ordie(&lgs_OI_init_mutex);
>
> int ret = poll(fds, nfds, -1);
>
> @@ -567,9 +557,9 @@ int main(int argc, char *argv[]) {
>
> if (fds[FD_AMF].revents & POLLIN) {
> if (lgs_cb->amf_hdl != 0) {
> - if ((error = saAmfDispatch(lgs_cb->amf_hdl, SA_DISPATCH_ALL)) !=
> + if ((ais_rc = saAmfDispatch(lgs_cb->amf_hdl, SA_DISPATCH_ALL)) !=
> SA_AIS_OK) {
> - LOG_ER("saAmfDispatch failed: %u", error);
> + LOG_ER("saAmfDispatch failed: %u", ais_rc);
> break;
> }
> } else {
> @@ -593,9 +583,9 @@ int main(int argc, char *argv[]) {
>
> if (fds[FD_CLM].revents & POLLIN) {
> if (lgs_cb->clm_hdl != 0) {
> - if ((error = saClmDispatch(lgs_cb->clm_hdl, SA_DISPATCH_ALL)) !=
> + if ((ais_rc = saClmDispatch(lgs_cb->clm_hdl, SA_DISPATCH_ALL)) !=
> SA_AIS_OK) {
> - LOG_ER("saClmDispatch failed: %u", error);
> + LOG_ER("saClmDispatch failed: %u", ais_rc);
> break;
> }
> } else {
> @@ -629,40 +619,16 @@ int main(int argc, char *argv[]) {
>
> if (fds[FD_MBX].revents & POLLIN) lgs_process_mbx(&lgs_mbx);
>
> - if (lgs_cb->immOiHandle && fds[FD_IMM].revents & POLLIN) {
> - error = saImmOiDispatch(lgs_cb->immOiHandle, SA_DISPATCH_ALL);
> -
> - /*
> - * BAD_HANDLE is interpreted as an IMM service restart. Try
> - * reinitialize the IMM OI API in a background thread and let
> - * this thread do business as usual especially handling write
> - * requests.
> - *
> - * All other errors are treated as non-recoverable (fatal) and will
> - * cause an exit of the process.
> - */
> - if (error == SA_AIS_ERR_BAD_HANDLE) {
> - TRACE("saImmOiDispatch returned BAD_HANDLE");
> -
> - /*
> - * Invalidate the IMM OI handle, this info is used in other
> - * locations. E.g. giving TRY_AGAIN responses to a create and
> - * close app stream requests. That is needed since the IMM OI
> - * is used in context of these functions.
> - *
> - * Also closing the handle. Finalize is ok with a bad handle
> - * that is bad because it is stale and this actually clears
> - * the handle from internal agent structures. In any case
> - * we ignore the return value from Finalize here.
> - */
> - saImmOiFinalize(lgs_cb->immOiHandle);
> - lgs_cb->immOiHandle = 0;
> - lgs_cb->immSelectionObject = -1;
> -
> - /* Initiate IMM reinitializtion in the background */
> - lgs_imm_impl_reinit_nonblocking(lgs_cb);
> - } else if (error != SA_AIS_OK) {
> - LOG_ER("saImmOiDispatch FAILED: %u", error);
> + if (fds[FD_IMM].revents & POLLIN) {
> + ais_rc = saImmOiDispatch(lgsGetOiHandle(), SA_DISPATCH_ALL);
> +
> + if (ais_rc == SA_AIS_ERR_BAD_HANDLE) {
> + LOG_NO("saImmOiDispatch returned BAD_HANDLE");
> +
> + // Request creation of a new OI
> + lgsOiCreateBackground();
> + } else if (ais_rc != SA_AIS_OK) {
> + LOG_ER("saImmOiDispatch FAILED: %u", ais_rc);
> break;
> }
> }
> diff --git a/src/log/logd/lgs_mbcsv_v2.cc b/src/log/logd/lgs_mbcsv_v2.cc
> index 9afc30155..63807e1b7 100644
> --- a/src/log/logd/lgs_mbcsv_v2.cc
> +++ b/src/log/logd/lgs_mbcsv_v2.cc
> @@ -21,9 +21,10 @@
> * version 2 check-pointing. See also lgs_mbcsv_v2.h
> */
>
> -#include "lgs_config.h"
> -#include "lgs_mbcsv_v2.h"
> -#include "lgs_mbcsv.h"
> +#include "log/logd/lgs_config.h"
> +#include "log/logd/lgs_imm.h"
> +#include "log/logd/lgs_mbcsv_v2.h"
> +#include "log/logd/lgs_mbcsv.h"
>
>
> /**************************************************************
> **************
> * Name : ckpt_proc_lgs_cfg
> diff --git a/src/log/logd/lgs_mbcsv_v3.cc b/src/log/logd/lgs_mbcsv_v3.cc
> index f9836c8af..75fd98dba 100644
> --- a/src/log/logd/lgs_mbcsv_v3.cc
> +++ b/src/log/logd/lgs_mbcsv_v3.cc
> @@ -21,9 +21,10 @@
> * version 3 check-pointing. See also lgs_mbcsv_v3.h
> */
>
> -#include "lgs_mbcsv_v3.h"
> -#include "lgs_mbcsv_v2.h"
> -#include "lgs_mbcsv.h"
> +#include "log/logd/lgs_imm.h"
> +#include "log/logd/lgs_mbcsv_v3.h"
> +#include "log/logd/lgs_mbcsv_v2.h"
> +#include "log/logd/lgs_mbcsv.h"
>
>
> /**************************************************************
> **************
> * Name : ckpt_proc_lgs_cfg
> diff --git a/src/log/logd/lgs_mbcsv_v5.cc b/src/log/logd/lgs_mbcsv_v5.cc
> index 75d627688..d219f8a5b 100644
> --- a/src/log/logd/lgs_mbcsv_v5.cc
> +++ b/src/log/logd/lgs_mbcsv_v5.cc
> @@ -22,8 +22,9 @@
> * V5 applies to log server configuration check-pointing
> */
>
> -#include "lgs_mbcsv_v5.h"
> #include "log/logd/lgs_dest.h"
> +#include "log/logd/lgs_imm.h"
> +#include "log/logd/lgs_mbcsv_v5.h"
>
>
> /**************************************************************
> **************
> * Name : ckpt_proc_lgs_cfg
> diff --git a/src/log/logd/lgs_oi_admin.cc b/src/log/logd/lgs_oi_admin.cc
> new file mode 100644
> index 000000000..abd74c816
> --- /dev/null
> +++ b/src/log/logd/lgs_oi_admin.cc
> @@ -0,0 +1,461 @@
> +/* -*- OpenSAF -*-
> + *
> + * (C) Copyright 2008 The OpenSAF Foundation
> + * Copyright Ericsson AB 2008, 2018 - All Rights Reserved.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are
> licensed
> + * under the GNU Lesser General Public License Version 2.1, February
1999.
> + * The complete license can be accessed from the following location:
> + * http://opensource.org/licenses/lgpl-license.php
> + * See the Copying file included with the OpenSAF distribution for full
> + * licensing terms.
> + *
> + * Author(s): Ericsson AB
> + *
> + */
> +
> +#include "log/logd/lgs_oi_admin.h"
> +
> +#include <atomic>
> +#include <thread>
> +
> +#include "ais/include/saAis.h"
> +#include "ais/include/saImmOi.h"
> +#include "base/logtrace.h"
> +#include "base/mutex.h"
> +#include "base/saf_error.h"
> +#include "base/time.h"
> +
> +#include "log/logd/lgs.h"
> +#include "log/logd/lgs_imm.h"
> +#include "log/logd/lgs_config.h"
> +#include "log/logd/lgs_util.h"
> +
> +// Note: Always use the set and get function with these varibales
> +static base::Mutex lgs_OI_init_mutex;
> +static SaImmOiHandleT oi_handle_ = 0;
> +static SaSelectionObjectT oi_selection_object_ = -1;
> +
> +static const SaImmOiImplementerNameT kImplementerName =
> + const_cast<SaImmOiImplementerNameT>("safLogService");
> +// The log server is OI for the following configuration classes
> +static const SaImmClassNameT kLogConfigurationClass =
> + const_cast<SaImmClassNameT>("OpenSafLogConfig");
> +static const SaImmClassNameT kLogStreamClass =
> + const_cast<SaImmClassNameT>("SaLogStreamConfig");
> +
> +static const uint64_t kOiCreationTimeout = 90000; // 1.5 minutes
> +static const uint64_t kOiHandleRequestTimeout = 60000; // 1 minute
> +static const uint64_t kOiRequestTimeout = 10000; // 10 sec generic
timeout
> +static const timespec kOiTryAgainDelay = base::kOneHundredMilliseconds;
> +
> +// Internal help functions
> +// ---------------------------------
> +
> +static void setProtectedGlobals(SaImmOiHandleT oi_handle,
> + SaSelectionObjectT oi_selction_object) {
> + TRACE_ENTER();
> + base::Lock protect_globals(lgs_OI_init_mutex);
> + oi_handle_ = oi_handle;
> + oi_selection_object_ = oi_selction_object;
> +}
> +
> +static SaAisErrorT finalizeOi(SaImmOiHandleT oi_handle) {
> + TRACE_ENTER();
> + SaAisErrorT ais_rc = SA_AIS_OK;
> + base::Timer try_again_timer(kOiRequestTimeout);
> + while (try_again_timer.is_timeout() == false) {
> + ais_rc = saImmOiFinalize(oi_handle);
> + if (ais_rc == SA_AIS_ERR_TRY_AGAIN) {
> + base::Sleep(kOiTryAgainDelay);
> + continue;
> + }
> + if (ais_rc != SA_AIS_OK) {
> + TRACE("%s: saImmOiFinalize() Fail, %s", __FUNCTION__,
> saf_error(ais_rc));
> + }
> + break;
> + }
> + if ((try_again_timer.is_timeout() == true) &&
> + (ais_rc == SA_AIS_ERR_TRY_AGAIN)) {
> + LOG_NO("%s: saImmOiFinalize() Fail, TRY AGAIN timeout",
> __FUNCTION__);
> + }
> +
> + return ais_rc;
> +}
> +
> +// IMM API help function used in the OI creation thread
> +// Communication flag read in OI thread and set by the lgs_OI_delete()
and
> +// create functions. When this flag is true the thread shall stop and
return
> +// as soon as possible
> +// Note: All of these functions will stop internal loops and return if
> +// the global atomic flag oi_stop == true
> +static std::atomic<bool> stop_oi_create(false);
> +
> +// Output: out_oi_handle. Set to 0 if fail
> +static SaAisErrorT initOiHandle(SaImmOiHandleT *out_oi_handle) {
> + TRACE_ENTER();
> + SaAisErrorT ais_rc = SA_AIS_OK;
> + const SaImmOiCallbacksT_2 *callbacks = getImmOiCallbacks();
> + base::Timer try_again_timer(kOiHandleRequestTimeout);
> + while (try_again_timer.is_timeout() == false) {
> + if (stop_oi_create) {
> + ais_rc = SA_AIS_OK;
> + break;
> + }
> + SaVersionT imm_version = kImmVersion;
> + ais_rc = saImmOiInitialize_2(out_oi_handle, callbacks, &imm_version);
> + if (ais_rc == SA_AIS_ERR_TRY_AGAIN) {
> + base::Sleep(kOiTryAgainDelay);
> + continue;
> + }
> + if (ais_rc != SA_AIS_OK) {
> + LOG_WA("%s: saImmOiInitialize_2() Fail, %s", __FUNCTION__,
> + saf_error(ais_rc));
> + *out_oi_handle = 0;
> + }
> + break;
> + }
> + if ((try_again_timer.is_timeout() == true) &&
> + (ais_rc == SA_AIS_ERR_TRY_AGAIN)) {
> + LOG_WA("%s: saImmOiInitialize_2() Fail, TRY AGAIN timeout",
> __FUNCTION__);
> + *out_oi_handle = 0;
> + }
> +
> + return ais_rc;
> +}
> +
> +// Return -1 if Fail
> +// out_ais_rc is set to return code from saImmOiSelectionObjectGet()
> +static SaSelectionObjectT requestOiSelectionObject(SaImmOiHandleT
> oi_handle,
> + SaAisErrorT*
out_ais_rc) {
> + TRACE_ENTER();
> + SaSelectionObjectT oi_selection_object = -1;
> + SaAisErrorT ais_rc = SA_AIS_OK;
> + base::Timer try_again_timer(kOiRequestTimeout);
> + while (try_again_timer.is_timeout() == false) {
> + if (stop_oi_create) {
> + oi_selection_object = -1;
> + break;
> + }
> + ais_rc = saImmOiSelectionObjectGet(oi_handle, &oi_selection_object);
> + if (ais_rc == SA_AIS_ERR_TRY_AGAIN) {
> + base::Sleep(kOiTryAgainDelay);
> + continue;
> + }
> + if (ais_rc != SA_AIS_OK) {
> + LOG_WA("%s: saImmOiSelectionObjectGet() Fail, %s", __FUNCTION__,
> + saf_error(ais_rc));
> + oi_selection_object = -1;
> + }
> + break;
> + }
> + if ((try_again_timer.is_timeout() == true) &&
> + (ais_rc == SA_AIS_ERR_TRY_AGAIN)) {
> + LOG_WA("%s: saImmOiSelectionObjectGet() Fail, TRY AGAIN timeout",
> + __FUNCTION__);
> + oi_selection_object = -1;
> + }
> +
> + *out_ais_rc = ais_rc;
> + return oi_selection_object;
> +}
> +
> +// Set implementer name in kImplementerName
> +static SaAisErrorT setOiImplementerName(SaImmOiHandleT oi_handle) {
> + TRACE_ENTER();
> + SaAisErrorT ais_rc = SA_AIS_OK;
> + base::Timer try_again_timer(kOiRequestTimeout);
> + while (try_again_timer.is_timeout() == false) {
> + if (stop_oi_create) {
> + ais_rc = SA_AIS_OK;
> + break;
> + }
> + ais_rc = saImmOiImplementerSet(oi_handle, kImplementerName);
> + if (ais_rc == SA_AIS_ERR_TRY_AGAIN) {
> + base::Sleep(kOiTryAgainDelay);
> + continue;
> + }
> + if (ais_rc == SA_AIS_ERR_EXIST) {
> + // Means that we already have the implementer name registered which
> is Ok
> + TRACE("%s saImmOiImplementerSet() Fail %s. Ignore",
> + __FUNCTION__, saf_error(ais_rc));
> + ais_rc = SA_AIS_OK;
> + break;
> + } else if (ais_rc != SA_AIS_OK) {
> + LOG_WA("%s: saImmOiImplementerSet() Fail, %s", __FUNCTION__,
> + saf_error(ais_rc));
> + }
> + break;
> + }
> + if ((try_again_timer.is_timeout() == true) &&
> + (ais_rc == SA_AIS_ERR_TRY_AGAIN)) {
> + LOG_WA("%s: saImmOiImplementerSet() Fail, TRY AGAIN timeout",
> + __FUNCTION__);
> + }
> +
> + TRACE_LEAVE2("ais_rc = %s", saf_error(ais_rc));
> + return ais_rc;
> +}
> +
> +static SaAisErrorT setClassImplementer(SaImmOiHandleT oi_handle,
> + const SaImmClassNameT class_name)
{
> + SaAisErrorT ais_rc = SA_AIS_OK;
> + base::Timer try_again_timer(kOiRequestTimeout);
> + while (try_again_timer.is_timeout() == false) {
> + if (stop_oi_create) {
> + ais_rc = SA_AIS_OK;
> + break;
> + }
> + ais_rc = saImmOiClassImplementerSet(oi_handle, class_name);
> + if (ais_rc == SA_AIS_ERR_TRY_AGAIN) {
> + base::Sleep(kOiTryAgainDelay);
> + continue;
> + }
> + if (ais_rc != SA_AIS_OK) {
> + LOG_WA("%s: saImmOiClassImplementerSet() Fail, %s", __FUNCTION__,
> + saf_error(ais_rc));
> + }
> + break;
> + }
> + if ((try_again_timer.is_timeout() == true) &&
> + (ais_rc == SA_AIS_ERR_TRY_AGAIN)) {
> + LOG_WA("%s: saImmOiClassImplementerSet() Fail, TRY AGAIN timeout",
> + __FUNCTION__);
> + }
> +
> + return ais_rc;
> +}
> +
> +// Activate the poll loop in main()
> +// This will reinstall IMM poll event handling
> +static void sendOiCreatedMessageToMainThread() {
> + TRACE_ENTER();
> + // Note: lgsv_evt must be allocated C style since it will be freed in
other
> + // part of the code with free()
> + lgsv_lgs_evt_t *lgsv_evt;
> + lgsv_evt = static_cast<lgsv_lgs_evt_t *>(calloc(1,
sizeof(lgsv_lgs_evt_t)));
> + osafassert(lgsv_evt);
> +
> + lgsv_evt->evt_type = LGSV_EVT_NO_OP;
> + if (m_NCS_IPC_SEND(&lgs_mbx, lgsv_evt, LGS_IPC_PRIO_CTRL_MSGS) !=
> + NCSCC_RC_SUCCESS) {
> + LOG_WA("imm_reinit_thread failed to send IPC message to main
> thread");
> + /*
> + * Se no reason why this would happen. But if it does at least there
> + * is something in the syslog. The main thread should still pick up
> + * the new imm FD when there is a healthcheck, but it could take
> + *minutes.
> + */
> + free(lgsv_evt);
> + }
> +}
> +
> +// Creates the log service OI
> +// stop_oi_create: Used to stop thread execution as soon as possible
> +// Will stop the thread when set to true.
> +static SaAisErrorT createLogServerOi() {
> + TRACE_ENTER();
> + SaAisErrorT ais_rc = SA_AIS_OK;
> + SaImmOiHandleT oi_handle = 0;
> + SaSelectionObjectT oi_selection_object = -1;
> + base::Timer io_create_timeout(kOiCreationTimeout);
> +
> + while (io_create_timeout.is_timeout() == false) {
> + // OI init sequence
> +
> + // Init OI handle
> + if (stop_oi_create) break;
> + ais_rc = initOiHandle(&oi_handle);
> + if (ais_rc != SA_AIS_OK) {
> + LOG_NO("%s: initOiHandle() Fail", __FUNCTION__);
> + oi_handle = 0;
> + break;
> + }
> +
> + // Set OI implementer name
> + if (stop_oi_create) break;
> + ais_rc = setOiImplementerName(oi_handle);
> + if (ais_rc == SA_AIS_ERR_BAD_HANDLE) {
> + TRACE("%s: setOiImplementerName() Fail %s. Try to recover",
> + __FUNCTION__, saf_error(ais_rc));
> + continue;
> + } else if (ais_rc != SA_AIS_OK) {
> + LOG_NO("%s: setOiImplementerName() Fail", __FUNCTION__);
> + break;
> + }
> +
> + // Become class implementer for log config class
> + if (stop_oi_create) break;
> + ais_rc = setClassImplementer(oi_handle, kLogConfigurationClass);
> + if (ais_rc == SA_AIS_ERR_BAD_HANDLE) {
> + TRACE("%s: setClassImplementer(LogConfigurationClass) Fail %s. "
> + "Try to recover", __FUNCTION__, saf_error(ais_rc));
> + continue;
> + } else if (ais_rc != SA_AIS_OK) {
> + LOG_NO("%s: setClassImplementer(LogConfigurationClass) Fail",
> + __FUNCTION__);
> + break;
> + }
> +
> + // Become class implementer for stream config class
> + if (stop_oi_create) break;
> + ais_rc = setClassImplementer(oi_handle, kLogStreamClass);
> + if (ais_rc == SA_AIS_ERR_BAD_HANDLE) {
> + TRACE("%s: setClassImplementer(kLogStreamClass) Fail %s. "
> + "Try to recover", __FUNCTION__, saf_error(ais_rc));
> + continue;
> + } else if (ais_rc != SA_AIS_OK) {
> + LOG_NO("%s: setClassImplementer(kLogStreamClass) Fail",
> __FUNCTION__);
> + break;
> + } else {
> + // Get the selection object
> + oi_selection_object = requestOiSelectionObject(oi_handle, &ais_rc);
> + if (ais_rc == SA_AIS_ERR_BAD_HANDLE) {
> + TRACE("%s: requestOiSelectionObject() Fail", __FUNCTION__);
> + }
> + break;
> + }
> + }
> +
> + // Creation is done, has failed or is stopped.
> + if (stop_oi_create) {
> + TRACE("%s: OI create is stopped", __FUNCTION__);
> + oi_handle = 0;
> + oi_selection_object = -1;
> + ais_rc = SA_AIS_ERR_NO_OP; // Dummy. Must not be SA_AIS_OK
> + } else if ((io_create_timeout.is_timeout() == true) &&
> + (ais_rc != SA_AIS_OK)) {
> + LOG_WA("%s: Fail, OI creation timeout", __FUNCTION__);
> +#if 0 // Note: The following is needed if some other recovery than
restart
> + oi_handle = 0;
> + oi_selection_object = -1;
> +#endif
> + // The legacy behavior is to exit log service in this case
> + lgs_exit("saImmOiInitialize_2 failed", SA_AMF_COMPONENT_RESTART);
> + } else if (ais_rc != SA_AIS_OK) {
> + LOG_WA("%s: Fail, OI creation error", __FUNCTION__);
> +#if 0 // Note: The following is needed if some other recovery than
restart
> + oi_handle = 0;
> + oi_selection_object = -1;
> +#endif
> + // The legacy behavior is to exit log service in this case
> + lgs_exit("saImmOiInitialize_2 failed", SA_AMF_COMPONENT_RESTART);
> + }
> +
> + // Save OI handle and selection object
> + setProtectedGlobals(oi_handle, oi_selection_object);
> +
> + return ais_rc;
> +}
> +
> +// The thread function for creating a log server OI
> +// stop_oi_create: Used to stop thread execution as soon as possible
> +// Will stop the thread when set to true.
> +static void oiCreationThread() {
> + TRACE_ENTER();
> + SaAisErrorT ais_rc = createLogServerOi();
> +
> + if (ais_rc == SA_AIS_OK) {
> + // An object implementer was successfully created
> + // Send a message to the main thread. IMM events shall be polled
again
> + sendOiCreatedMessageToMainThread();
> + }
> +
> + return;
> +}
> +
> +// Public functions
> +//-----------------
> +// Make the thread class available for create and delete
> +static std::thread oiCreationThread_ {};
> +
> +
> +SaImmOiHandleT lgsGetOiHandle() {
> + base::Lock protect_globals(lgs_OI_init_mutex);
> + return oi_handle_;
> +}
> +
> +SaSelectionObjectT lgsGetOiSelectionObject() {
> + base::Lock protect_globals(lgs_OI_init_mutex);
> + return oi_selection_object_;
> +}
> +
> +SaSelectionObjectT lgsGetOiFdsParams(SaImmOiHandleT* out_oi_handle) {
> + base::Lock protect_globals(lgs_OI_init_mutex);
> + *out_oi_handle = oi_handle_;
> + return oi_selection_object_;
> +}
> +
> +void lgsOiCreateBackground() {
> + TRACE_ENTER();
> + if ((oiCreationThread_.joinable() == true) || (stop_oi_create == true))
{
> + // Thread is executing. Do nothing
> + return;
> + }
> +
> + // Make sure that the OI is finalized before creating a new one
> + // Note: oi_handle_ can be use unprotected here since we know that
there
> is
> + // no running oiCreationThread
> + finalizeOi(oi_handle_);
> + oi_handle_ = 0;
> + oi_selection_object_ = -1;
> +
> + // Start a OI creation thread
> + // Note: Throws an exception if "The system is unable to start a new
> thread"
> + // Should never happen so it is not handled here (will cause node
restart)
> + oiCreationThread_ = std::thread {&oiCreationThread};
> +}
> +
> +void lgsOiCreateSynchronous() {
> + TRACE_ENTER();
> + // Note: oi_handle_ can be use unprotected here since we know that
there
> is
> + // no running oiCreationThread
> + // There is no meaning to vall finalizeOI() since this function only
shall be
> + // used for the first creation of an OI handle during initialization of
the
> + // log service
> + oi_handle_ = 0;
> + oi_selection_object_ = -1;
> +
> + SaAisErrorT ais_rc = createLogServerOi();
> + LOG_NO("%s: createLogServerOi() %s", __FUNCTION__, saf_error(ais_rc));
> +}
> +
> +// Note: In this version this is just call lgsOiCreateBackground(). The
reason
> +// for having this function is to have a place where an implementer set
can
> +// be done instead of creating an OI if the lgsOiStop function is changed
> +// to just clear the OI. Note that if set fail the OI must be created
anyway
> +//
> +// This function shall be used only when changing HA state from standby
to
> +// active
> +void lgsOiStart() {
> + TRACE_ENTER();
> + lgsOiCreateBackground();
> +}
> +
> +// Note: oi_handle_ and oi_selection_object_ is always set in thread also
if
> +// thread is stopped. Is set to 0 and -1 respectively in all cases except
when
> +// an OI is successfully created
> +//
> +// Note: This version will completely finalize the OI. This is probably
good
> +// enough. Clear / Set handling may be a bit faster but Stop /
Start of
> +// OI should be rare.
> +// If optimization is needed we can do implementer clear here
> +void lgsOiStop() {
> + TRACE_ENTER();
> + stop_oi_create = true;
> +
> + // Handle thread if it exist
> + if (oiCreationThread_.joinable() == true) {
> + // Wait for thread to stop
> + oiCreationThread_.join();
> + }
> +
> + // Note: oi_handle_ can be use unprotected here since we know that
there
> is
> + // no running oiCreationThread
> + finalizeOi(oi_handle_);
> + oi_handle_ = 0;
> + oi_selection_object_ = -1;
> + stop_oi_create = false;
> +}
> diff --git a/src/log/logd/lgs_oi_admin.h b/src/log/logd/lgs_oi_admin.h
> new file mode 100644
> index 000000000..8502e30e7
> --- /dev/null
> +++ b/src/log/logd/lgs_oi_admin.h
> @@ -0,0 +1,105 @@
> +/* -*- OpenSAF -*-
> + *
> + * (C) Copyright 2008 The OpenSAF Foundation
> + * Copyright Ericsson AB 2008, 2018 - All Rights Reserved.
> + *
> + * This program is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> MERCHANTABILITY
> + * or FITNESS FOR A PARTICULAR PURPOSE. This file and program are
> licensed
> + * under the GNU Lesser General Public License Version 2.1, February
1999.
> + * The complete license can be accessed from the following location:
> + * http://opensource.org/licenses/lgpl-license.php
> + * See the Copying file included with the OpenSAF distribution for full
> + * licensing terms.
> + *
> + * Author(s): Ericsson AB
> + *
> + */
> +
> +#include "ais/include/saImmOi.h"
> +
> +// Contains administrative handling of the lgs main object implementer
(OI)
> +// Implements functions for initializing an OI in a background thread,
> +// finalizing the OI and stop an ongoing initialization
> +// The reason for using a background thread is to not block the log
server.
> +// An initialize request may take up to 1 minute.
> +// When stopping the OI a running OI initializing thread is stopped and
the OI
> +// is finalized.
> +//
> +// Examples of situations when the functions are used:
> +// Starting log server: OI shall be intialized. This should be done in
> +// background so that start of log server is not
blocked.
> +//
> +// Switch/fail over: The to become standby; must give up the OI. The
> chosen
> +// way of doing that is to finalize the OI. An
alternative
> +// is to only clear the OI which is no longer used
here.
> +// The to become active; must initialize an OI. An
> +// alternative is to keep the OI handle and just use
the
> +// set API
> +//
> +// BAD HANDLE: IMM may return bad handle when synchronous
> operations
> +// are called including the dispatch function. If
this
> +// happen the OI shall be initialized again except
in a
> +// switch/fail over situation where the server shall
become
> +// standby
> +//
> +// Note1: The background thread puts a no-operation message in the
> mailbox
> +// handled by the main poll loop when OI initialize is done. This
is
> +// needed to handle installing of the IMM fd in the poll loop.
> +//
> +// Note2: The previous global immOiHandle and immSelectionObject
> variables in
> +// cb struct are removed. Values can be fetched using thread safe
get
> +// functions
> +
> +#ifndef LGS_OI_ADMIN_H
> +#define LGS_OI_ADMIN_H
> +
> +// Creates a new OI. Return false if fail.
> +// Note1: If there is an existing OI it will be deleted and a new is
created.
> +// This means calling IMM finalize, setting oi_handle = 0,
> +// oi_selection_object = -1 and starting the OI creation thread.
The
> +// OI creation thread will update oi_handle and
oi_selection_object with
> +// new values when creation is done.
> +// Nothing will be done if OI creation is already ongoing when
this
> +// function is called
> +// Note2: lgsOiCreateBackground() shall not be used when log server is
> starting.
> +// During initialization configuration streams are created.
> +// When creating a configuration stream cached Rt attributes has
to be
> +// written and this requires a valid OI handle
> +// Instead use lgsOiCreateSyncronous()
> +//
> +// This function shall also be used to restore the OI in case of a BAD
HANDLE
> +// return code when using the OI handle with an OI IMM operation.
> +void lgsOiCreateBackground();
> +
> +// Note3: This function shall only be called once and only when the log
> server
> +// is initializing
> +// This function is not thread safe
> +void lgsOiCreateSynchronous();
> +
> +// Start an OI.
> +// Shall be used when this server shall become an OI.
> +// For example when becoming active
> +void lgsOiStart();
> +
> +// Stop an existing OI
> +// To be used when this server no longer shall be an OI.
> +// For example becoming standby
> +void lgsOiStop();
> +
> +// Get both OI handle and selection object. Guarantees that we get a pair
> +// that is created together. Return -1 if there is no selection object
and
> +// the value of out_oi_handle will be 0
> +// Is thread safe
> +SaSelectionObjectT lgsGetOiFdsParams(SaImmOiHandleT* out_oi_handle);
> +
> +// Returns the created OI selection object or -1 if there is none
> +// Is thread safe
> +SaSelectionObjectT lgsGetOiSelectionObject();
> +
> +// Returns the created OI handle or 0 if there is no handle
> +// Is thread safe
> +SaImmOiHandleT lgsGetOiHandle();
> +
> +#endif /* LGS_OI_ADMIN_H */
> +
> diff --git a/src/log/logd/lgs_recov.cc b/src/log/logd/lgs_recov.cc
> index dcaad188d..7c0197b7f 100644
> --- a/src/log/logd/lgs_recov.cc
> +++ b/src/log/logd/lgs_recov.cc
> @@ -15,9 +15,11 @@
> *
> */
>
> -#include "lgs_recov.h"
> +#include "log/logd/lgs_recov.h"
> +
> #include "log/logd/lgs_file.h"
> #include "log/logd/lgs_filehdl.h"
> +#include "log/logd/lgs_imm.h"
>
> /***
> * The following functions are used to handle a list of runtime stream
objects
> diff --git a/src/log/logd/lgs_stream.cc b/src/log/logd/lgs_stream.cc
> index 0c83e305b..4f50f5a98 100644
> --- a/src/log/logd/lgs_stream.cc
> +++ b/src/log/logd/lgs_stream.cc
> @@ -30,14 +30,16 @@
> #include "log/logd/lgs_stream.h"
> #include <algorithm>
>
> +#include "base/osaf_time.h"
> +#include "osaf/immutil/immutil.h"
> +
> #include "log/logd/lgs.h"
> #include "log/logd/lgs_config.h"
> #include "log/logd/lgs_file.h"
> #include "log/logd/lgs_filehdl.h"
> #include "log/logd/lgs_mbcsv_v1.h"
> #include "log/logd/lgs_mbcsv_v2.h"
> -#include "base/osaf_time.h"
> -#include "osaf/immutil/immutil.h"
> +#include "log/logd/lgs_oi_admin.h"
>
> #define DEFAULT_NUM_APP_LOG_STREAMS 64
>
> @@ -444,15 +446,18 @@ void log_stream_delete(log_stream_t **s) {
>
> if (lgs_cb->ha_state == SA_AMF_HA_ACTIVE) {
> if (stream->isRtStream == SA_TRUE) {
> - SaAisErrorT rv;
> + SaAisErrorT ais_rc;
> TRACE("Stream is closed, I am HA active so remove IMM object");
> SaNameT objectName;
> osaf_extended_name_lend(stream->name.c_str(), &objectName);
> - rv = saImmOiRtObjectDelete(lgs_cb->immOiHandle, &objectName);
> - if (rv != SA_AIS_OK) {
> + ais_rc = saImmOiRtObjectDelete(lgsGetOiHandle(), &objectName);
> + if (ais_rc != SA_AIS_OK) {
> + if (ais_rc == SA_AIS_ERR_BAD_HANDLE) {
> + lgsOiCreateBackground();
> + }
> /* no retry; avoid blocking LOG service #1886 */
> - LOG_WA("saImmOiRtObjectDelete returned %u for %s", rv,
> - stream->name.c_str());
> + LOG_WA("%s: saImmOiRtObjectDelete returned %s for %s",
> + __FUNCTION__, saf_error(ais_rc), stream->name.c_str());
> }
> }
> }
> @@ -514,6 +519,53 @@ int lgs_populate_log_stream(
> return rc;
> }
>
> +// Wrap creation of a runtime object. Handle try again ERR_EXIST
> +// If the object already exist it is deleted and then the new object is
created
> +// Note: This is a help function to be used in createRtObject() only
> +// Note: immutil is used
> +// The first 4 parameters are the same as for
> immutil_saImmOiRtObjectCreate_2
> +// The last parameter is the same as object name used with
> +// immutil_saImmOiRtObjectDelete()
> +static SaAisErrorT createRtObject(const SaImmOiHandleT oi_handle,
> + const SaImmClassNameT class_name,
> + const SaNameT* parent_name,
> + const SaImmAttrValuesT_2**
attribute_values,
> + const SaNameT *object_name) {
> +SaAisErrorT ais_rc = SA_AIS_OK;
> +
> + for (int i = 0; i <= 2; i++) {
> + ais_rc = immutil_saImmOiRtObjectCreate_2(oi_handle,
> + class_name,
> + parent_name,
> + attribute_values);
> + if (ais_rc == SA_AIS_ERR_EXIST) {
> + SaAisErrorT del_rc = immutil_saImmOiRtObjectDelete(oi_handle,
> object_name);
> + if (del_rc == SA_AIS_ERR_BAD_HANDLE) {
> + LOG_NO("%s: saImmOiRtObjectDelete() Fail, %s", __FUNCTION__,
> + saf_error(del_rc));
> + lgsOiCreateBackground();
> + } else if (del_rc != SA_AIS_OK) {
> + LOG_NO("%s: saImmOiRtObjectDelete() Fail, %s", __FUNCTION__,
> + saf_error(del_rc));
> + break;
> + } else {
> + // The existing object is deleted. Try again to create a new one
> + continue;
> + }
> + } else if (ais_rc == SA_AIS_ERR_BAD_HANDLE) {
> + LOG_NO("%s: saImmOiRtObjectCreate_2() Fail, %s",
> + __FUNCTION__, saf_error(ais_rc));
> + lgsOiCreateBackground();
> + break;
> + } else {
> + break;
> + }
> + }
> +
> + // saImmOiRtObjectCreate_2() return code
> + return ais_rc;
> +}
> +
> /**
> * Create a new rt app stream object.
> *
> @@ -536,8 +588,9 @@ SaAisErrorT
> lgs_create_appstream_rt_object(log_stream_t *const stream) {
> parent_name++; /* FIX, vulnerable for malformed DNs */
> parentName = &parent;
> osaf_extended_name_lend(parent_name, &parent);
> - } else
> + } else {
> rdnstr = const_cast<char *>(stream->name.c_str());
> + }
>
> void *arr1[] = {&rdnstr};
> const SaImmAttrValuesT_2 attr_safLgStr = {
> @@ -622,14 +675,20 @@ SaAisErrorT
> lgs_create_appstream_rt_object(log_stream_t *const stream) {
> &attr_saLogStreamCreationTimestamp,
> NULL};
>
> - rc = immutil_saImmOiRtObjectCreate_2(
> - lgs_cb->immOiHandle,
> const_cast<SaImmClassNameT>("SaLogStream"),
> - parentName, attrValues);
> + SaNameT object_name;
> + osaf_extended_name_lend(stream->name.c_str(), &object_name);
> + SaImmOiHandleT oi_handle = lgsGetOiHandle();
> + rc = createRtObject(oi_handle,
> + const_cast<SaImmClassNameT>("SaLogStream"),
> + parentName,
> + attrValues,
> + &object_name);
> free(dndup);
>
> if (rc != SA_AIS_OK) {
> - LOG_WA("saImmOiRtObjectCreate_2 returned %u for %s, parent %s", rc,
> - stream->name.c_str(), parent_name);
> + LOG_WA("%s: createRtObject() returned %s for %s, "
> + "parent %s", __FUNCTION__, saf_error(rc),
stream->name.c_str(),
> + parent_name);
> }
> }
>
> --
> 2.16.2
------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Opensaf-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel