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
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel