Hi Zoran,

Reviewed and tested the patch.
Ack from me.

BR,

Hung Nguyen - DEK Technologies


--------------------------------------------------------------------------------
From: Zoran Milinkovic [email protected]
Sent: Monday, September 11, 2017 10:53PM
To: Hung Nguyen
    [email protected]
Cc: Opensaf-devel, Zoran Milinkovic
    [email protected], [email protected]
Subject: [PATCH 1/1] imm: remove disconnected appliers [#2579]


When an applier is disconnected, it will be removed from the system after time 
period set in minApplierTimeout attribute in IMM object.
If the time is set to 0, it will work as it works today, and it will never be 
removed from the system.

The time set in minApplierTimeout attribute guarantees that the applier will be 
"alive" for at least the time set in the attribute.
When this period expires, with the next clean the basement call, the applier 
will be removed.

The time set in minApplierTimeout attribute is in seconds.

To enable this feature, protocol51710 must be enabled and minApplierTimeout 
attribute value must be great than 0.
---
 samples/immsv/OpensafImm_Upgrade_5.17.10.xml | 120 +++++++++++++++++
 src/imm/common/immsv_api.h                   |   2 +
 src/imm/common/immsv_evt.c                   | 118 ++++++++++++++++
 src/imm/common/immsv_evt.h                   |  14 ++
 src/imm/immd/immd_evt.c                      |  69 ++++++++++
 src/imm/immloadd/imm_loader.cc               |  12 +-
 src/imm/immnd/ImmModel.cc                    | 193 ++++++++++++++++++++++++++-
 src/imm/immnd/ImmModel.h                     |   6 +-
 src/imm/immnd/immnd_evt.c                    |  43 ++++++
 src/imm/immnd/immnd_init.h                   |   5 +-
 src/imm/immnd/immnd_proc.c                   |  41 +++++-
 11 files changed, 613 insertions(+), 10 deletions(-)
 create mode 100644 samples/immsv/OpensafImm_Upgrade_5.17.10.xml

diff --git a/samples/immsv/OpensafImm_Upgrade_5.17.10.xml 
b/samples/immsv/OpensafImm_Upgrade_5.17.10.xml
new file mode 100644
index 0000000..fb70880
--- /dev/null
+++ b/samples/immsv/OpensafImm_Upgrade_5.17.10.xml
@@ -0,0 +1,120 @@
+<?xml version="1.0"?>
+<imm:IMM-contents xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:noNamespaceSchemaLocation="SAI-AIS-IMM-XSD-A.02.13.xsd" xmlns:xs="http://www.w3.org/2001/XMLSchema"; 
xmlns:imm="http://www.saforum.org/IMMSchema";>
+  <class name="OpensafImm">
+    <category>SA_CONFIG</category>
+    <rdn>
+      <name>opensafImm</name>
+      <type>SA_NAME_T</type>
+      <category>SA_CONFIG</category>
+      <flag>SA_INITIALIZED</flag>
+    </rdn>
+    <attr>
+      <name>maxClasses</name>
+      <type>SA_UINT32_T</type>
+      <category>SA_CONFIG</category>
+      <flag>SA_WRITABLE</flag>
+      <default-value>1000</default-value>
+    </attr>
+    <attr>
+      <name>maxImplementers</name>
+      <type>SA_UINT32_T</type>
+      <category>SA_CONFIG</category>
+      <flag>SA_WRITABLE</flag>
+      <default-value>3000</default-value>
+    </attr>
+    <attr>
+      <name>maxAdminowners</name>
+      <type>SA_UINT32_T</type>
+      <category>SA_CONFIG</category>
+      <flag>SA_WRITABLE</flag>
+      <default-value>2000</default-value>
+    </attr>
+    <attr>
+      <name>maxCcbs</name>
+      <type>SA_UINT32_T</type>
+      <category>SA_CONFIG</category>
+      <flag>SA_WRITABLE</flag>
+      <default-value>10000</default-value>
+    </attr>
+    <attr>
+      <name>scAbsenceAllowed</name>
+      <type>SA_UINT32_T</type>
+      <category>SA_RUNTIME</category>
+      <flag>SA_PERSISTENT</flag>
+      <flag>SA_CACHED</flag>
+      <default-value>0</default-value>
+    </attr>
+    <attr>
+      <name>accessControlMode</name>
+      <type>SA_UINT32_T</type>
+      <category>SA_CONFIG</category>
+      <flag>SA_WRITABLE</flag>
+      <default-value>0</default-value>
+    </attr>
+    <attr>
+      <name>authorizedGroup</name>
+      <type>SA_STRING_T</type>
+      <category>SA_CONFIG</category>
+      <flag>SA_WRITABLE</flag>
+    </attr>
+    <attr>
+      <name>longDnsAllowed</name>
+      <type>SA_UINT32_T</type>
+      <category>SA_CONFIG</category>
+      <flag>SA_WRITABLE</flag>
+      <default-value>0</default-value>
+    </attr>
+    <attr>
+      <name>opensafImmSyncBatchSize</name>
+      <type>SA_UINT32_T</type>
+      <category>SA_CONFIG</category>
+      <flag>SA_WRITABLE</flag>
+      <default-value>65223</default-value>
+    </attr>
+    <attr>
+      <name>opensafImmNostdFlags</name>
+      <type>SA_UINT32_T</type>
+      <category>SA_RUNTIME</category>
+      <flag>SA_CACHED</flag>
+      <default-value>0</default-value>
+    </attr>
+    <attr>
+      <name>opensafImmEpoch</name>
+      <type>SA_UINT32_T</type>
+      <category>SA_RUNTIME</category>
+      <flag>SA_PERSISTENT</flag>
+      <flag>SA_CACHED</flag>
+    </attr>
+    <attr>
+      <name>opensafImmClassNames</name>
+      <type>SA_STRING_T</type>
+      <category>SA_RUNTIME</category>
+      <flag>SA_MULTI_VALUE</flag>
+      <flag>SA_PERSISTENT</flag>
+      <flag>SA_CACHED</flag>
+    </attr>
+    <attr>
+      <name>minApplierTimeout</name>
+      <type>SA_UINT32_T</type>
+      <category>SA_CONFIG</category>
+      <flag>SA_WRITABLE</flag>
+      <default-value>0</default-value>
+    </attr>
+    <attr>
+      <name>SaImmAttrImplementerName</name>
+      <type>SA_STRING_T</type>
+      <category>SA_CONFIG</category>
+    </attr>
+    <attr>
+      <name>SaImmAttrClassName</name>
+      <type>SA_STRING_T</type>
+      <category>SA_CONFIG</category>
+      <default-value>OpensafImm</default-value>
+    </attr>
+    <attr>
+      <name>SaImmAttrAdminOwnerName</name>
+      <type>SA_STRING_T</type>
+      <category>SA_CONFIG</category>
+    </attr>
+  </class>
+</imm:IMM-contents>
diff --git a/src/imm/common/immsv_api.h b/src/imm/common/immsv_api.h
index cb43ec6..32fc573 100644
--- a/src/imm/common/immsv_api.h
+++ b/src/imm/common/immsv_api.h
@@ -69,6 +69,7 @@ extern "C" {
 #define OPENSAF_IMM_MAX_IMPLEMENTERS "maxImplementers"
 #define OPENSAF_IMM_MAX_ADMINOWNERS "maxAdminowners"
 #define OPENSAF_IMM_MAX_CCBS "maxCcbs"
+#define OPENSAF_IMM_MIN_APPLIER_TIMEOUT "minApplierTimeout"
typedef enum {
   ACCESS_CONTROL_DISABLED = 0,
@@ -149,6 +150,7 @@ typedef enum {
 #define OPENSAF_IMM_FLAG_PRT47_ALLOW 0x00000040
 #define OPENSAF_IMM_FLAG_PRT50_ALLOW 0x00000080
 #define OPENSAF_IMM_FLAG_PRT51_ALLOW 0x00000100
+#define OPENSAF_IMM_FLAG_PRT51710_ALLOW 0x00000200
#define OPENSAF_IMM_SERVICE_NAME "safImmService" diff --git a/src/imm/common/immsv_evt.c b/src/imm/common/immsv_evt.c
index 8871c14..88c5101 100644
--- a/src/imm/common/immsv_evt.c
+++ b/src/imm/common/immsv_evt.c
@@ -66,6 +66,7 @@ static const char *immd_evt_names[] = {"undefined",
                                       "IMMD_EVT_ND2D_LOADING_COMPLETED",
                                       "IMMD_EVT_ND2D_2PBE_PRELOAD",
                                       "IMMD_EVT_ND2D_IMPLSET_REQ_2",
+                                      "IMMD_EVT_ND2D_IMPLDELETE",
                                       "undefined (high)"};
static const char *immsv_get_immd_evt_name(unsigned int id)
@@ -185,6 +186,7 @@ static const char *immnd_evt_names[] = {
     "IMMND_EVT_A2ND_OBJ_CREATE_2",    /* saImmOmCcbObjectCreate_o3 */
     "IMMND_EVT_A2ND_OI_OBJ_CREATE_2", /* saImmOiRtObjectCreate_o3 */
     "IMMND_EVT_A2ND_OBJ_SAFE_READ",   /* saImmOmCcbObjectRead */
+    "IMMND_EVT_D2ND_IMPLDELETE",
     "undefined (high)"};
static const char *immsv_get_immnd_evt_name(unsigned int id)
@@ -1631,6 +1633,26 @@ static uint32_t immsv_evt_enc_sublevels(IMMSV_EVT 
*i_evt, NCS_UBAID *o_ub)
                                    __LINE__);
                                return NCSCC_RC_OUT_OF_MEM;
                        }
+               } else if (i_evt->info.immd.type == IMMD_EVT_ND2D_IMPLDELETE) {
+                       uint8_t *p8;
+                       IMMSV_IMPLDELETE *impl_delete = 
&i_evt->info.immd.info.impl_delete;
+
+                       for(SaUint32T i=0; i<impl_delete->size; ++i) {
+                               uint32_t length = 
strnlen(impl_delete->implNameList[i].buf,
+                                                                                 
impl_delete->implNameList[i].size);
+
+                               IMMSV_RSRV_SPACE_ASSERT(p8, o_ub, 4);
+                               ncs_encode_32bit(&p8, length);
+                               ncs_enc_claim_space(o_ub, 4);
+
+                               if (ncs_encode_n_octets_in_uba(o_ub,
+                                               (uint8_t 
*)impl_delete->implNameList[i].buf,
+                                               length) != NCSCC_RC_SUCCESS) {
+                                       LOG_WA(
+                                               "Failure inside 
ncs_encode_n_octets_in_uba");
+                                       return NCSCC_RC_FAILURE;
+                               }
+                       }
                } else if ((i_evt->info.immd.info.ctrl_msg.pbeEnabled >= 3) &&
                           (i_evt->info.immd.type ==
                            IMMD_EVT_ND2D_INTRO)) { /* extended intro */
@@ -2155,6 +2177,28 @@ static uint32_t immsv_evt_enc_sublevels(IMMSV_EVT 
*i_evt, NCS_UBAID *o_ub)
                        if (!immsv_evt_enc_inline_text(__LINE__, o_ub, os)) {
                                return NCSCC_RC_OUT_OF_MEM;
                        }
+               } else if (i_evt->info.immnd.type == IMMND_EVT_D2ND_IMPLDELETE) 
{
+                       uint32_t length;
+                       uint8_t *p8;
+                       IMMSV_IMPLDELETE *impl_delete =
+                                       &i_evt->info.immnd.info.impl_delete;
+
+                       for(SaUint32T i=0; i<impl_delete->size; ++i) {
+                               length = 
strnlen(impl_delete->implNameList[i].buf,
+                                                               
impl_delete->implNameList[i].size);
+
+                               IMMSV_RSRV_SPACE_ASSERT(p8, o_ub, 4);
+                               ncs_encode_32bit(&p8, length);
+                               ncs_enc_claim_space(o_ub, 4);
+
+                               if (ncs_encode_n_octets_in_uba(o_ub,
+                                               (uint8_t 
*)impl_delete->implNameList[i].buf,
+                                               length) != NCSCC_RC_SUCCESS) {
+                                       LOG_WA(
+                                           "Failure inside 
ncs_encode_n_octets_in_uba");
+                                       return NCSCC_RC_FAILURE;
+                               }
+                       }
                }
        }
@@ -2390,6 +2434,31 @@ static uint32_t immsv_evt_dec_sublevels(NCS_UBAID *i_ub, IMMSV_EVT *o_evt)
                                immsv_evt_dec_attrmods(i_ub, &p);
                                o_evt->info.immd.info.objModify.attrMods = p;
                        }
+               } else if (o_evt->info.immd.type == IMMD_EVT_ND2D_IMPLDELETE) {
+                       uint8_t *p8;
+                       uint8_t local_data[8];
+                       IMMSV_OCTET_STRING *implNameList;
+                       IMMSV_IMPLDELETE *impl_delete = 
&o_evt->info.immd.info.impl_delete;
+
+                       impl_delete->implNameList = (IMMSV_OCTET_STRING 
*)calloc(1,
+                                       impl_delete->size * 
sizeof(IMMSV_OCTET_STRING));
+                       implNameList = impl_delete->implNameList;
+                       for(SaUint32T i=0; i<impl_delete->size; ++i) {
+                               IMMSV_FLTN_SPACE_ASSERT(p8, local_data, i_ub, 
4);
+                               implNameList[i].size = ncs_decode_32bit(&p8);
+                               ncs_dec_skip_space(i_ub, 4);
+
+                               implNameList[i].buf = (char *)malloc(
+                                               implNameList[i].size + 1);
+                               if (implNameList[i].buf == NULL ||
+                                               
ncs_decode_n_octets_from_uba(i_ub,
+                                                               (uint8_t 
*)implNameList[i].buf,
+                                                               
implNameList[i].size) != NCSCC_RC_SUCCESS) {
+                                       LOG_WA("Failure inside 
ncs_decode_n_octets_from_uba");
+                                       return NCSCC_RC_FAILURE;
+                               }
+                               implNameList[i].buf[implNameList[i].size] = 0;
+                       }
                } else if ((o_evt->info.immd.info.ctrl_msg.pbeEnabled >= 3) &&
                           (o_evt->info.immd.type ==
                            IMMD_EVT_ND2D_INTRO)) { /* extended intro */
@@ -2814,6 +2883,31 @@ static uint32_t immsv_evt_dec_sublevels(NCS_UBAID *i_ub, 
IMMSV_EVT *o_evt)
                        IMMSV_OCTET_STRING *os =
                            &(o_evt->info.immnd.info.ccbUpcallRsp.errorString);
                        immsv_evt_dec_inline_string(i_ub, os);
+               } else if (o_evt->info.immnd.type == IMMND_EVT_D2ND_IMPLDELETE) 
{
+                       uint8_t *p8;
+                       uint8_t local_data[8];
+                       IMMSV_OCTET_STRING *implNameList;
+                       IMMSV_IMPLDELETE *impl_delete;
+
+                       impl_delete = &o_evt->info.immnd.info.impl_delete;
+                       impl_delete->implNameList = (IMMSV_OCTET_STRING 
*)calloc(1,
+                                                       impl_delete->size * 
sizeof(IMMSV_OCTET_STRING));
+                       implNameList = impl_delete->implNameList;
+                       for (SaUint32T i=0; i<impl_delete->size; ++i) {
+                               IMMSV_FLTN_SPACE_ASSERT(p8, local_data, i_ub, 
4);
+                               implNameList[i].size = ncs_decode_32bit(&p8);
+                               ncs_dec_skip_space(i_ub, 4);
+
+                               implNameList[i].buf = (char 
*)malloc(implNameList[i].size);
+                               if (implNameList[i].buf == NULL ||
+                                               
ncs_decode_n_octets_from_uba(i_ub,
+                                                               (uint8_t 
*)implNameList[i].buf,
+                                                               
implNameList[i].size) != NCSCC_RC_SUCCESS) {
+                                       LOG_WA("Failure inside 
ncs_decode_n_octets_from_uba");
+                                       return NCSCC_RC_FAILURE;
+                               }
+                               implNameList[i].buf[implNameList[i].size] = 0;
+                       }
                }
        }
        return NCSCC_RC_SUCCESS;
@@ -3523,6 +3617,12 @@ static uint32_t immsv_evt_enc_toplevel(IMMSV_EVT *i_evt, 
NCS_UBAID *o_ub)
                        ncs_enc_claim_space(o_ub, 8);
                        break;
+ case IMMD_EVT_ND2D_IMPLDELETE:
+                       IMMSV_RSRV_SPACE_ASSERT(p8, o_ub, 4);
+                       ncs_encode_32bit(&p8, immdevt->info.impl_delete.size);
+                       ncs_enc_claim_space(o_ub, 4);
+                       break;
+
                case IMMD_EVT_MDS_INFO:
                        LOG_WA("Unexpected event over MDS->IMMD:%u",
                               immdevt->type);
@@ -4547,6 +4647,12 @@ static uint32_t immsv_evt_enc_toplevel(IMMSV_EVT *i_evt, 
NCS_UBAID *o_ub)
                        /* message has no contents */
                        break;
+ case IMMND_EVT_D2ND_IMPLDELETE:
+                       IMMSV_RSRV_SPACE_ASSERT(p8, o_ub, 4);
+                       ncs_encode_32bit(&p8, immndevt->info.impl_delete.size);
+                       ncs_enc_claim_space(o_ub, 4);
+                       break;
+
                case IMMND_EVT_MDS_INFO: /* IMMA/IMMND/IMMD UP/DOWN Info */
                case IMMND_EVT_TIME_OUT: /* Time out event */
                case IMMND_EVT_CB_DUMP:
@@ -5256,6 +5362,12 @@ static uint32_t immsv_evt_dec_toplevel(NCS_UBAID *i_ub, 
IMMSV_EVT *o_evt)
break; + case IMMD_EVT_ND2D_IMPLDELETE:
+                       IMMSV_FLTN_SPACE_ASSERT(p8, local_data, i_ub, 4);
+                       immdevt->info.impl_delete.size = ncs_decode_32bit(&p8);
+                       ncs_dec_skip_space(i_ub, 4);
+                       break;
+
                case IMMD_EVT_MDS_INFO:
                        LOG_ER("Unexpected event over MDS->IMMD:%u",
                               immdevt->type);
@@ -6336,6 +6448,12 @@ static uint32_t immsv_evt_dec_toplevel(NCS_UBAID *i_ub, 
IMMSV_EVT *o_evt)
                        ncs_dec_skip_space(i_ub, 4);
                        break;
+ case IMMND_EVT_D2ND_IMPLDELETE:
+                       IMMSV_FLTN_SPACE_ASSERT(p8, local_data, i_ub, 4);
+                       immndevt->info.impl_delete.size = ncs_decode_32bit(&p8);
+                       ncs_dec_skip_space(i_ub, 4);
+                       break;
+
                case IMMND_EVT_D2ND_RESET:
                        /* message has no contents */
                        break;
diff --git a/src/imm/common/immsv_evt.h b/src/imm/common/immsv_evt.h
index 59aa351..3e96c98 100644
--- a/src/imm/common/immsv_evt.h
+++ b/src/imm/common/immsv_evt.h
@@ -246,6 +246,8 @@ typedef enum immnd_evt_type {
IMMND_EVT_A2ND_OBJ_SAFE_READ = 100, /* saImmOmCcbObjectRead */ + IMMND_EVT_D2ND_IMPLDELETE = 101, /* Applier delete */
+
   IMMND_EVT_MAX
 } IMMND_EVT_TYPE;
 /* Make sure the string array in immsv_evt.c matches the IMMND_EVT_TYPE enum. 
*/
@@ -294,6 +296,8 @@ typedef enum immd_evt_type {
IMMD_EVT_ND2D_IMPLSET_REQ_2 = 27, /* OiImplementerSet */ + IMMD_EVT_ND2D_IMPLDELETE = 28, /* Delete non-used applier */
+
   IMMD_EVT_MAX
 } IMMD_EVT_TYPE;
 /* Make sure the string array in immsv_evt.c matches the IMMD_EVT_TYPE enum. */
@@ -510,6 +514,12 @@ typedef struct imma_tmr_info {
   SaInvocationT invocation;
 } IMMA_TMR_INFO;
+/* Used in both ND2D and D2ND events */
+typedef struct immsv_impldelete {
+  SaUint32T size;
+  IMMSV_OCTET_STRING *implNameList;    // List of implementer names
+} IMMSV_IMPLDELETE;
+
 /******************************************************************************
  IMMA Event Data Struct
  
******************************************************************************/
@@ -589,6 +599,8 @@ typedef struct immnd_evt {
SaUint64T syncFevsBase; /* FevsCount that sync iterator is
                                based on . */
+
+    IMMSV_IMPLDELETE impl_delete;
   } info;
 } IMMND_EVT;
@@ -626,6 +638,8 @@ typedef struct immd_evt {
     IMMSV_SYNC_FEVS_BASE syncFevsBase; /* FevsCount that sync is
                                           based on . */
     IMMSV_ND2D_2_PBE pbe2; /* Stats about a pbe file (redundant pbe)*/
+
+    IMMSV_IMPLDELETE impl_delete;
   } info;
 } IMMD_EVT;
diff --git a/src/imm/immd/immd_evt.c b/src/imm/immd/immd_evt.c
index 24a4185..a0d9319 100644
--- a/src/imm/immd/immd_evt.c
+++ b/src/imm/immd/immd_evt.c
@@ -85,6 +85,9 @@ static uint32_t immd_evt_proc_sync_fevs_base(IMMD_CB *cb, 
IMMD_EVT *evt,
 static uint32_t immd_evt_proc_2pbe_preload(IMMD_CB *cb, IMMD_EVT *evt,
                                           IMMSV_SEND_INFO *sinfo);
+static uint32_t immd_evt_proc_impl_delete(IMMD_CB *cb, IMMD_EVT *evt,
+                                               IMMSV_SEND_INFO *sinfo);
+
 /****************************************************************************
  * Name          : immd_process_evt
  *
@@ -220,6 +223,11 @@ void immd_process_evt(void)
                                                     &evt->sinfo);
                break;
+ case IMMD_EVT_ND2D_IMPLDELETE:
+               rc = immd_evt_proc_impl_delete(cb, &evt->info.immd,
+                               &evt->sinfo);
+               break;
+
        default:
                /* Log the error TBD */
                LOG_WA("UNRECOGNIZED IMMD EVENT: %u", evt->info.immd.type);
@@ -3266,3 +3274,64 @@ done:
        TRACE_LEAVE();
        return NCSCC_RC_SUCCESS;
 }
+
+static uint32_t immd_evt_proc_impl_delete(IMMD_CB *cb, IMMD_EVT *evt,
+                                               IMMSV_SEND_INFO *sinfo) {
+       IMMSV_EVT fevs_evt;
+       IMMSV_IMPLDELETE *impl_del = &evt->info.impl_delete;
+       NCS_UBAID uba;
+       char *tmpData = NULL;
+       uba.start = NULL;
+       TRACE_ENTER();
+       TRACE_5("Delete %u implementer(s) (applier(s))", impl_del->size);
+
+       /*Create and pack the core message for fevs. */
+
+       memset(&fevs_evt, 0, sizeof(IMMSV_EVT));
+       fevs_evt.type = IMMSV_EVT_TYPE_IMMND;
+       fevs_evt.info.immnd.type = IMMND_EVT_D2ND_IMPLDELETE;
+       fevs_evt.info.immnd.info.impl_delete = *impl_del;
+
+       uint32_t proc_rc = ncs_enc_init_space(&uba);
+       if (proc_rc != NCSCC_RC_SUCCESS) {
+               LOG_WA("Failed init ubaid");
+               goto fail;
+       }
+
+       proc_rc = immsv_evt_enc(&fevs_evt, &uba);
+       if (proc_rc != NCSCC_RC_SUCCESS) {
+               LOG_WA("Failed encode fevs");
+               goto fail;
+       }
+
+       int32_t size = uba.ttl;
+       tmpData = malloc(size);
+       osafassert(tmpData);
+       char *data = m_MMGR_DATA_AT_START(uba.start, size, tmpData);
+
+       memset(&fevs_evt, 0, sizeof(IMMSV_EVT)); /*No ponters=>no leak */
+       fevs_evt.type = IMMSV_EVT_TYPE_IMMD;
+       fevs_evt.info.immd.type = 0;
+       fevs_evt.info.immd.info.fevsReq.msg.size = size;
+       fevs_evt.info.immd.info.fevsReq.msg.buf = data;
+
+       proc_rc =
+           immd_evt_proc_fevs_req(cb, &(fevs_evt.info.immd), sinfo, false);
+
+fail:
+       if (tmpData) {
+               free(tmpData);
+       }
+
+       if (uba.start) {
+               m_MMGR_FREE_BUFR_LIST(uba.start);
+       }
+
+       for(uint32_t i=0; i<evt->info.impl_delete.size; ++i) {
+               free(evt->info.impl_delete.implNameList[i].buf);
+       }
+       free(evt->info.impl_delete.implNameList);
+
+       TRACE_LEAVE();
+       return proc_rc;
+}
diff --git a/src/imm/immloadd/imm_loader.cc b/src/imm/immloadd/imm_loader.cc
index fc51a6a..4b6ad08 100644
--- a/src/imm/immloadd/imm_loader.cc
+++ b/src/imm/immloadd/imm_loader.cc
@@ -292,7 +292,8 @@ static int base64_decode(char *in, char *out) {
 void opensafClassCreate(SaImmHandleT immHandle) {
   SaAisErrorT err = SA_AIS_OK;
   int retries = 0;
-  SaImmAttrDefinitionT_2 d1, d2, d3, d4, d5, d6, d7, d8, d9, d10, d11, d12, 
d13;
+  SaImmAttrDefinitionT_2 d1, d2, d3, d4, d5, d6, d7, d8, d9, d10;
+  SaImmAttrDefinitionT_2 d11, d12, d13, d14;
   SaUint32T nost_flags_default = 0;
   SaUint32T batch_size_default = IMMSV_DEFAULT_MAX_SYNC_BATCH_SIZE;
   SaUint32T extended_names_enabled_default = 0;
@@ -302,6 +303,7 @@ void opensafClassCreate(SaImmHandleT immHandle) {
   SaUint32T max_implementers_default = 3000;
   SaUint32T max_adminOwners_default = 2000;
   SaUint32T max_ccbs_default = 10000;
+  SaUint32T min_applier_timeout = 0;
d1.attrName = (char *)OPENSAF_IMM_ATTR_RDN;
   d1.attrValueType = SA_IMM_ATTR_SANAMET;
@@ -371,8 +373,14 @@ void opensafClassCreate(SaImmHandleT immHandle) {
   d13.attrFlags = SA_IMM_ATTR_CONFIG | SA_IMM_ATTR_WRITABLE;
   d13.attrDefaultValue = &max_ccbs_default;
+ d14.attrName = (char *)OPENSAF_IMM_MIN_APPLIER_TIMEOUT;
+  d14.attrValueType = SA_IMM_ATTR_SAUINT32T;
+  d14.attrFlags = SA_IMM_ATTR_CONFIG | SA_IMM_ATTR_WRITABLE;
+  d14.attrDefaultValue = &min_applier_timeout;
+
   const SaImmAttrDefinitionT_2 *attrDefs[] = {
-      &d1, &d2, &d3, &d4, &d5, &d6, &d7, &d8, &d9, &d10, &d11, &d12, &d13, 0};
+      &d1, &d2, &d3, &d4, &d5, &d6, &d7, &d8, &d9, &d10,
+      &d11, &d12, &d13, &d14, 0};
do { /* Create the class */ diff --git a/src/imm/immnd/ImmModel.cc b/src/imm/immnd/ImmModel.cc
index 2a53ed4..b4db0a0 100644
--- a/src/imm/immnd/ImmModel.cc
+++ b/src/imm/immnd/ImmModel.cc
@@ -82,7 +82,8 @@ struct ImplementerInfo {
         mAdminOpBusy(0),
         mDying(false),
         mApplier(false),
-        mTimeout(DEFAULT_TIMEOUT_SEC) {}
+        mTimeout(DEFAULT_TIMEOUT_SEC),
+        mApplierDisconnected(0) {}
   SaUint32T mId;
   SaUint32T mConn;  // Current implementer, only valid on one node.
   // NULL otherwise.
@@ -93,6 +94,7 @@ struct ImplementerInfo {
   bool mDying;
   bool mApplier;       // This is an applier OI
   SaUint32T mTimeout;  // OI callback timeout
+  SaUint64T mApplierDisconnected;  // Time when applier is disconnected
 };
typedef std::vector<ImplementerInfo*> ImplementerVector;
@@ -585,6 +587,7 @@ static const std::string 
immMaxClasses(OPENSAF_IMM_MAX_CLASSES);
 static const std::string immMaxAdmOwn(OPENSAF_IMM_MAX_ADMINOWNERS);
 static const std::string immMaxCcbs(OPENSAF_IMM_MAX_CCBS);
 static const std::string immMaxImp(OPENSAF_IMM_MAX_IMPLEMENTERS);
+static const std::string immMinApplierTimeout(OPENSAF_IMM_MIN_APPLIER_TIMEOUT);
static const std::string immMngtClass("SaImmMngt");
 static const std::string immManagementDn(
@@ -1117,6 +1120,10 @@ bool immModel_protocol51Allowed(IMMND_CB* cb) {
   return ImmModel::instance(&cb->immModel)->protocol51Allowed();
 }
+bool immModel_protocol51710Allowed(IMMND_CB* cb) {
+  return ImmModel::instance(&cb->immModel)->protocol51710Allowed();
+}
+
 OsafImmAccessControlModeT immModel_accessControlMode(IMMND_CB* cb) {
   return ImmModel::instance(&cb->immModel)->accessControlMode();
 }
@@ -1133,18 +1140,21 @@ SaUint32T immModel_cleanTheBasement(
     IMMND_CB* cb, SaInvocationT** admReqArr, SaUint32T* admReqArrSize,
     SaInvocationT** searchReqArr, SaUint32T* searchReqArrSize,
     SaUint32T** ccbIdArr, SaUint32T* ccbIdArrSize, SaUint32T** pbePrtoReqArr,
-    SaUint32T* pbePrtoReqArrSize, bool iAmCoordNow) {
+    SaUint32T* pbePrtoReqArrSize, IMMSV_OCTET_STRING **applierArr,
+    SaUint32T *applierArrSize, bool iAmCoordNow) {
   InvocVector admReqs;
   InvocVector searchReqs;
   InvocVector::iterator ix1;
   IdVector ccbs;
   IdVector pbePrtoReqs;
+  ImplNameVector appliers;
   IdVector::iterator ix2;
   unsigned int ix;
SaUint32T stuck = ImmModel::instance(&cb->immModel)
                         ->cleanTheBasement(admReqs, searchReqs, ccbs,
-                                           pbePrtoReqs, iAmCoordNow);
+                                           pbePrtoReqs, appliers,
+                                           iAmCoordNow);
*admReqArrSize = (SaUint32T)admReqs.size();
   if (*admReqArrSize) {
@@ -1244,6 +1254,16 @@ SaUint32T immModel_cleanTheBasement(
         &cb->client_info_db, cl_node->patnode.key_info);
   }
+ if(appliers.size() > 0) {
+    *applierArrSize = appliers.size();
+    *applierArr = (IMMSV_OCTET_STRING *)malloc(
+            appliers.size() * sizeof(IMMSV_OCTET_STRING));
+    for(size_t i=0; i<appliers.size(); ++i) {
+      (*applierArr)[i].buf = strdup(appliers[i].c_str());
+      (*applierArr)[i].size = strlen((*applierArr)[i].buf);
+    }
+  }
+
   return stuck;
 }
@@ -2236,6 +2256,10 @@ void immModel_setCcbErrorString(IMMND_CB* cb, SaUint32T ccbId,
   va_end(vl);
 }
+void immModel_implementerDelete(IMMND_CB *cb, const char *implementerName) {
+  ImmModel::instance(&cb->immModel)->implementerDelete(implementerName);
+}
+
 /*====================================================================*/
ImmModel::ImmModel() : loaderPid(-1) {}
@@ -3897,6 +3921,30 @@ bool ImmModel::protocol51Allowed() {
   return noStdFlags & OPENSAF_IMM_FLAG_PRT51_ALLOW;
 }
+bool ImmModel::protocol51710Allowed() {
+  // TRACE_ENTER();
+  /* Assume that all nodes are running the same version when loading */
+  if (sImmNodeState == IMM_NODE_LOADING) {
+    return true;
+  }
+  ObjectMap::iterator oi = sObjectMap.find(immObjectDn);
+  if (oi == sObjectMap.end()) {
+    // TRACE_LEAVE();
+    return false;
+  }
+
+  ObjectInfo* immObject = oi->second;
+  ImmAttrValueMap::iterator avi =
+      immObject->mAttrValueMap.find(immAttrNostFlags);
+  osafassert(avi != immObject->mAttrValueMap.end());
+  osafassert(!(avi->second->isMultiValued()));
+  ImmAttrValue* valuep = avi->second;
+  unsigned int noStdFlags = valuep->getValue_int();
+
+  // TRACE_LEAVE();
+  return noStdFlags & OPENSAF_IMM_FLAG_PRT51710_ALLOW;
+}
+
 bool ImmModel::protocol41Allowed() {
   // TRACE_ENTER();
   ObjectMap::iterator oi = sObjectMap.find(immObjectDn);
@@ -4980,6 +5028,8 @@ SaAisErrorT ImmModel::adminOwnerDelete(SaUint32T ownerId, 
bool hard,
               immObject->mAttrValueMap.find(immMaxAdmOwn);
           ImmAttrValueMap::iterator avi4 =
               immObject->mAttrValueMap.find(immMaxCcbs);
+          ImmAttrValueMap::iterator avi5 =
+              immObject->mAttrValueMap.find(immMinApplierTimeout);
ImmAttrValue* valuep = (ImmAttrValue*)avi->second;
           unsigned int noStdFlags = valuep->getValue_int();
@@ -4999,6 +5049,13 @@ SaAisErrorT ImmModel::adminOwnerDelete(SaUint32T 
ownerId, bool hard,
           } else {
             noStdFlags |= OPENSAF_IMM_FLAG_PRT51_ALLOW;
           }
+          if(avi5 == immObject->mAttrValueMap.end()) {
+            LOG_NO("protcol51710 is not set for opensafImmNostdFlags because"
+                "The new OpenSAF 5.17.10 attributes are not added "
+                "to OpensafImm class");
+          } else {
+            noStdFlags |= OPENSAF_IMM_FLAG_PRT51710_ALLOW;
+          }
           valuep->setValue_int(noStdFlags);
           LOG_NO("%s changed to: 0x%x", immAttrNostFlags.c_str(), noStdFlags);
           /* END Temporary code. */
@@ -8324,7 +8381,7 @@ SaAisErrorT ImmModel::ccbObjectCreate(
             impl->mDying = false;
             impl->mApplier = false;
           }
-          // Reconenct implementer.
+          // Reconnect implementer.
           object->mImplementer = impl;
         }
       }
@@ -13873,6 +13930,13 @@ void ImmModel::discardNode(unsigned int deadNode, 
IdVector& cv, IdVector& gv,
       // messages that depend on the implementer. We DO NOT want different
       // behavior at different nodes, only because an implementor is gone.
+ // Save the time when applier is disconnected
+      if(info->mImplementerName.at(0) == '@') {
+        struct timespec ts;
+        osaf_clock_gettime(CLOCK_MONOTONIC, &ts);
+        info->mApplierDisconnected = osaf_timespec_to_millis(&ts);
+      }
+
       // We keep the ImplementerInfo entry with the implementer name,
       // for now.
       // The ImplementerInfo is pointed to by ClassInfo or ObjectInfo.
@@ -13998,6 +14062,14 @@ void ImmModel::discardImplementer(unsigned int 
implHandle, bool reallyDiscard,
       // implementers. Possible solution is to here iterate through all
       // classes and objects. If none point to this object then we can
       // actually remove it. Removal must be via fevs though!
+
+      // Save the time when applier is disconnected
+      if(info->mImplementerName.at(0) == '@') {
+        struct timespec ts;
+        osaf_clock_gettime(CLOCK_MONOTONIC, &ts);
+        info->mApplierDisconnected = osaf_timespec_to_millis(&ts);
+      }
+
       if ((sImmNodeState == IMM_NODE_R_AVAILABLE) ||
           (sImmNodeState == IMM_NODE_W_AVAILABLE)) {
         /* Sync is ongoing. Remember the death of the implementer. */
@@ -14407,7 +14479,9 @@ bool ImmModel::purgeSyncRequest(SaUint32T clientId) {
SaUint32T ImmModel::cleanTheBasement(InvocVector& admReqs,
                                      InvocVector& searchReqs, IdVector& ccbs,
-                                     IdVector& pbePrtoReqs, bool iAmCoord) {
+                                     IdVector& pbePrtoReqs,
+                                     ImplNameVector& appliers,
+                                     bool iAmCoord) {
   timespec now;
   osaf_clock_gettime(CLOCK_MONOTONIC, &now);
   ContinuationMap2::iterator ci2;
@@ -14663,6 +14737,44 @@ SaUint32T ImmModel::cleanTheBasement(InvocVector& 
admReqs,
     }
   }
+ if(protocol51710Allowed()) {
+    unsigned int applierTimeout;
+
+    ObjectMap::iterator oi = sObjectMap.find(immObjectDn);
+    // This has already been checked in protocol51710Allowed()
+    osafassert(oi != sObjectMap.end());
+
+    ObjectInfo* immObject = oi->second;
+    ImmAttrValueMap::iterator avi =
+        immObject->mAttrValueMap.find(immMinApplierTimeout);
+    osafassert(avi != immObject->mAttrValueMap.end());
+    osafassert(!(avi->second->isMultiValued()));
+    ImmAttrValue* valuep = avi->second;
+    applierTimeout = valuep->getValue_int();
+
+    if(applierTimeout > 0) {
+      SaUint64T now;
+      struct timespec ts;
+      ImplementerVector::iterator ivi;
+
+      // Convert applierTimeout to miliseconds
+      applierTimeout *= 1000;
+
+      osaf_clock_gettime(CLOCK_MONOTONIC, &ts);
+      now = osaf_timespec_to_millis(&ts);
+
+      for(ivi=sImplementerVector.begin();
+              ivi != sImplementerVector.end();
+              ++ivi) {
+        if((*ivi)->mImplementerName.at(0) == '@'
+                && (*ivi)->mApplierDisconnected > 0
+                && ((*ivi)->mApplierDisconnected + applierTimeout) <= now) {
+          appliers.push_back((*ivi)->mImplementerName);
+        }
+      }
+    }
+  }
+
   return ccbsStuck + pbeRtRegress;
 }
@@ -14821,6 +14933,7 @@ SaAisErrorT ImmModel::implementerSet(const IMMSV_OCTET_STRING* implementerName, if (isApplier) {
     info->mApplier = true;
+    info->mApplierDisconnected = 0;
     LOG_NO("Implementer (applier) connected: %u (%s) <%u, %x>", info->mId,
            info->mImplementerName.c_str(), info->mConn, info->mNodeId);
   } else {
@@ -15868,6 +15981,66 @@ void ImmModel::clearImplName(ObjectInfo* obj) {
   }
 }
+void ImmModel::implementerDelete(const char *implementerName) {
+  ImplementerInfo *applier = NULL;
+
+  TRACE_ENTER();
+
+  auto ivi = sImplementerVector.begin();
+  for(; ivi != sImplementerVector.end(); ++ivi) {
+    if((*ivi)->mImplementerName == implementerName) {
+      applier = *ivi;
+      break;
+    }
+  }
+
+  if(!applier) {
+    TRACE("Cannot find implementer with id: %s", implementerName);
+    goto failed;
+  }
+
+  if(applier->mImplementerName.at(0) != '@') {
+    TRACE("Implementer with id %s is not applier", implementerName);
+    goto failed;
+  }
+
+  if(!applier->mApplierDisconnected) {
+    TRACE("Applier with id %s is used again", implementerName);
+    goto failed;
+  }
+
+  // Delete implementer from sImplementerVector
+  sImplementerVector.erase(ivi);
+
+  // Delete implementer from sClassMap
+  for(auto cmi = sClassMap.begin(); cmi != sClassMap.end(); ++cmi) {
+    // TODO: It might be more efficient
+    // if we call only cmi->second->mAppliers.erase(applier);
+    auto it = cmi->second->mAppliers.find(applier);
+    if(it != cmi->second->mAppliers.end()) {
+      cmi->second->mAppliers.erase(it);
+    }
+  }
+
+  // Delete implementer from sObjAppliersMap
+  for(auto oami = sObjAppliersMap.begin();
+      oami != sObjAppliersMap.end(); ++oami) {
+    // TODO: Same as for sClassMap
+    auto it = oami->second->find(applier);
+    if(it != oami->second->end()) {
+      oami->second->erase(it);
+    }
+  }
+
+  // Delete implementer from sImplDetachTime if it exists
+  sImplDetachTime.erase(applier);
+
+  delete applier;
+
+failed:
+  TRACE_LEAVE();
+}
+
 /**
  * Helper function to set admin owner.
  */
@@ -19252,6 +19425,11 @@ SaAisErrorT 
ImmModel::finalizeSync(ImmsvOmFinalizeSync* req, bool isCoord,
// Sync currently existing implementers
       ImmsvImplList* ii = req->implementers;
+      // Calculate applier timeout before the loop
+      struct timespec ts;
+      SaUint64T applierDisconnected;
+      osaf_clock_gettime(CLOCK_MONOTONIC, &ts);
+      applierDisconnected = osaf_timespec_to_millis(&ts);
       for (; ii; ii = ii->next) {
         std::string implName;
         size_t sz = strnlen((const char*)ii->implementerName.buf,
@@ -19327,6 +19505,11 @@ SaAisErrorT 
ImmModel::finalizeSync(ImmsvOmFinalizeSync* req, bool isCoord,
         info->mImplementerName = implName;
         info->mAdminOpBusy = 0;
         info->mApplier = (info->mImplementerName.at(0) == '@');
+        if(!info->mNodeId && info->mApplier) {
+          /* The info when an applier is disconnected is not synced.
+           * It will be calculated from the time it's synced */
+          info->mApplierDisconnected = applierDisconnected;
+        }
         sImplementerVector.push_back(info);
         TRACE_5(
             "Immnd sync client synced implementer id:%u name:>>%s<< "
diff --git a/src/imm/immnd/ImmModel.h b/src/imm/immnd/ImmModel.h
index c970d91..9e4c54a 100644
--- a/src/imm/immnd/ImmModel.h
+++ b/src/imm/immnd/ImmModel.h
@@ -73,6 +73,7 @@ class ImmSearchOp;
 typedef std::vector<SaUint32T> ConnVector;
 typedef std::vector<unsigned int> NodeIdVector;
 typedef std::vector<std::string> ObjectNameVector;
+typedef std::vector<std::string> ImplNameVector;
 typedef std::vector<SaUint32T> IdVector;
 typedef std::map<std::string, ObjectInfo*> ObjectMap;
 typedef std::vector<SaInvocationT> InvocVector;
@@ -112,6 +113,7 @@ class ImmModel {
   bool protocol47Allowed();
   bool protocol50Allowed();
   bool protocol51Allowed();
+  bool protocol51710Allowed();
   bool oneSafe2PBEAllowed();
   bool purgeSyncRequest(SaUint32T clientId);
   bool verifySchemaChange(const std::string& className, ClassInfo* oldClass,
@@ -314,6 +316,8 @@ class ImmModel {
void clearImplName(ObjectInfo* obj); + void implementerDelete(const char *implementerName);
+
   SaAisErrorT implementerClear(const struct ImmsvOiImplSetReq* req,
                                SaUint32T con, unsigned int nodeId, IdVector& 
gv,
                                bool isAtCoord);
@@ -413,7 +417,7 @@ class ImmModel {
                 unsigned int* pbeNodeIdPtr);
   SaUint32T cleanTheBasement(InvocVector& admReqs, InvocVector& searchReqs,
                              IdVector& ccbs, IdVector& pbePrtoReqs,
-                             bool iAmCoord);
+                             ImplNameVector& appliers, bool iAmCoord);
void fetchAdmImplContinuation(SaInvocationT& inv,
                                 SaUint32T* implConn,     // in-out!
diff --git a/src/imm/immnd/immnd_evt.c b/src/imm/immnd/immnd_evt.c
index 0e1b330..52d33dc 100644
--- a/src/imm/immnd/immnd_evt.c
+++ b/src/imm/immnd/immnd_evt.c
@@ -285,6 +285,8 @@ static void immnd_evt_ccb_abort(IMMND_CB *cb, SaUint32T 
ccbId,
 static uint32_t immnd_evt_proc_reset(IMMND_CB *cb, IMMND_EVT *evt,
                                     IMMSV_SEND_INFO *sinfo);
+static uint32_t immnd_evt_impl_delete(IMMND_CB *cb, IMMND_EVT *evt);
+
 #if 0 /* Only for debug */
 static void printImmValue(SaImmValueTypeT t, IMMSV_EDU_ATTR_VAL *v)
 {
@@ -563,6 +565,11 @@ uint32_t immnd_evt_destroy(IMMSV_EVT *evt, bool onheap, 
uint32_t line)
                free(evt->info.immnd.info.ccbUpcallRsp.errorString.buf);
                evt->info.immnd.info.ccbUpcallRsp.errorString.buf = NULL;
                evt->info.immnd.info.ccbUpcallRsp.errorString.size = 0;
+       } else if (evt->info.immnd.type == IMMND_EVT_D2ND_IMPLDELETE) {
+               for(uint32_t i=0; i<evt->info.immnd.info.impl_delete.size; ++i) 
{
+                       
free(evt->info.immnd.info.impl_delete.implNameList[i].buf);
+               }
+               free(evt->info.immnd.info.impl_delete.implNameList);
        }
if (onheap) {
@@ -9932,6 +9939,10 @@ immnd_evt_proc_fevs_dispatch(IMMND_CB *cb, 
IMMSV_OCTET_STRING *msg,
                                         reply_dest);
                break;
+ case IMMND_EVT_D2ND_IMPLDELETE:
+               immnd_evt_impl_delete(cb, &frwrd_evt.info.immnd);
+               break;
+
        default:
                LOG_ER(
                    "UNPACK FAILURE, unrecognized message type: %u over FEVS",
@@ -12318,3 +12329,35 @@ uint32_t immnd_is_immd_up(IMMND_CB *cb)
return is_immd_up;
 }
+
+/*****************************************************************************
+ * Name          : immnd_evt_impl_delete
+ *
+ * Description   : This function delete non-used appliers who timed out
+ *
+ * Arguments     : cb       - IMMND Control Block pointer
+ *                 evt - Received Event structure
+ *
+ * Return Values : true/false
+ *****************************************************************************/
+static uint32_t immnd_evt_impl_delete(IMMND_CB *cb, IMMND_EVT *evt)
+{
+       uint32_t rc = NCSCC_RC_FAILURE;
+       TRACE_ENTER();
+
+       if(cb->mSync) {
+               TRACE("The node is going to be synced. Ignoring.");
+               rc =  NCSCC_RC_FAILURE;
+               goto failed;
+       }
+
+       for(uint32_t i=0; i<evt->info.impl_delete.size; ++i) {
+               immModel_implementerDelete(cb,
+                               evt->info.impl_delete.implNameList[i].buf);
+       }
+
+       TRACE_LEAVE();
+
+failed:
+       return rc;
+}
diff --git a/src/imm/immnd/immnd_init.h b/src/imm/immnd/immnd_init.h
index eacd5c4..1791236 100644
--- a/src/imm/immnd/immnd_init.h
+++ b/src/imm/immnd/immnd_init.h
@@ -128,7 +128,8 @@ SaUint32T immModel_cleanTheBasement(
     IMMND_CB *cb, SaInvocationT **admReqArr, SaUint32T *admReqArrSize,
     SaInvocationT **searchReqArr, SaUint32T *searchReqArrSize,
     SaUint32T **ccbIdArr, SaUint32T *ccbIdArrSize, SaUint32T **pbePrtoReqIdArr,
-    SaUint32T *pbePrtoReqArrSize, bool iAmCoordNow);
+    SaUint32T *pbePrtoReqArrSize, IMMSV_OCTET_STRING **applierArrapplierArr,
+    SaUint32T *applierArrSize, bool iAmCoordNow);
void immModel_getNonCriticalCcbs(IMMND_CB *cb, SaUint32T **ccbIdArr,
                                  SaUint32T *ccbIdArrSize);
@@ -477,6 +478,8 @@ void immmModel_getLocalImplementers(IMMND_CB *cb, SaUint32T 
*arrSize,
                                     SaUint32T **implIdArr,
                                     SaUint32T **implConnArr);
+void immModel_implementerDelete(IMMND_CB *cb, const char *implementerName);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/imm/immnd/immnd_proc.c b/src/imm/immnd/immnd_proc.c
index 22f8737..f525548 100644
--- a/src/imm/immnd/immnd_proc.c
+++ b/src/imm/immnd/immnd_proc.c
@@ -1199,6 +1199,8 @@ static void immnd_cleanTheHouse(IMMND_CB *cb, bool 
iAmCoordNow)
        SaUint32T ccbIdArrSize = 0;
        SaUint32T *pbePrtoReqArr = NULL;
        SaUint32T pbePrtoReqArrSize = 0;
+       IMMSV_OCTET_STRING *applierArr = NULL;
+       SaUint32T applierArrSize = 0;
SaInvocationT inv;
        SaUint32T reqConn = 0;
@@ -1305,7 +1307,7 @@ static void immnd_cleanTheHouse(IMMND_CB *cb, bool 
iAmCoordNow)
        stuck = immModel_cleanTheBasement(
            cb, &admReqArr, &admReqArrSize, &searchReqArr, &searchReqArrSize,
            &ccbIdArr, &ccbIdArrSize, &pbePrtoReqArr, &pbePrtoReqArrSize,
-           iAmCoordNow);
+           &applierArr, &applierArrSize, iAmCoordNow);
if (stuck > 1) {
                pbePrtoStuck = true;
@@ -1587,6 +1589,43 @@ static void immnd_cleanTheHouse(IMMND_CB *cb, bool 
iAmCoordNow)
                }
        }
+ if(applierArrSize) {
+               IMMSV_EVT send_evt;
+               SaUint32T pos = 0;
+
+               memset(&send_evt, 0, sizeof(IMMSV_EVT));
+               send_evt.type = IMMSV_EVT_TYPE_IMMD;
+               send_evt.info.immd.type = IMMD_EVT_ND2D_IMPLDELETE;
+
+               /* For the performance issue, IMMD_EVT_ND2D_IMPLDELETE
+                * will send sets of applier names. Each set will be up
+                * to 50255 (50000 + 255) characters of applier names.
+                * This will cover that in few IMMD_EVT_ND2D_IMPLDELETE
+                * messages, all timed out appliers are removed from
+                * the cluster.
+                */
+               while(pos < applierArrSize) {
+                       uint32_t sendSize;
+
+                       send_evt.info.immd.info.impl_delete.size = 0;
+                       send_evt.info.immd.info.impl_delete.implNameList =
+                                       &(applierArr[pos]);
+                       for(sendSize=0; pos < applierArrSize && sendSize < 
50000; ++pos) {
+                               ++send_evt.info.immd.info.impl_delete.size;
+                               sendSize += strlen(applierArr[pos].buf);
+                       }
+                       if (immnd_mds_msg_send(cb, NCSMDS_SVC_ID_IMMD,
+                                       cb->immd_mdest_id, &send_evt) != 
NCSCC_RC_SUCCESS) {
+                               LOG_WA("Failure to broadcast implementer (applier) 
delete");
+                       }
+               }
+
+               for(SaUint32T i=0; i<applierArrSize; ++i) {
+                       free(applierArr[i].buf);
+               }
+               free(applierArr);
+       }
+
        /*TRACE_LEAVE(); */
 }

------------------------------------------------------------------------------
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

Reply via email to