When CCB apply (IMMND_EVT_A2ND_CCB_APPLY) gets TIMEOUT, IMMND will be
informed the timeout via msg type IMMND_EVT_A2ND_CL_TIMEOUT, and then
doing following things:
1) Attemp to abort CCB even the CCB state is in critical.
2) Remove client node from client dabase.

Once the CCB has been comitted, saImmOmCcbApply() returns SA_AIS_OK to user.
As the client is removed at #2 above, any IMM operations on the IMM OM handle
such as saImmOmCcbObjectDelete() or saImmOmFinalize() will result in BAD_HANDLE.

With this fix, the client having critical CCB will not be purged when
timeout happens at IMM sync requests.
---
 .../management/test_saImmOmCcbInitialize.c    |   4 +
 .../management/test_saImmOmCcbObjectDelete.c  | 120 ++++++++++++++++++
 src/imm/immnd/ImmModel.cc                     |  18 +--
 3 files changed, 133 insertions(+), 9 deletions(-)

diff --git a/src/imm/apitest/management/test_saImmOmCcbInitialize.c 
b/src/imm/apitest/management/test_saImmOmCcbInitialize.c
index ab4fe158f..71d1c1703 100644
--- a/src/imm/apitest/management/test_saImmOmCcbInitialize.c
+++ b/src/imm/apitest/management/test_saImmOmCcbInitialize.c
@@ -160,6 +160,7 @@ extern void saImmOmCcbObjectDelete_11(void);
 extern void saImmOmCcbObjectDelete_12(void);
 extern void saImmOmCcbObjectDelete_13(void);
 extern void saImmOmCcbObjectDelete_14(void);
+extern void saImmOmCcbObjectDelete_15(void);
 extern void saImmOmCcbObjectModify_2_01(void);
 extern void saImmOmCcbObjectModify_2_02(void);
 extern void saImmOmCcbObjectModify_2_03(void);
@@ -299,6 +300,9 @@ __attribute__((constructor)) static void 
saImmOmInitialize_constructor(void)
        test_case_add(
            6, saImmOmCcbObjectDelete_14,
            "saImmOmCcbObjectDelete - SA_AIS_ERR_FAILED_OPERATION, set 
NO_DANGLING reference to an object created in the same CCB and then delete 
reffered object");
+       test_case_add(
+               6, saImmOmCcbObjectDelete_15,
+               "saImmOmCcbObjectDelete - SA_AIS_OK, operate on CCB handle 
which had been previously applied but got TIMEOUT");
 
        test_case_add(6, saImmOmCcbObjectModify_2_01,
                      "saImmOmCcbObjectModify_2 - SA_AIS_OK");
diff --git a/src/imm/apitest/management/test_saImmOmCcbObjectDelete.c 
b/src/imm/apitest/management/test_saImmOmCcbObjectDelete.c
index d8423b795..f02fb60a3 100644
--- a/src/imm/apitest/management/test_saImmOmCcbObjectDelete.c
+++ b/src/imm/apitest/management/test_saImmOmCcbObjectDelete.c
@@ -794,6 +794,126 @@ void saImmOmCcbObjectDelete_14(void)
        test_validate(rc, SA_AIS_ERR_FAILED_OPERATION);
 }
 
+/*
+ * The saImmOmCcbObjectDelete_15 test case is created to verify that
+ * no SA_AIS_ERR_BAD_HANDLE is returned when working on the CCB handle
+ * which has been previously applied but got SA_AIS_ERR_TIMEOUT internally
+ * due to PBE hung. (refer to ticket #2889 for more info).
+ *
+ * This test case should be run on the same node with osafimmpbed process.
+ * The test case will report PASSED if the pre-condition does not meet.
+ */
+#include <pthread.h>
+#include <unistd.h>
+
+static bool enable_pbe(void)
+{
+       const char *cmd = "immcfg -m -a saImmRepositoryInit=1"
+               " safRdn=immManagement,safApp=safImmService";
+
+       return (WEXITSTATUS(system(cmd)) == EXIT_SUCCESS);
+}
+
+static bool pbe_running_on_this_node(void)
+{
+       const char *cmd = "pidof osafimmpbed >/dev/null 2>&1";
+
+       return (enable_pbe() && WEXITSTATUS(system(cmd)) == EXIT_SUCCESS);
+}
+
+static int hang_pbe(void)
+{
+       const char *cmd = "pkill -STOP osafimmpbed";
+
+       return WEXITSTATUS(system(cmd));
+}
+
+static void *unhang_pbe(void *args)
+{
+       const char *cmd = "pkill -CONT osafimmpbed";
+
+       sleep(10);
+       if (WEXITSTATUS(system(cmd)) != EXIT_SUCCESS)
+               fprintf(stderr, "Failed to execute cmd: %s\n", cmd);
+
+       return NULL;
+}
+
+static void resume_pbe_in_bg(void)
+{
+       pthread_t thread;
+       pthread_attr_t attr;
+
+       pthread_attr_init(&attr);
+       pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+       pthread_create(&thread, &attr, &unhang_pbe, NULL);
+}
+
+void saImmOmCcbObjectDelete_15(void)
+{
+       const SaImmAdminOwnerNameT adminOwnerName =
+           (SaImmAdminOwnerNameT) __func__;
+       SaImmAdminOwnerHandleT ownerHandle;
+       SaImmCcbHandleT ccbHandle;
+       SaNameT rdn = {strlen("saImmOmCcbObjectDelete_15"),
+                      "saImmOmCcbObjectDelete_15"};
+       SaNameT *nameValues[] = {&rdn};
+       SaImmAttrValuesT_2 v2 = {"rdn", SA_IMM_ATTR_SANAMET, 1,
+                                (void **)nameValues};
+       SaUint32T int1Value1 = 7;
+       SaUint32T *int1Values[] = {&int1Value1};
+       SaImmAttrValuesT_2 v1 = {"attr1", SA_IMM_ATTR_SAUINT32T, 1,
+                                (void **)int1Values};
+       const SaImmAttrValuesT_2 *attrValues[] = {&v1, &v2, NULL};
+       const SaNameT *objectNames[] = {&rootObj, NULL};
+       const SaNameT objectName = {
+               strlen("saImmOmCcbObjectDelete_15,rdn=root"),
+               "saImmOmCcbObjectDelete_15,rdn=root"
+       };
+
+       if (pbe_running_on_this_node() == false) {
+               printf("Not support! This test should run on the same node"
+                      " with osafimmpbed.\n");
+               test_validate(SA_AIS_OK, SA_AIS_OK);
+               return;
+       }
+
+       safassert(immutil_saImmOmInitialize(&immOmHandle, &immOmCallbacks,
+                                           &immVersion), SA_AIS_OK);
+       safassert(immutil_saImmOmAdminOwnerInitialize(
+                         immOmHandle, adminOwnerName, SA_TRUE,
+                         &ownerHandle), SA_AIS_OK);
+       safassert(immutil_saImmOmAdminOwnerSet(
+                         ownerHandle, objectNames,
+                         SA_IMM_ONE), SA_AIS_OK);
+
+       safassert(immutil_saImmOmCcbInitialize(
+                         ownerHandle, 0, &ccbHandle), SA_AIS_OK);
+       safassert(immutil_saImmOmCcbObjectCreate_2(
+                         ccbHandle, configClassName, &rootObj,
+                         attrValues), SA_AIS_OK);
+
+       // Make PBE hung while applying CCB
+       hang_pbe();
+       resume_pbe_in_bg();
+       safassert(immutil_saImmOmCcbApply(ccbHandle), SA_AIS_OK);
+
+       SaAisErrorT ais = immutil_saImmOmCcbObjectDelete(ccbHandle,
+                                                        &objectName);
+       if (ais != SA_AIS_OK) {
+               test_validate(ais, SA_AIS_OK);
+               return;
+       }
+
+       safassert(immutil_saImmOmCcbApply(ccbHandle), SA_AIS_OK);
+       safassert(immutil_saImmOmCcbFinalize(ccbHandle), SA_AIS_OK);
+       safassert(immutil_saImmOmAdminOwnerRelease(
+                         ownerHandle, objectNames,
+                         SA_IMM_ONE), SA_AIS_OK);
+       safassert(immutil_saImmOmAdminOwnerFinalize(ownerHandle), SA_AIS_OK);
+       safassert(immutil_saImmOmFinalize(immOmHandle), SA_AIS_OK);
+}
+
 __attribute__((constructor)) static void
 saImmOmCcbObjectDelete_constructor(void)
 {
diff --git a/src/imm/immnd/ImmModel.cc b/src/imm/immnd/ImmModel.cc
index 80ba6efac..6f0593dc5 100644
--- a/src/imm/immnd/ImmModel.cc
+++ b/src/imm/immnd/ImmModel.cc
@@ -6065,7 +6065,7 @@ bool ImmModel::commitModify(const std::string& dn, 
ObjectInfo* afterImage) {
     /* Empty Admin Owner can imply (hard) release during apply/commit.
        This can happen if client invokes apply and then disconnects
        without waiting for reply. Typically because of timeout on
-       the syncronous ccbApply. This can happen for large CCBs
+       the synchronous ccbApply. This can happen for large CCBs
        and/or with a sluggish PBE. The releaseOn finalize will
        have auto-released the adminOwner on the before-image but
        not on the after image of modify. Corrected here.
@@ -14392,7 +14392,7 @@ bool ImmModel::purgeSyncRequest(SaUint32T clientId) {
       SaInt32T subinv = m_IMMSV_UNPACK_HANDLE_LOW(inv);
       if (subinv < 0) {
         LOG_IN(
-            "Attempt to purge syncronous request for client connection,"
+            "Attempt to purge synchronous request for client connection,"
             "and found an asyncronous admin op request %d for that connection,"
             "ignoring the asyncronous continuation",
             subinv);
@@ -14415,7 +14415,7 @@ bool ImmModel::purgeSyncRequest(SaUint32T clientId) {
   if (ciFound != sAdmReqContinuationMap.end()) {
     sAdmReqContinuationMap.erase(ciFound);
     purged = true;
-    TRACE_5("Purged syncronous Admin-op continuation");
+    TRACE_5("Purged synchronous Admin-op continuation");
   }
 
   ciFound = sSearchReqContinuationMap.end();
@@ -14424,7 +14424,7 @@ bool ImmModel::purgeSyncRequest(SaUint32T clientId) {
     if (ci2->second.mConn == clientId) {
       if (purged || (ciFound != sSearchReqContinuationMap.end())) {
         LOG_WA(
-            "Attempt to purge syncronous search request for client connection,"
+            "Attempt to purge synchronous search request for client 
connection,"
             "but found multiple requests for that connection, "
             "incorrect use of imm handle");
         return false;
@@ -14445,7 +14445,7 @@ bool ImmModel::purgeSyncRequest(SaUint32T clientId) {
     if (ci2->second.mConn == clientId) {
       if (purged || (ciFound != sPbeRtReqContinuationMap.end())) {
         LOG_WA(
-            "Attempt to purge syncronous PRTA request for client connection,"
+            "Attempt to purge synchronous PRTA request for client connection,"
             "but found multiple requests for that connection, "
             "incorrect use of imm handle");
         return false;
@@ -14465,17 +14465,17 @@ bool ImmModel::purgeSyncRequest(SaUint32T clientId) {
         osaf_timespec_compare(&(*i3)->mWaitStartTime, &kZeroSeconds) == 1) {
       SaUint32T ccbId = (*i3)->mId;
 
-      if ((*i3)->mState > IMM_CCB_CRITICAL) {
+      if ((*i3)->mState >= IMM_CCB_CRITICAL) {
         LOG_IN(
-            "Attempt to purge syncronous request for client connection,"
-            "ignoring CCB %u with state > IMM_CCB_CRITICAL",
+            "Attempt to purge synchronous request for client connection,"
+            "ignoring CCB %u with state >= IMM_CCB_CRITICAL",
             ccbId);
         continue;
       }
 
       if (purged || (ccbFound != sCcbVector.end())) {
         LOG_WA(
-            "Attempt to purge syncronous CCB request for client connection,"
+            "Attempt to purge synchronous CCB request for client connection,"
             "but found multiple requests for that connection, "
             "incorrect use of imm handle");
         return false;
-- 
2.18.0


------------------------------------------------------------------------------
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
Opensaf-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to