osaf/libs/agents/saf/imma/imma_cb.h | 1 +
osaf/libs/agents/saf/imma/imma_oi_api.c | 2 +-
osaf/libs/agents/saf/imma/imma_om_api.c | 166 ++++++++++++-
osaf/libs/common/immsv/immsv_evt.c | 4 +
osaf/libs/common/immsv/include/immsv_evt.h | 1 +
osaf/libs/saf/include/saImmOm_A_2_14.h | 3 +
osaf/services/saf/immsv/immnd/ImmModel.cc | 167 ++++++++++--
osaf/services/saf/immsv/immnd/ImmModel.hh | 3 +-
osaf/services/saf/immsv/immnd/immnd_evt.c | 73 ++++-
osaf/services/saf/immsv/immnd/immnd_init.h | 4 +-
tests/immsv/implementer/test_SaImmOiCcb.c | 120 ++++++++-
tests/immsv/implementer/test_saImmOiAugmentCcbInitialize.c | 38 ++-
tests/immsv/management/test_saImmOmCcbApply.c | 89 ++++++
tests/immsv/management/test_saImmOmCcbInitialize.c | 4 +
tests/unit_test_fw/src/utest.c | 2 +-
15 files changed, 607 insertions(+), 70 deletions(-)
See ticket or osaf/services/saf/immsv/README for details.
diff --git a/osaf/libs/agents/saf/imma/imma_cb.h
b/osaf/libs/agents/saf/imma/imma_cb.h
--- a/osaf/libs/agents/saf/imma/imma_cb.h
+++ b/osaf/libs/agents/saf/imma/imma_cb.h
@@ -98,6 +98,7 @@ typedef struct imma_ccb_node {
timeout => Ccb-outcome to be
recovered. */
bool mApplied; /* Current mCcbId applied&terminated */
bool mAborted; /* Current mCcbId aborted */
+ bool mValidated; /* Current mCcbId validated */
bool mAugCcb; /* Current and only mCcbId is an augment. */
bool mAugIsTainted;/* AugCcb has tainted root CCB => apply aug or abort
root*/
} IMMA_CCB_NODE;
diff --git a/osaf/libs/agents/saf/imma/imma_oi_api.c
b/osaf/libs/agents/saf/imma/imma_oi_api.c
--- a/osaf/libs/agents/saf/imma/imma_oi_api.c
+++ b/osaf/libs/agents/saf/imma/imma_oi_api.c
@@ -3417,7 +3417,7 @@ SaAisErrorT saImmOiAugmentCcbInitialize(
IMMA_CALLBACK_INFO * cbi=NULL;
SaImmHandleT privateOmHandle = 0LL;
SaImmAdminOwnerHandleT privateAoHandle = 0LL;
- SaVersionT version = {'A', 2, 11};
+ SaVersionT version = {'A', 2, 14};
SaUint32T adminOwnerId = 0;
SaUint32T ccbId = 0;
diff --git a/osaf/libs/agents/saf/imma/imma_om_api.c
b/osaf/libs/agents/saf/imma/imma_om_api.c
--- a/osaf/libs/agents/saf/imma/imma_om_api.c
+++ b/osaf/libs/agents/saf/imma/imma_om_api.c
@@ -54,6 +54,7 @@ static const char *sysaImplName = SA_IMM
static int imma_om_resurrect(IMMA_CB *cb, IMMA_CLIENT_NODE *cl_node, bool
*locked);
static SaAisErrorT imma_finalizeCcb(SaImmCcbHandleT ccbHandle, bool
keepCcbHandleOpen);
+static SaAisErrorT imma_applyCcb(SaImmCcbHandleT ccbHandle, bool onlyValidate);
/****************************************************************************
Name : SaImmOmInitialize
@@ -2873,6 +2874,11 @@ SaAisErrorT saImmOmCcbObjectDelete(SaImm
******************************************************************************/
SaAisErrorT saImmOmCcbApply(SaImmCcbHandleT ccbHandle)
{
+ return imma_applyCcb(ccbHandle, false);
+}
+
+SaAisErrorT imma_applyCcb(SaImmCcbHandleT ccbHandle, bool onlyValidate)
+{
SaAisErrorT rc = SA_AIS_OK;
IMMA_CB *cb = &imma_cb;
IMMSV_EVT evt;
@@ -2924,7 +2930,9 @@ SaAisErrorT saImmOmCcbApply(SaImmCcbHand
ccb-id has been EXPLICITLY applied by the user.
This can only be done by a successful explicit
saImmOmCcbApply. A ccb-handle with an aborted ccb-id
- can not be used any more. Only finalize is allowed on handle.
+ can only be used again after an explcit saImmOmCcbAbort()
has been
+ invoked on the handle. Otherwise only finalize is allowed on
+ the handle.
Setting mApplied to true opens for the IMPLICIT
start of a new ccb-id with the current and same
SaImmCcbHandleT value.
@@ -2949,6 +2957,11 @@ SaAisErrorT saImmOmCcbApply(SaImmCcbHand
goto done;
}
+ if (ccb_node->mValidated && onlyValidate) {
+ rc = SA_AIS_OK; /* Validation is idempotent on clientr side */
+ goto done;
+ }
+
immHandle = ccb_node->mImmHandle;
/* Free string from previous ccb-op */
@@ -2977,9 +2990,20 @@ SaAisErrorT saImmOmCcbApply(SaImmCcbHand
goto done;
}
+ if(onlyValidate && !(cl_node->isImmA2e)) {
+ LOG_IN("ERR_VERSION: saImmOmCcbValidate() only supported in
version A.02.14 or higher");
+ rc = SA_AIS_ERR_VERSION;
+ goto done;
+ }
+
if(ccb_node->mAugCcb) {
- TRACE("Apply for augmentation for CcbId %u", ccb_node->mCcbId);
- ccb_node->mApplied = true;
+ if(onlyValidate) {
+ LOG_IN("ERR_BAD_OPERATION: saImmOmCcbValidate() not
allowed on augmented ccbs");
+ rc = SA_AIS_ERR_BAD_OPERATION;
+ } else {
+ TRACE("Apply for augmentation for CcbId %u",
ccb_node->mCcbId);
+ ccb_node->mApplied = true;
+ }
goto done;
}
@@ -2988,7 +3012,7 @@ SaAisErrorT saImmOmCcbApply(SaImmCcbHand
/* Populate the CcbApply event */
memset(&evt, 0, sizeof(IMMSV_EVT));
evt.type = IMMSV_EVT_TYPE_IMMND;
- evt.info.immnd.type = IMMND_EVT_A2ND_CCB_APPLY;
+ evt.info.immnd.type = (onlyValidate) ? IMMND_EVT_A2ND_CCB_VALIDATE :
IMMND_EVT_A2ND_CCB_APPLY;
evt.info.immnd.info.ccbId = ccb_node->mCcbId;
if((rc = imma_proc_increment_pending_reply(cl_node, true)) !=
SA_AIS_OK) {
@@ -2997,7 +3021,7 @@ SaAisErrorT saImmOmCcbApply(SaImmCcbHand
}
ccb_node->mExclusive = true;
- ccb_node->mApplying = true;
+ ccb_node->mApplying = !onlyValidate;
ccbId = ccb_node->mCcbId;
rc = imma_evt_fake_evs(cb, &evt, &out_evt, cl_node->syncr_timeout,
cl_node->handle, &locked, false);
@@ -3086,7 +3110,8 @@ SaAisErrorT saImmOmCcbApply(SaImmCcbHand
ccb_node->mApplying = false;
osafassert(ccb_node->mErrorStrings == NULL);
if (rc == SA_AIS_OK) {
- ccb_node->mApplied = true;
+ ccb_node->mValidated = true;
+ ccb_node->mApplied = !onlyValidate;
TRACE_1("CCB APPLY - Successful Apply for ccb
id %u",
ccb_node->mCcbId);
} else {
@@ -3184,6 +3209,18 @@ SaAisErrorT saImmOmCcbApply(SaImmCcbHand
we dont want it to indicate aborted, nor applied, nor active.
*/
TRACE_3("client_node %p exposed :%u", cl_node, cl_node ?
(cl_node->exposed) : 0);
+ if(onlyValidate) {
+ /* Let ERR_TIMEOUT reach the user when only validation
was attempted.
+ This means the user does not know if validation
succeeded or not.
+ They can choose to try to apply/commit the ccb which
could succeed if
+ validation did succeed. But if validation failed
then the apply/commit
+ will fail.
+
+ If the validation is still on-going when the attempt
to apply/commit
+ reaches the immsv, then the user should get
TRY_AGAIN from local IMMND.
+ */
+ goto done;
+ }
/* Reset the ccb_node flags back to indicate apply is in
progress. */
ccb_node->mExclusive = true;
@@ -3269,12 +3306,18 @@ SaAisErrorT saImmOmCcbApply(SaImmCcbHand
Description : Aborts a CCB(id) without finalizing the ccb-handle.
Discards any ccb operations currently associated with the
ccb-handle.
- If SA_AIS_OK is returned then ccb-handle can continue to be
used and
- is in the same empty state as if it had just been
initialized.
+ Also resetts a ccbHandle that has previously received the
abort
+ return code SA_AIS_ERR_FAILED_OPERATION.
Previously it was only possible to explicitly abort an
active ccb
by invoking saImOmCcbFinalize() which also closes the
ccb-handle.
+ Previously it was also not possible to reset a ccbHandle
that had
+ received the ccb-aborted return code:
SA_AIS_ERR_FAILED_OPERATION.
+
+ If SA_AIS_OK is returned then ccb-handle can continue to be
used and
+ is in the same empty state as if it had just been
initialized.
+
This a blocking syncronous call.
@@ -3297,6 +3340,52 @@ SaAisErrorT saImmOmCcbAbort(SaImmCcbHand
}
+/****************************************************************************
+ Name : saImmOmCcbValidate
+
+ Description : Performs the validation part of ccb-apply for the CCB in
its
+ current active state. If validation succeeds, then no
additional
+ ccb-operations can be added to the ccb until the current
set of
+ operations have been applied or aborted. An apply of a
successfully
+ validated ccb is highly likely to succeed, but still not
guaranteed
+ to succeed. If an apply of a validated ccb fails, it will
obviously
+ not be due to any failure in validation, but for "physical"
reasons,
+ such as some problem with the PBE (persistent back end), or
a crash
+ of some vital IMM process.
+
+ Thus after a successfull saImmOmCcbVAlidate, the ccb is in
a state
+ that only accepts one of:
+
+ - saImmOmCcbApply(ccbHandle); - Only applicable if
saImmOmCcbValidate
+ returned SA_AIS_OK,
SA_AIS_ERR_TIMEOUT,
+ or SA_AIS_ERR_TRY_AGAIN
(validation not done).
+
+ - saImmOmCcbAbort(ccbHandle); - Always applicable if
handle is valid.
+ - saImmOmCcbFinalize(ccbHandle); - Always applicable if
handle is valid.
+
+ Arguments : ccbHandle - Ccb Handle
+
+ Return Values : Same return values as saImmOmCcbApply with the following
adjustment:
+ SA_AIS_OK - Validation succeeded. Ccb has not been
committed/applied.
+ This ccb can now be aborted or an attempt may
be made to
+ apply/commit.
+
+ Refer to SAI-AIS IMM A.2.1 specification for the other
return values
+ and to the OpenSAF_IMMSv_PR (programmers reference) for
implementation
+ specific details.
+
+ Note that just as for regular saImm*OmCcbApply an abort is
signalled by:
+ SA_AIS_ERR_FAILED_OPERATION - Ccb is aborted possibly due
to failed
+ validation.
+
+
+******************************************************************************/
+SaAisErrorT saImmOmCcbValidate(SaImmCcbHandleT ccbHandle)
+{
+ return imma_applyCcb(ccbHandle, true);
+}
+
+
/****************************************************************************
Name : saImmOmAdminOperationInvoke_2/_o2
@@ -7669,6 +7758,7 @@ static SaAisErrorT imma_finalizeCcb(SaIm
SaUint32T ccbId = 0;
SaImmHandleT immHandle = 0LL;
SaImmAdminOwnerHandleT adminOwnerHdl = 0LL;
+ SaUint32T adminOwnerId = 0;
SaUint32T timeout = 0;
TRACE_ENTER();
@@ -7823,7 +7913,67 @@ static SaAisErrorT imma_finalizeCcb(SaIm
if(keepCcbHandleOpen) { /* saImmOmCcbAbort */
osafassert(ccb_node);
ccb_node->mApplied = true;
+ ccb_node->mAborted = false;
+ ccb_node->mValidated = false;
ccb_node->mExclusive = false;
+
+ /* Fetch cl_node again and generate new ccb_id. We
need to set up
+ a pristine ccb-id to make the ccb-handle identical
to a one just
+ obtained from a saImmOmCcbInitialize.
+ */
+ imma_client_node_get(&cb->client_tree, &immHandle,
&cl_node);
+ if (!(cl_node && cl_node->isOm)) {
+ rc = SA_AIS_ERR_LIBRARY;
+ TRACE_4("ERR_LIBRARY: No valid SaImmHandleT
associated with Ccb");
+ goto done;
+ }
+
+ if (cl_node->stale) {
+ TRACE_1("IMM Handle %llx is stale", immHandle);
+ rc = SA_AIS_OK;
+ imma_ccb_node_delete(cb, ccb_node);
+ ccb_node = NULL;
+ goto done;
+ }
+
+ /* Get the Admin Owner info */
+ imma_admin_owner_node_get(&cb->admin_owner_tree,
&adminOwnerHdl, &ao_node);
+ if (!ao_node) {
+ rc = SA_AIS_ERR_BAD_HANDLE;
+ TRACE_3("ERR_BAD_HANDLE: Amin-Owner node
associated with Ccb is missing");
+ goto done;
+ }
+
+ adminOwnerId = ao_node->mAdminOwnerId;
+
+ if((rc = imma_proc_increment_pending_reply(cl_node,
true)) != SA_AIS_OK) {
+ TRACE_4("ERR_LIBRARY: Overlapping use of IMM
handle by multiple threads");
+ goto done;
+ }
+
+ rc = imma_newCcbId(cb, ccb_node, adminOwnerId, &locked,
cl_node->syncr_timeout);
+ cl_node=NULL;
+ if(rc != SA_AIS_OK) {goto done;}
+ /* ccb_node still valid if rc == SA_AIS_OK. */
+ if(rc == SA_AIS_OK) {
+ osafassert(!(ccb_node->mExclusive));
+ osafassert(locked);
+ }
+
+ imma_client_node_get(&cb->client_tree, &immHandle,
&cl_node);
+ if (!(cl_node && cl_node->isOm)) {
+ rc = SA_AIS_ERR_BAD_HANDLE;
+ TRACE_3("ERR_BAD_HANDLE: Client node not found
after down call");
+ imma_ccb_node_delete(cb, ccb_node); /*Remove
node from tree and free it. */
+ ccb_node = NULL;
+ goto done;
+ }
+
+ imma_proc_decrement_pending_reply(cl_node, true);
+
+ /* Dont care if cl_node is stale here. This will be
caught
+ in the next attempt to use the related handle(s).
+ */
}
}
diff --git a/osaf/libs/common/immsv/immsv_evt.c
b/osaf/libs/common/immsv/immsv_evt.c
--- a/osaf/libs/common/immsv/immsv_evt.c
+++ b/osaf/libs/common/immsv/immsv_evt.c
@@ -172,6 +172,7 @@ static const char *immnd_evt_names[] = {
"IMMND_EVT_A2ND_AUG_ADMO",
"IMMND_EVT_A2ND_CL_TIMEOUT",
"IMMND_EVT_A2ND_ACCESSOR_GET",
+ "IMMND_EVT_A2ND_CCB_VALIDATE", /* saImmOmCcbValidate */
"undefined (high)"
};
@@ -3365,6 +3366,8 @@ static uint32_t immsv_evt_enc_toplevel(I
case IMMND_EVT_A2ND_CCB_APPLY: /* saImmOmCcbApply */
case IMMND_EVT_A2ND_CCB_FINALIZE: /* saImmOmCcbFinalize */
case IMMND_EVT_A2ND_RECOVER_CCB_OUTCOME:
+ case IMMND_EVT_A2ND_CCB_VALIDATE: /* saImmOmCcbValidate */
+
IMMSV_RSRV_SPACE_ASSERT(p8, o_ub, 4);
ncs_encode_32bit(&p8, immndevt->info.ccbId);
ncs_enc_claim_space(o_ub, 4);
@@ -4698,6 +4701,7 @@ static uint32_t immsv_evt_dec_toplevel(N
case IMMND_EVT_A2ND_CCB_APPLY: /* saImmOmCcbApply */
case IMMND_EVT_A2ND_CCB_FINALIZE: /* saImmOmCcbFinalize */
case IMMND_EVT_A2ND_RECOVER_CCB_OUTCOME:
+ case IMMND_EVT_A2ND_CCB_VALIDATE: /* saImmOmCcbValidate */
IMMSV_FLTN_SPACE_ASSERT(p8, local_data, i_ub, 4);
immndevt->info.ccbId = ncs_decode_32bit(&p8);
ncs_dec_skip_space(i_ub, 4);
diff --git a/osaf/libs/common/immsv/include/immsv_evt.h
b/osaf/libs/common/immsv/include/immsv_evt.h
--- a/osaf/libs/common/immsv/include/immsv_evt.h
+++ b/osaf/libs/common/immsv/include/immsv_evt.h
@@ -204,6 +204,7 @@ typedef enum immnd_evt_type {
IMMND_EVT_A2ND_CL_TIMEOUT = 93, /* Inform local IMMND of a library
timeout. */
IMMND_EVT_A2ND_ACCESSOR_GET = 94, /* saImmOmAccessorGet_2 */
+ IMMND_EVT_A2ND_CCB_VALIDATE = 95, /* saImmOmCcbValidate */
IMMND_EVT_MAX
} IMMND_EVT_TYPE;
diff --git a/osaf/libs/saf/include/saImmOm_A_2_14.h
b/osaf/libs/saf/include/saImmOm_A_2_14.h
--- a/osaf/libs/saf/include/saImmOm_A_2_14.h
+++ b/osaf/libs/saf/include/saImmOm_A_2_14.h
@@ -37,6 +37,9 @@ extern "C" {
/* 4.8.x saImmOmCcb */
extern SaAisErrorT
+ saImmOmCcbValidate(SaImmCcbHandleT ccbHandle);
+
+ extern SaAisErrorT
saImmOmCcbAbort(SaImmCcbHandleT ccbHandle);
#ifdef __cplusplus
diff --git a/osaf/services/saf/immsv/immnd/ImmModel.cc
b/osaf/services/saf/immsv/immnd/ImmModel.cc
--- a/osaf/services/saf/immsv/immnd/ImmModel.cc
+++ b/osaf/services/saf/immsv/immnd/ImmModel.cc
@@ -302,12 +302,14 @@ typedef enum {
IMM_CCB_CREATE_OP = 3, //Ongoing create (pending implementer
calls/replies)
IMM_CCB_MODIFY_OP = 4, //Ongoing modify (pending implementer
calls/replies)
IMM_CCB_DELETE_OP = 5, //Ongoing delete (pending implementer
calls/replies)
- IMM_CCB_PREPARE = 6, //Waiting for nodes prepare & completed
calls/replies
- IMM_CCB_CRITICAL = 7, //Unilateral abort no longer allowed (except by
PBE).
- IMM_CCB_PBE_ABORT = 8, //The Persistent back end replied with abort
- IMM_CCB_COMMITTED = 9, //Committed at nodes pending implementer apply
calls
- IMM_CCB_ABORTED = 10, //READY->ABORTED PREPARE->ABORTED
- IMM_CCB_ILLEGAL = 11 //CCB has been removed.
+ IMM_CCB_VALIDATING = 6, //Explicit validate started (saImmOmCcbValidate
only)
+ IMM_CCB_VALIDATED = 7, //Explicit validate has completed
(saImmOmCcbValidate only)
+ IMM_CCB_PREPARE = 8, //Waiting for nodes prepare & completed
calls/replies
+ IMM_CCB_CRITICAL = 9, //Unilateral abort no longer allowed (except by
PBE).
+ IMM_CCB_PBE_ABORT = 10, //The Persistent back end replied with abort
+ IMM_CCB_COMMITTED = 11, //Committed at nodes pending implementer apply
calls
+ IMM_CCB_ABORTED = 12, //READY->ABORTED PREPARE->ABORTED
+ IMM_CCB_ILLEGAL = 13 //CCB has been removed.
} ImmCcbState;
@@ -978,7 +980,8 @@ immModel_ccbApply(IMMND_CB *cb,
SaUint32T* arrSize,
SaUint32T** implConnArr,
SaUint32T** implIdArr,
- SaUint32T** ctnArr)
+ SaUint32T** ctnArr,
+ bool validateOnly)
{
ConnVector cv;
IdVector implsv;
@@ -990,7 +993,7 @@ immModel_ccbApply(IMMND_CB *cb,
SaAisErrorT err = ImmModel::instance(&cb->immModel)->
- ccbApply(ccbId, reqConn, cv, implsv, ctnv);
+ ccbApply(ccbId, reqConn, cv, implsv, ctnv, validateOnly);
*arrSize = (SaUint32T) cv.size();
if(*arrSize) {
@@ -4322,20 +4325,32 @@ ImmModel::ccbResult(SaUint32T ccbId)
case IMM_CCB_CREATE_OP:
case IMM_CCB_MODIFY_OP:
case IMM_CCB_DELETE_OP:
- LOG_WA("ccbResult: CCB %u is active! state:%u.", ccbId,
(*i)->mState);
+ LOG_WA("ccbResult: CCB %u is active, state:%u.", ccbId,
(*i)->mState);
err = SA_AIS_ERR_TRY_AGAIN;
- break; //Unusual
+ break;
case IMM_CCB_PREPARE:
- LOG_WA("ccbResult: CCB %u in prepare! Commit/abort in
progress?",
+ LOG_WA("ccbResult: CCB %u in state 'prepare' validation in
progress",
ccbId);
err = SA_AIS_ERR_TRY_AGAIN;
- break; //Unusual
+ break;
+
+ case IMM_CCB_VALIDATING:
+ LOG_WA("ccbResult: CCB %u in state 'validating' explicit
validation in progress",
+ ccbId);
+ err = SA_AIS_ERR_TRY_AGAIN;
+ break;
+
+ case IMM_CCB_VALIDATED:
+ LOG_WA("ccbResult: CCB %u in state 'validated'. Waiting for
apply or abort/finalize",
+ ccbId);
+ err = SA_AIS_ERR_TRY_AGAIN;
+ break;
case IMM_CCB_CRITICAL:
- LOG_NO("ccbResult: CCB %u in critical state! Commit/apply in
progress?", ccbId);
+ LOG_NO("ccbResult: CCB %u in critical state! Commit/apply in
progress", ccbId);
err = SA_AIS_ERR_TRY_AGAIN;
- break; //Can happen if PBE crashes.
+ break; //Can be here if PBE is crashed, hung on fs, or
backloged.
default:
LOG_ER("ccbResult: Illegal state %u in ccb %u", (*i)->mState,
ccbId);
@@ -4505,11 +4520,16 @@ ImmModel::ccbApply(SaUint32T ccbId,
SaUint32T reqConn,
ConnVector& connVector,
IdVector& implIds,
- IdVector& continuations)
+ IdVector& continuations,
+ bool validateOnly)
{
SaAisErrorT err = SA_AIS_OK;
TRACE_ENTER();
- TRACE_5("APPLYING CCB ID:%u", ccbId);
+ if(validateOnly) {
+ TRACE_5("Explicit VALIDATE started for CCB ID:%u", ccbId);
+ } else {
+ TRACE_5("APPLYING CCB ID:%u", ccbId);
+ }
CcbVector::iterator i;
AdminOwnerVector::iterator i2;
@@ -4530,10 +4550,41 @@ ImmModel::ccbApply(SaUint32T ccbId,
ccb->mAdminOwnerId);
ccb->mVeto = SA_AIS_ERR_BAD_HANDLE;
} else if(ccb->mState > IMM_CCB_READY) {
- LOG_NO("Ccb <%u> not in correct state (%u) for Apply ignoring
request",
- ccb->mId, ccb->mState);
- err = SA_AIS_ERR_ACCESS_DENIED;
- goto ignore;
+ if(ccb->mState == IMM_CCB_VALIDATING) {
+ LOG_IN("Ccb <%u> in incorrect state 'CCB_VALIDATING for "
+ "saImmOmCcbValidate() ignoring request", ccb->mId);
+ err = SA_AIS_ERR_ACCESS_DENIED;
+ goto done;
+ } else if(ccb->mState == IMM_CCB_VALIDATED) {
+ if(validateOnly) {
+ LOG_IN("Ccb <%u> in incorrect state 'CCB_VALIDATED for "
+ "saImmOmCcbValidate() ignoring request", ccb->mId);
+ err = SA_AIS_ERR_ACCESS_DENIED;
+ goto done;
+ } else {
+ LOG_IN("Ccb <%u> in state (IMM_CCB_VALIDATED) received
apply/commit",
+ ccb->mId);
+ err = ccb->mVeto;
+ if(err == SA_AIS_OK) {
+ if(!ccb->mImplementers.empty()) {
+ /* apply callback needs to be sent to
implementers. */
+ err = SA_AIS_ERR_INTERRUPT;
+ }
+ }
+ goto done;
+ }
+
+ } else {
+ LOG_NO("Ccb <%u> not in correct state (%u) for Apply ignoring
request",
+ ccb->mId, ccb->mState);
+ /* This includes state IMM_CCB_VALIDATING which means explicit
validation
+ is in progress. Neihter a redundant saImmOmValidate(), nor
a premature
+ saImmOmCcbApply() can be accepted in this state. But a
saImmOmCcbAbort()
+ or a saImmOmCcbFinalize would be accepted.
+ */
+ err = SA_AIS_ERR_ACCESS_DENIED;
+ goto done;
+ }
}
osafassert(reqConn==0 || (ccb->mOriginatingConn == reqConn));
@@ -4550,12 +4601,21 @@ ImmModel::ccbApply(SaUint32T ccbId,
}
err = SA_AIS_ERR_FAILED_OPERATION;
ccb->mVeto = SA_AIS_ERR_FAILED_OPERATION;
- } else if(validateNoDanglingRefs(ccb)) {
+ } else if(!validateNoDanglingRefs(ccb)) {
+ err = SA_AIS_ERR_FAILED_OPERATION;
+ ccb->mVeto = SA_AIS_ERR_FAILED_OPERATION;
+ } else {
/* sMissingParents must be empty if err is SA_AIS_OK */
osafassert(sMissingParents.empty());
- TRACE_5("Apply CCB %u", ccb->mId);
- ccb->mState = IMM_CCB_PREPARE;
+ if(validateOnly) {
+ TRACE_5("Validate CCB %u", ccb->mId);
+ ccb->mState = IMM_CCB_VALIDATING;
+ } else {
+ TRACE_5("Apply CCB %u", ccb->mId);
+ ccb->mState = IMM_CCB_PREPARE;
+ }
+
CcbImplementerMap::iterator isi;
for(isi = ccb->mImplementers.begin();
isi != ccb->mImplementers.end();
@@ -4600,11 +4660,9 @@ ImmModel::ccbApply(SaUint32T ccbId,
continuations.push_back(sLastContinuationId);
}
}
- } else {
- err = SA_AIS_ERR_FAILED_OPERATION;
- }
- }
- ignore:
+ }
+ }
+ done:
TRACE_LEAVE();
return err;
@@ -4972,8 +5030,9 @@ ImmModel::ccbCommit(SaUint32T ccbId, Con
if(ccb->mState == IMM_CCB_PREPARE) {
ccb->mState = IMM_CCB_CRITICAL;
} else {
+ TRACE_5("Ccb %u comitted by PBE now in state:%u", ccbId, ccb->mState);
osafassert(ccb->mState == IMM_CCB_CRITICAL);
- TRACE_5("Ccb %u comitted by persistent back end", ccbId);
+ TRACE_5("Comitting Ccb %u in IMMND", ccbId);
}
ccb->mWaitStartTime = 0;
@@ -5096,7 +5155,13 @@ ImmModel::ccbAbort(SaUint32T ccbId, Conn
break;
case IMM_CCB_PREPARE:
- LOG_NO("Ccb %u aborted in COMPLETED processing", ccbId);
+ case IMM_CCB_VALIDATING:
+ LOG_NO("Ccb %u aborted in COMPLETED processing (validation)",
ccbId);
+ *client = ccb->mOriginatingConn;
+ break;
+
+ case IMM_CCB_VALIDATED:
+ LOG_NO("Ccb %u aborted after explicit validation", ccbId);
*client = ccb->mOriginatingConn;
break;
@@ -5232,12 +5297,18 @@ ImmModel::ccbTerminate(SaUint32T ccbId)
return SA_AIS_ERR_TRY_AGAIN;
case IMM_CCB_PREPARE:
+ case IMM_CCB_VALIDATING:
case IMM_CCB_PBE_ABORT:
LOG_WA("Will not terminate ccb %u while waiting for "
"replies from implementers on completed ack", ccbId);
TRACE_LEAVE();
return SA_AIS_ERR_TRY_AGAIN;
+ case IMM_CCB_VALIDATED: /* Could logically be allowed, but prefer
propper cleanup */
+ LOG_NO("Will not terminate ccb %u in validated state, should
be aborted first", ccbId);
+ TRACE_LEAVE();
+ return SA_AIS_ERR_TRY_AGAIN;
+
case IMM_CCB_CRITICAL:
LOG_WA("Will not terminate ccb %u in critical state ", ccbId);
TRACE_LEAVE();
@@ -5467,6 +5538,8 @@ ImmModel::ccbAugmentInit(immsv_oi_ccb_up
case IMM_CCB_COMMITTED:
case IMM_CCB_ABORTED:
case IMM_CCB_PREPARE:
+ case IMM_CCB_VALIDATING:
+ case IMM_CCB_VALIDATED:
case IMM_CCB_PBE_ABORT:
case IMM_CCB_CRITICAL:
LOG_ER("Ccb Augment attempted in wrong CCB state");
@@ -8498,6 +8571,27 @@ ImmModel::ccbWaitForCompletedAck(SaUint3
will force attempts to recover ccb-outcome from the current PBE.
*/
+ if(ccb->mState == IMM_CCB_VALIDATING) {
+ /* Explicit validation (saImmOmCcbValidate) stop waiting. */
+ ccb->mState = IMM_CCB_VALIDATED;
+ TRACE_5("Explicit validation completed err state:%u for ccb:%u", *err,
ccbId);
+ if((*err) == SA_AIS_OK) {
+ /* We interrupt the validate/apply after validation is completed
and before
+ the commit phase of hte apply.
+ */
+ *err = SA_AIS_ERR_INTERRUPT;
+ }
+
+ return false;
+ }
+
+ if((ccb->mState == IMM_CCB_VALIDATED) && ((*err) == SA_AIS_OK)) {
+ TRACE("Continuing apply/commit for explicitly validated ccb:%u err
state:%u", ccbId, *err);
+ TRACE("Dont think we ever get here.");
+ LOG_IN("GOING FROM IMM_CCB_VALIDATED to IMM_CCB_PREPARE Ccb:%u",
ccbId);
+ ccb->mState = IMM_CCB_PREPARE;
+ }
+
if(ccb->mState == IMM_CCB_CRITICAL) {
/* This must be the PBE reply. Stop waiting. */
TRACE_5("PBE replied with rc:%u for ccb:%u", *err, ccbId);
@@ -8684,6 +8778,7 @@ ImmModel::ccbCompletedContinuation(immsv
SaUint32T ccbId = rsp->ccbId;
CcbInfo* ccb = 0;
CcbVector::iterator i1;
+ CcbImplementerMap::iterator ix;
i1 = std::find_if(sCcbVector.begin(), sCcbVector.end(), CcbIdIs(ccbId));
if(i1 == sCcbVector.end() || (!(*i1)->isActive()) ) {
@@ -8692,9 +8787,14 @@ ImmModel::ccbCompletedContinuation(immsv
return;
}
ccb = *i1;
-
- CcbImplementerMap::iterator ix =
- ccb->mImplementers.find(rsp->implId);
+
+ if(ccb->mState == IMM_CCB_VALIDATED) {
+ LOG_IN("GOING FROM IMM_CCB_VALIDATED to IMM_CCB_PREPARE Ccb:%u",
ccbId);
+ ccb->mState = IMM_CCB_PREPARE;
+ goto done;
+ }
+
+ ix = ccb->mImplementers.find(rsp->implId);
if(ix == ccb->mImplementers.end()) {
if((ccb->mVeto == SA_AIS_OK) && (ccb->mState < IMM_CCB_CRITICAL)) {
LOG_WA("Completed continuation: implementer '%u' Not found "
@@ -8789,6 +8889,7 @@ ImmModel::ccbCompletedContinuation(immsv
}
}
}
+ done:
TRACE_LEAVE();
}
diff --git a/osaf/services/saf/immsv/immnd/ImmModel.hh
b/osaf/services/saf/immsv/immnd/ImmModel.hh
--- a/osaf/services/saf/immsv/immnd/ImmModel.hh
+++ b/osaf/services/saf/immsv/immnd/ImmModel.hh
@@ -176,7 +176,8 @@ public:
SaUint32T reqConn,
ConnVector& connVector,
IdVector& implIds,
- IdVector& continuations);
+ IdVector& continuations,
+ bool validateOnly);
SaAisErrorT ccbTerminate(SaUint32T ccbId);
diff --git a/osaf/services/saf/immsv/immnd/immnd_evt.c
b/osaf/services/saf/immsv/immnd/immnd_evt.c
--- a/osaf/services/saf/immsv/immnd/immnd_evt.c
+++ b/osaf/services/saf/immsv/immnd/immnd_evt.c
@@ -167,9 +167,8 @@ static void immnd_evt_pbe_admop_rsp(IMMN
static void immnd_evt_proc_object_sync(IMMND_CB *cb,
IMMND_EVT *evt, SaBoolT originatedAtThisNd, SaImmHandleT clnt_hdl,
MDS_DEST reply_dest, SaUint64T msgNo);
-static void immnd_evt_proc_ccb_apply(IMMND_CB *cb,
- IMMND_EVT *evt,
- SaBoolT originatedAtThisNd, SaImmHandleT
clnt_hdl, MDS_DEST reply_dest);
+static void immnd_evt_proc_ccb_apply(IMMND_CB *cb, IMMND_EVT *evt, SaBoolT
originatedAtThisNd,
+ SaImmHandleT clnt_hdl, MDS_DEST
reply_dest, SaBoolT validateOnly);
static void immnd_evt_proc_ccb_compl_rsp(IMMND_CB *cb,
IMMND_EVT *evt,
@@ -3053,6 +3052,7 @@ static SaAisErrorT immnd_fevs_local_chec
break;
case IMMND_EVT_A2ND_CCB_APPLY:
+ case IMMND_EVT_A2ND_CCB_VALIDATE:
if(immModel_pbeNotWritable(cb)) {
/* NO_RESOURCES is here imm internal proxy for
TRY_AGAIN.
The library code for saImmOmCcbApply will translate
NO_RESOURCES
@@ -3652,8 +3652,9 @@ static void immnd_evt_proc_ccb_compl_rsp
reqConn = 0; /* Ensure we dont reply to OM client yet.
*/
}
} else {
- TRACE("Finished waiting for completed Acks from implementers
(and PBE)");
+ bool validateOnly = false;
if (err == SA_AIS_OK) { /*Proceed with commit */
+ TRACE("Finished waiting for completed Acks from
implementers (and PBE)");
/*If we arrive here, the assumption is that all
implementors have agreed
to commit and all immnds are prepared to commit this
ccb. Fevs must
guarantee that all have seen the same replies from
implementers.
@@ -3786,10 +3787,18 @@ static void immnd_evt_proc_ccb_compl_rsp
free(applConnArr);
applConnArr = NULL;
}
- } else { /*err != SA_AIS_OK => generate
SaImmOiCcbAbortCallbackT upcall
- for all local implementers involved in the
Ccb */
+ } else if (err == SA_AIS_ERR_INTERRUPT) {
+ /* ERR_INTERRUPT => validateOnly. */
+ TRACE("Explicit validation finished OK with
completed Acks from OIs "
+ "(not includingPBE)");
+
+ err = SA_AIS_OK;
+ validateOnly = true;
+ } else {
errStrings = immModel_ccbGrabErrStrings(cb,
evt->info.ccbUpcallRsp.ccbId);
TRACE("Abort in immnd_evt_proc_ccb_compl_rsp reqConn:
%u", reqConn);
+ /*err != SA_AIS_OK => generate SaImmOiCcbAbortCallbackT
upcall
+ for all local implementers involved in the
Ccb */
immnd_evt_ccb_abort(cb, evt->info.ccbUpcallRsp.ccbId,
NULL);
}
/* Either commit or abort has been decided. Ccb is now done.
@@ -3799,8 +3808,8 @@ static void immnd_evt_proc_ccb_compl_rsp
*/
if (reqConn) {
+
SaImmHandleT tmp_hdl = m_IMMSV_PACK_HANDLE(reqConn,
cb->node_id);
-
immnd_client_node_get(cb, tmp_hdl, &cl_node);
if (cl_node == NULL || cl_node->mIsStale) {
LOG_WA("IMMND - Client went down so no
response");
@@ -3828,7 +3837,10 @@ static void immnd_evt_proc_ccb_compl_rsp
}
immsv_evt_free_attrNames(send_evt.info.imma.info.errRsp.errStrings);
}
+
finalize_ccb:
+ if(validateOnly) { goto done;}
+
TRACE_2("CCB COMPLETED: TERMINATING CCB:%u",
evt->info.ccbUpcallRsp.ccbId);
err = immModel_ccbFinalize(cb, evt->info.ccbUpcallRsp.ccbId);
if (err != SA_AIS_OK) {
@@ -3836,6 +3848,7 @@ static void immnd_evt_proc_ccb_compl_rsp
/* There is really not much we can do here. */
}
}
+ done:
TRACE_LEAVE();
}
@@ -7066,12 +7079,12 @@ static void immnd_evt_proc_ccb_finalize(
* IMM_DEST reply_dest - The dest of the ND to where reply
* is to be sent (only relevant if
* originatedAtThisNode is false).
+ * SaBoolT validateOnly - SA_TRUE => only do validation, not
commit/apply.
* Return Values : None
*
*****************************************************************************/
-static void immnd_evt_proc_ccb_apply(IMMND_CB *cb,
- IMMND_EVT *evt,
- SaBoolT originatedAtThisNd, SaImmHandleT
clnt_hdl, MDS_DEST reply_dest)
+static void immnd_evt_proc_ccb_apply(IMMND_CB *cb, IMMND_EVT *evt, SaBoolT
originatedAtThisNd,
+ SaImmHandleT clnt_hdl, MDS_DEST
reply_dest, SaBoolT validateOnly)
{
SaAisErrorT err = SA_AIS_OK;
IMMSV_EVT send_evt;
@@ -7118,11 +7131,11 @@ static void immnd_evt_proc_ccb_apply(IMM
}
err = immModel_ccbApply(cb, evt->info.ccbId, originatedAtThisNd ? conn
: 0,
- &arrSize, &implConnArr, &implIdArr, &ctnArr);
+ &arrSize, &implConnArr, &implIdArr, &ctnArr, validateOnly);
if (err == SA_AIS_OK) {
if (arrSize) {
- TRACE_2("THERE ARE LOCAL IMPLEMENTERS in ccb:%u",
evt->info.ccbId);
+ TRACE_2("THERE ARE LOCAL IMPLEMENTERS in ccb:%u sending
completed upcall", evt->info.ccbId);
delayedReply = SA_TRUE;
memset(&send_evt, '\0', sizeof(IMMSV_EVT));
send_evt.type = IMMSV_EVT_TYPE_IMMA;
@@ -7203,6 +7216,7 @@ static void immnd_evt_proc_ccb_apply(IMM
}
} else {
TRACE_2("NO IMPLEMENTERS AT ALL AND NO PBE. for ccb:%u
err:%u sz:%u", evt->info.ccbId, err, arrSize);
+ TRACE("delayedReply:%u", delayedReply);
}
}
/* err != SA_AIS_OK or no implementers => immediate reply. */
@@ -7222,6 +7236,35 @@ static void immnd_evt_proc_ccb_apply(IMM
/*REPLY can not be sent immediately if there are implementers or PBE.
Must wait for prepare votes. */
if (!delayedReply) {
+ if (err == SA_AIS_ERR_INTERRUPT) {
+ /* ERR_INTERUPT is an IMMND internal error code
indicating
+ that this was etiher a saImmOmCcbValidate that is now
+ complete, i.e. we need to interrupt and return
without
+ continuing with the commit/apply part. Or it was an
+ saImmOmCcbApply continuting such interrupted
processing,
+ i.e. we must here skip sending completed callbacks
(validation)
+ since this is done already for this ccb.
+ */
+ err = SA_AIS_OK;
+ if(validateOnly) {
+ TRACE("Explicit validation finished OK");
+ goto immediate_reply;
+ } else {
+ /* Fake continuation of end of validation.
+ To avoid writing large ammounts of new code
almost
+ identical to existing, we fake a reply from
a non existent
+ OI on a final completed callback. This is
what would trigger
+ the commit/apply of a normal CCB.
+ */
+ memset(&send_evt, '\0', sizeof(IMMSV_EVT));
+ send_evt.type = IMMSV_EVT_TYPE_IMMND;
+ send_evt.info.immnd.type =
IMMND_EVT_A2ND_CCB_COMPLETED_RSP;
+ send_evt.info.immnd.info.ccbUpcallRsp.ccbId =
evt->info.ccbId;
+ immnd_evt_proc_ccb_compl_rsp(cb,
&(send_evt.info.immnd), originatedAtThisNd, clnt_hdl, reply_dest);
+ goto done;
+ }
+ }
+
if (err == SA_AIS_OK) {
/*No implementers anywhere and all is OK */
/* Check for appliers. */
@@ -7538,7 +7581,11 @@ immnd_evt_proc_fevs_dispatch(IMMND_CB *c
break;
case IMMND_EVT_A2ND_CCB_APPLY:
- immnd_evt_proc_ccb_apply(cb, &frwrd_evt.info.immnd,
originatedAtThisNd, clnt_hdl, reply_dest);
+ immnd_evt_proc_ccb_apply(cb, &frwrd_evt.info.immnd,
originatedAtThisNd, clnt_hdl, reply_dest, SA_FALSE);
+ break;
+
+ case IMMND_EVT_A2ND_CCB_VALIDATE:
+ immnd_evt_proc_ccb_apply(cb, &frwrd_evt.info.immnd,
originatedAtThisNd, clnt_hdl, reply_dest, SA_TRUE);
break;
case IMMND_EVT_A2ND_CCB_FINALIZE:
diff --git a/osaf/services/saf/immsv/immnd/immnd_init.h
b/osaf/services/saf/immsv/immnd/immnd_init.h
--- a/osaf/services/saf/immsv/immnd/immnd_init.h
+++ b/osaf/services/saf/immsv/immnd/immnd_init.h
@@ -140,8 +140,8 @@ extern "C" {
SaAisErrorT
immModel_ccbApply(IMMND_CB *cb,
SaUint32T ccbId,
- SaUint32T replyConn,
- SaUint32T *arrSize, SaUint32T **implConnArr,
SaUint32T **implIdArr, SaUint32T **ctnArr);
+ SaUint32T replyConn, SaUint32T *arrSize,
SaUint32T **implConnArr,
+ SaUint32T **implIdArr, SaUint32T **ctnArr, bool
validateOnly);
bool immModel_ccbAbort(IMMND_CB *cb,
SaUint32T ccbId, SaUint32T *arrSize, SaUint32T **implConnArr,
SaUint32T *client,
diff --git a/tests/immsv/implementer/test_SaImmOiCcb.c
b/tests/immsv/implementer/test_SaImmOiCcb.c
--- a/tests/immsv/implementer/test_SaImmOiCcb.c
+++ b/tests/immsv/implementer/test_SaImmOiCcb.c
@@ -260,7 +260,7 @@ static void *classImplementerThreadMain(
return NULL;
}
-static SaAisErrorT om_ccb_exec(void)
+static SaAisErrorT om_ccb_exec(unsigned int control)
{
SaAisErrorT rc;
SaImmHandleT handle;
@@ -293,7 +293,29 @@ static SaAisErrorT om_ccb_exec(void)
if ((rc = saImmOmCcbObjectCreate_2(ccbHandle, configClassName, &rootObj,
attrValues)) != SA_AIS_OK)
goto done;
- safassert(saImmOmCcbApply(ccbHandle), SA_AIS_OK);
+ switch(control) {
+
+ case 0:
+ safassert(saImmOmCcbApply(ccbHandle), SA_AIS_OK);
+ break;
+
+ case 1: safassert(saImmOmCcbValidate(ccbHandle), SA_AIS_OK);
+ safassert(saImmOmCcbApply(ccbHandle), SA_AIS_OK);
+ break;
+
+ case 2: safassert(saImmOmCcbValidate(ccbHandle), SA_AIS_OK);
+ safassert(saImmOmCcbAbort(ccbHandle), SA_AIS_OK);
+ break;
+
+ case 3: safassert(saImmOmCcbValidate(ccbHandle),
SA_AIS_ERR_FAILED_OPERATION);
+ safassert(saImmOmCcbAbort(ccbHandle), SA_AIS_OK);
+ break;
+
+
+
+ default:
+ TRACE("Incorrect control parameter:%u to om_ccb_exec",
control);
+ }
done:
if(rc != SA_AIS_OK) {
@@ -392,7 +414,7 @@ static void saImmOiCcb_01(void)
assert(res == 0);
sleep(1); /* Race condition, allow implementer threads to set up !*/
- rc = om_ccb_exec();
+ rc = om_ccb_exec(0);
pthread_join(thread[0], NULL);
pthread_join(thread[1], NULL);
@@ -419,7 +441,7 @@ static void saImmOiCcb_02(void)
saImmOiCcbObjectDeleteCallback_response = SA_AIS_ERR_BAD_OPERATION;
sleep(1); /* Race condition, allow implementer threads to set up!*/
- rc = om_ccb_exec();
+ rc = om_ccb_exec(0);
pthread_join(thread[0], NULL);
pthread_join(thread[1], NULL);
@@ -453,7 +475,7 @@ static void saImmOiCcb_03(void)
assert(res == 0);
sleep(1); /* Race condition, allow implementer threads to set up!*/
- rc = om_ccb_exec();
+ rc = om_ccb_exec(0);
pthread_join(thread[0], NULL);
@@ -477,7 +499,7 @@ static void saImmOiCcb_04(void)
saImmOiCcbObjectModifyCallback_response = SA_AIS_ERR_BAD_OPERATION;
sleep(1); /* Race condition, allow implementer threads to set up!*/
- rc = om_ccb_exec();
+ rc = om_ccb_exec(0);
pthread_join(threadid, NULL);
@@ -516,7 +538,7 @@ static void saImmOiCcb_05(void)
/* Set saveErrorStrings to 1 and save error strings in om_ccb_exec() */
returnErrorStrings = NULL;
saveErrorStrings = 1;
- rc = om_ccb_exec();
+ rc = om_ccb_exec(0);
saveErrorStrings = 0;
/* There is at least one error string */
@@ -549,6 +571,87 @@ static void saImmOiCcb_05(void)
TRACE_LEAVE();
}
+static void saImmOiCcb_06(void)
+{
+ int res;
+ pthread_t thread[2];
+
+ TRACE_ENTER();
+ om_setup();
+
+ /* Create implementer threads */
+ res = pthread_create(&thread[0], NULL, objectImplementerThreadMain,
&dnObj1);
+ assert(res == 0);
+ res = pthread_create(&thread[1], NULL, objectImplementerThreadMain,
&dnObj2);
+ assert(res == 0);
+
+ sleep(1); /* Race condition, allow implementer threads to set up !*/
+ rc = om_ccb_exec(1);
+
+ pthread_join(thread[0], NULL);
+ pthread_join(thread[1], NULL);
+
+ test_validate(rc, SA_AIS_OK);
+
+ om_teardown();
+ TRACE_LEAVE();
+}
+
+static void saImmOiCcb_07(void)
+{
+ int res;
+ pthread_t thread[2];
+
+ TRACE_ENTER();
+ om_setup();
+
+ /* Create implementer threads */
+ res = pthread_create(&thread[0], NULL, objectImplementerThreadMain,
&dnObj1);
+ assert(res == 0);
+ res = pthread_create(&thread[1], NULL, objectImplementerThreadMain,
&dnObj2);
+ assert(res == 0);
+
+ sleep(1); /* Race condition, allow implementer threads to set up !*/
+ rc = om_ccb_exec(2);
+
+ pthread_join(thread[0], NULL);
+ pthread_join(thread[1], NULL);
+
+ test_validate(rc, SA_AIS_OK);
+
+ om_teardown();
+ TRACE_LEAVE();
+}
+
+static void saImmOiCcb_08(void)
+{
+ int res;
+ pthread_t thread[2];
+
+ TRACE_ENTER();
+ om_setup();
+
+ /* Create implementer threads */
+ res = pthread_create(&thread[0], NULL, objectImplementerThreadMain,
&dnObj1);
+ assert(res == 0);
+ res = pthread_create(&thread[1], NULL, objectImplementerThreadMain,
&dnObj2);
+ assert(res == 0);
+
+ saImmOiCcbObjectDeleteCallback_response = SA_AIS_ERR_BAD_OPERATION;
+ sleep(1); /* Race condition, allow implementer threads to set up!*/
+ rc = om_ccb_exec(3);
+
+ pthread_join(thread[0], NULL);
+ pthread_join(thread[1], NULL);
+
+ test_validate(rc, SA_AIS_ERR_FAILED_OPERATION);
+
+ om_teardown();
+ saImmOiCcbObjectDeleteCallback_response = SA_AIS_OK;
+ TRACE_LEAVE();
+}
+
+
__attribute__ ((constructor)) static void saImmOiCcb_constructor(void)
{
dnObj1.length = (SaUint16T) sprintf((char*) dnObj1.value, "%s,%s",
rdnObj1.value, rootObj.value);
@@ -561,5 +664,8 @@ static void saImmOiCcb_05(void)
test_case_add(4, saImmOiCcb_03, "saImmOiCcb - SA_AIS_OK - 1
classImplementer thread");
test_case_add(4, saImmOiCcb_04, "saImmOiCcb -
SA_AIS_ERR_BAD_OPERATION/FAILED_OPERATION - 1 classImplementer thread");
test_case_add(4, saImmOiCcb_05, "saImmOiCcb -
SA_AIS_ERR_BAD_OPERATION/FAILED_OPERATION - saImmOiCcbSetErrorString and
saImmOmCcbGetErrorStrings");
+ test_case_add(4, saImmOiCcb_06, "saImmOiCcb - SA_AIS_OK -
saImmOmCcbValidate followed by saImmOmCcbApply");
+ test_case_add(4, saImmOiCcb_07, "saImmOiCcb - SA_AIS_OK -
saImmOmCcbValidate followed by saImmOmCcbAbort");
+ test_case_add(4, saImmOiCcb_08, "saImmOiCcb - SA_AIS_ERR_FAILED_OPERATION
- saImmOmCcbValidate (OI reports error) followed by saImmOmCcbAbort");
}
diff --git a/tests/immsv/implementer/test_saImmOiAugmentCcbInitialize.c
b/tests/immsv/implementer/test_saImmOiAugmentCcbInitialize.c
--- a/tests/immsv/implementer/test_saImmOiAugmentCcbInitialize.c
+++ b/tests/immsv/implementer/test_saImmOiAugmentCcbInitialize.c
@@ -30,6 +30,8 @@ typedef struct ImmThreadArg {
static int objectDispatchThreadIsSet = 0;
static int classDispatchThreadIsSet = 0;
static int useAdminOwner = 0;
+static int testValidate = 0;
+static SaAisErrorT globalRc = SA_AIS_OK;
static const SaNameT rdnObj1 = {sizeof("Obj1"), "Obj1"};
static const SaNameT rdnObj2 = {sizeof("Obj2"), "Obj2"};
@@ -229,9 +231,14 @@ static SaAisErrorT saImmOiAugCcbObjectMo
callbackCounter++;
safassert(saImmOiAugmentCcbInitialize(immOiHandle, ccbId, &ccbHandle,
&ownerHandle), SA_AIS_OK);
if(useAdminOwner)
- safassert(saImmOmAdminOwnerSet(ownerHandle, objectNames, SA_IMM_ONE),
SA_AIS_OK);
- if((rc = saImmOmCcbObjectModify_2(ccbHandle, &rdnObj2, attrMods)) ==
SA_AIS_OK)
- rc = saImmOmCcbApply(ccbHandle);
+ safassert(saImmOmAdminOwnerSet(ownerHandle, objectNames, SA_IMM_ONE),
SA_AIS_OK);
+ if((rc = saImmOmCcbObjectModify_2(ccbHandle, &rdnObj2, attrMods)) ==
SA_AIS_OK) {
+ if(testValidate) {
+ globalRc = saImmOmCcbValidate(ccbHandle);
+ } //else {
+ rc = saImmOmCcbApply(ccbHandle);
+ //}
+ }
TRACE_LEAVE2();
return rc;
}
@@ -523,7 +530,9 @@ static void saImmOiCcbAugmentInitialize_
done:
pthread_join(threadid, NULL);
- test_validate(rc, SA_AIS_OK);
+ if(!testValidate) {
+ test_validate(rc, SA_AIS_OK);
+ }
safassert(saImmOmCcbFinalize(ccbHandle), SA_AIS_OK);
safassert(saImmOmAdminOwnerFinalize(ownerHandle), SA_AIS_OK);
@@ -711,6 +720,26 @@ done:
TRACE_LEAVE();
}
+static void saImmOiCcbAugmentInitialize_05(void)
+{
+ /*
+ SaImmHandleT handle;
+ ImmThreadArg arg;
+ const SaImmAdminOwnerNameT adminOwnerName = (SaImmAdminOwnerNameT)
__FILE__;
+ SaImmAdminOwnerHandleT ownerHandle;
+ const SaNameT *objectNames[] = { &rdnObj1, &rdnObj2, NULL };
+ SaImmCcbHandleT ccbHandle;
+ SaAisErrorT rc;
+ pthread_t threadid;
+ */
+ TRACE_ENTER();
+
+ testValidate = 1;
+ saImmOiCcbAugmentInitialize_02();
+ test_validate(globalRc, SA_AIS_ERR_BAD_OPERATION);
+
+ TRACE_LEAVE();
+}
__attribute__ ((constructor)) static void
saImmOiCcbAugmentInitialize_constructor(void)
{
@@ -719,5 +748,6 @@ done:
test_case_add(6, saImmOiCcbAugmentInitialize_02,
"saImmOiCcbAugmentInitialize - SA_AIS_OK - one object implementer: modify,
delete");
test_case_add(6, saImmOiCcbAugmentInitialize_03,
"saImmOiCcbAugmentInitialize - SA_AIS_OK - two object implementers: modify,
delete");
test_case_add(6, saImmOiCcbAugmentInitialize_04,
"saImmOiCcbAugmentInitialize - SA_AIS_OK - two object implementers: modify and
delete with saImmOmAdminOwnerSet");
+ test_case_add(6, saImmOiCcbAugmentInitialize_05,
"saImmOiCcbAugmentInitialize - SA_AIS_ERR_BAD_OPERATION - saImmOmValidate not
allowed in augmentation");
}
diff --git a/tests/immsv/management/test_saImmOmCcbApply.c
b/tests/immsv/management/test_saImmOmCcbApply.c
--- a/tests/immsv/management/test_saImmOmCcbApply.c
+++ b/tests/immsv/management/test_saImmOmCcbApply.c
@@ -16,6 +16,7 @@
*/
#include "immtest.h"
+#include <unistd.h>
void saImmOmCcbApply_01(void)
{
@@ -189,3 +190,91 @@ done:
TRACE_LEAVE();
}
+void saImmOmCcbValidate_01(void)
+{
+ TRACE_ENTER();
+ const SaImmAdminOwnerNameT adminOwnerName = (SaImmAdminOwnerNameT)
__FUNCTION__;
+ SaImmAdminOwnerHandleT ownerHandle;
+ SaImmCcbHandleT ccbHandle;
+ SaNameT rdn = {strlen("Obj1"), "Obj1"};
+ 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};
+
+ safassert(saImmOmInitialize(&immOmHandle, &immOmCallbacks, &immVersion),
SA_AIS_OK);
+ safassert(saImmOmAdminOwnerInitialize(immOmHandle, adminOwnerName,
+ SA_TRUE, &ownerHandle), SA_AIS_OK);
+ safassert(saImmOmAdminOwnerSet(ownerHandle, objectNames, SA_IMM_ONE),
SA_AIS_OK);
+ safassert(saImmOmCcbInitialize(ownerHandle, 0, &ccbHandle), SA_AIS_OK);
+ safassert(saImmOmCcbObjectCreate_2(ccbHandle, configClassName,
+ &rootObj, attrValues), SA_AIS_OK);
+
+ /* validate the ccb */
+ if ((rc = saImmOmCcbValidate(ccbHandle)) != SA_AIS_OK)
+ goto done;
+
+ if ((rc = saImmOmCcbAbort(ccbHandle)) != SA_AIS_OK) /* Abort after
valiadtion should be ok */
+ goto done;
+
+ if ((rc = saImmOmCcbApply(ccbHandle)) != SA_AIS_OK) /* Aply after abort
(empty ccb) should be ok */
+ goto done;
+
+ safassert(saImmOmCcbFinalize(ccbHandle), SA_AIS_OK);
+
+done:
+ test_validate(rc, SA_AIS_OK);
+ safassert(saImmOmAdminOwnerFinalize(ownerHandle), SA_AIS_OK);
+ safassert(saImmOmFinalize(immOmHandle), SA_AIS_OK);
+ TRACE_LEAVE();
+}
+
+void saImmOmCcbValidate_02(void)
+{
+ TRACE_ENTER();
+ const SaImmAdminOwnerNameT adminOwnerName = (SaImmAdminOwnerNameT)
__FUNCTION__;
+ SaImmAdminOwnerHandleT ownerHandle;
+ SaImmCcbHandleT ccbHandle;
+ SaNameT rdn = {strlen("Obj1"), "Obj1"};
+ 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("Obj1,rdn=root"), "Obj1,rdn=root"};
+
+ safassert(saImmOmInitialize(&immOmHandle, &immOmCallbacks, &immVersion),
SA_AIS_OK);
+ safassert(saImmOmAdminOwnerInitialize(immOmHandle, adminOwnerName,
+ SA_TRUE, &ownerHandle), SA_AIS_OK);
+ safassert(saImmOmAdminOwnerSet(ownerHandle, objectNames, SA_IMM_ONE),
SA_AIS_OK);
+ safassert(saImmOmCcbInitialize(ownerHandle, 0, &ccbHandle), SA_AIS_OK);
+ safassert(saImmOmCcbObjectCreate_2(ccbHandle, configClassName,
+ &rootObj, attrValues), SA_AIS_OK);
+
+ /* validate the ccb */
+ if ((rc = saImmOmCcbValidate(ccbHandle)) != SA_AIS_OK)
+ goto done;
+
+ if ((rc = saImmOmCcbApply(ccbHandle)) != SA_AIS_OK) /* Aply after validate
(normal case) should be ok */
+ goto done;
+
+ if ((rc = saImmOmCcbAbort(ccbHandle)) != SA_AIS_OK) /* Abort after apply
(empty ccb) should be ok */
+ goto done;
+
+ safassert(saImmOmCcbObjectDelete(ccbHandle, &objectName), SA_AIS_OK);
+ safassert(saImmOmCcbApply(ccbHandle), SA_AIS_OK);
+
+ safassert(saImmOmCcbFinalize(ccbHandle), SA_AIS_OK);
+
+done:
+ test_validate(rc, SA_AIS_OK);
+ safassert(saImmOmAdminOwnerFinalize(ownerHandle), SA_AIS_OK);
+ safassert(saImmOmFinalize(immOmHandle), SA_AIS_OK);
+ TRACE_LEAVE();
+}
diff --git a/tests/immsv/management/test_saImmOmCcbInitialize.c
b/tests/immsv/management/test_saImmOmCcbInitialize.c
--- a/tests/immsv/management/test_saImmOmCcbInitialize.c
+++ b/tests/immsv/management/test_saImmOmCcbInitialize.c
@@ -166,6 +166,8 @@ extern void saImmOmCcbFinalize_01(void);
extern void saImmOmCcbFinalize_02(void);
extern void saImmOmCcbAbort_01(void);
extern void saImmOmCcbAbort_02(void);
+extern void saImmOmCcbValidate_01(void);
+extern void saImmOmCcbValidate_02(void);
__attribute__ ((constructor)) static void saImmOmInitialize_constructor(void)
{
@@ -239,5 +241,7 @@ extern void saImmOmCcbAbort_02(void);
test_case_add(6, saImmOmCcbObjectModify_2_07, "saImmOmCcbObjectModify_2
SA_IMM_ATTR_DELETE multi/multi - SA_AIS_OK");
test_case_add(6, saImmOmCcbAbort_01, "saImmOmCcbAbort - SA_AIS_OK");
test_case_add(6, saImmOmCcbAbort_02, "saImmOmCcbAbort - SA_AIS_OK on
continued ccb handle usage.");
+ test_case_add(6, saImmOmCcbValidate_01, "saImmOmCcbValidate followed by
apply - SA_AIS_OK");
+ test_case_add(6, saImmOmCcbValidate_02, "saImmOmCcbValidate followed by
abort - SA_AIS_OK");
}
diff --git a/tests/unit_test_fw/src/utest.c b/tests/unit_test_fw/src/utest.c
--- a/tests/unit_test_fw/src/utest.c
+++ b/tests/unit_test_fw/src/utest.c
@@ -37,7 +37,7 @@ static unsigned int test_passed;
static unsigned int test_failed;
#define NO_SUITES 64
-#define NR_TESTS 64
+#define NR_TESTS 128
static struct test testlist[NO_SUITES][NR_TESTS];
static const char *suite_name[NO_SUITES];
static int last_test_status;
------------------------------------------------------------------------------
_______________________________________________
Opensaf-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel