This second patch for ticket #623 triggers a compiler warning for some.
Since warnings are intentionally treated as error in OpenSAF, the compilation
will fail.
The reason I missed this warning is very strange.
You get the warning or not depending on which optimization level you compile
with.
The warning is actually not triggered if you compile with optimization level
zero.
Default optimization level for CFLAGS and CXXFLAGS is apparently O2 and does
trigger the warning.
So if these environment variables are redefined (which was the case for me),
then they
remove the CFLAGS default value and default to the default value for gcc which
is O0 apparently.
Exatly why the optimizing level is in the business of generating warnings or
not is unclear to me.
But it probably has to do with that some warnings require data flow analysis to
be detected and
such analysis is probably only done at level O2 or above.
Bottom line is this.
If you get the warning:
In the file osaf/services/saf/immsv/immpbed/immpbe_daemon.cc
In the callback function saImmOiCcbObjectCreateCallback
In the initial declarations of variables,
this variable has always been declared uninitialized:
struct CcbUtilCcbData *ccbUtilCcbData;
You need to change this to:
struct CcbUtilCcbData *ccbUtilCcbData=NULL;
To avoid getting the compiler warning.
I will of course fix this before pushing.
/AndersBj
-----Original Message-----
From: Anders Bjornerstedt [mailto:[email protected]]
Sent: den 12 februari 2014 20:03
To: [email protected]
Cc: [email protected]
Subject: [devel] [PATCH 2 of 2] IMM: 2PBE slave wait for prepare from primary
in PRT-create & PRT-update [#623]
osaf/services/saf/immsv/immpbed/immpbe_daemon.cc | 343 +++++++++++++---------
1 files changed, 203 insertions(+), 140 deletions(-)
Risk for discrepancy between 2PBE slave and primary is reduced further by
having the slave wait for ok_to_prepare trigger from primary for the weak-ccb
associated with the PRT operations. The 2PBE primary will also not perform the
PRT operation if it does not get ok reply from slave on the prepare call, This
follows the same pattern as existed earlier (in 4.4 2PBE) for regular CCBs and
for PRO deletes.
The ok_to_prepare call is a synchronous admin-opertion invoked from primary to
slave. At primary it blocks the main thread waiting for reply. At slave it is
received and executed by the slave's runtime thread, where the slave's main
thread should have received the data and be blocked waiting for this
ok_to_pripare.
The risk for discrepancy in the sqlite commit to the two pbe files should be
minimal and only possible by crash or SIGKILL of one or both PBEs during sqlite
commit processing. A SIGTERM on the PBEs should not be able to cause a
discrepancy.
diff --git a/osaf/services/saf/immsv/immpbed/immpbe_daemon.cc
b/osaf/services/saf/immsv/immpbed/immpbe_daemon.cc
--- a/osaf/services/saf/immsv/immpbed/immpbe_daemon.cc
+++ b/osaf/services/saf/immsv/immpbed/immpbe_daemon.cc
@@ -1076,8 +1076,8 @@ static SaAisErrorT saImmOiCcbObjectModif {
SaAisErrorT rc = SA_AIS_OK;
struct CcbUtilCcbData *ccbUtilCcbData = NULL;
- struct CcbUtilOperationData *operation = NULL;
- long long unsigned int opCount=0;
+ SaUint64T numOps=0LL;
+ unsigned int msecs_waited = 0;
TRACE_ENTER2("Modify callback for CCB:%llu object:%s", ccbId,
objectName->value);
if ((ccbUtilCcbData = ccbutil_findCcbData(ccbId)) == NULL) { @@ -1088,7
+1088,7 @@ static SaAisErrorT saImmOiCcbObjectModif
}
}
- opCount = (long long unsigned int) ccbUtilCcbData->userData;
+ numOps = (SaUint64T) ccbUtilCcbData->userData;
if(strncmp((char *) objectName->value, (char *) OPENSAF_IMM_OBJECT_DN,
objectName->length) ==0) {
char buf[sBufsize];
@@ -1100,121 +1100,119 @@ static SaAisErrorT saImmOiCcbObjectModif
/* We will actually get invoked twice on this object, both as
normal implementer and as PBE
the response on the modify upcall from PBE is discarded, but
not for the regular implemener.
*/
- } else {
- /* "memorize the modification request" */
- if(ccbutil_ccbAddModifyOperation(ccbUtilCcbData, objectName,
attrMods) != 0) {
- LOG_ER("ccbutil_ccbAddModifyOperation did NOT return
zero");
+ goto done;
+ }
+
+ /* memorize the modification request */
+ if(ccbutil_ccbAddModifyOperation(ccbUtilCcbData, objectName, attrMods)
!= 0) {
+ LOG_ER("ccbutil_ccbAddModifyOperation did NOT return zero");
+ rc = SA_AIS_ERR_BAD_OPERATION;
+ goto done;
+ }
+
+ ccbUtilCcbData->userData = (void *) ++numOps;
+
+ if(ccbId < 0x100000000LL) {
+ /* Regular CCB only records the modify */
+ goto done;
+ }
+
+ /* PRTA update operation. */
+ if(sPbe2B) {
+ /* Slave PBE waits for prepare for PRTA update (weak ccb) as
admop
+invoked from primary PBE.*/
+
+ while((msecs_waited < max_waiting_time_ms) &&
+ ( (s2PbeBCcbToCompleteAtB != ccbId) ||
+ (s2PbeBCcbOpCountNowAtB == 0) ||
+ (!pbeTransIsPrepared())
+ )) {
+ LOG_IN("PBE slave waiting for prepare from primary on
PRTA update ccb:%llx", ccbId);
+ usleep(sleep_delay_ms * 1000);
+ msecs_waited += sleep_delay_ms;
+ }
+
+ if((s2PbeBCcbToCompleteAtB != ccbId) ||
+ (s2PbeBCcbOpCountNowAtB == 0) ||
+ (!pbeTransIsPrepared())) {
+ LOG_NO("Slave PBE time-out in waiting on porepare for
PRTA update ccb:%llx dn:%s", ccbId,
+ (const char *) objectName->value);
+ rc = SA_AIS_ERR_FAILED_OPERATION;
+ goto abort_prta_trans;
+ }
+ goto commit_prta_trans;
+
+ } else if(sPbe2) {
+ /* 2PBE at primary requests PBE slave to prepare this weak ccb.
If prepare at slave
+ fails, then the weak ccb (PRTA update) is aborted also here
at
+primary. */
+
+ LOG_IN("Starting distributed PBE commit for PRTA update
Ccb:%llx/%llu", ccbId, ccbId);
+ if(!pbe2_start_prepare_ccb_A_to_B(ccbId, (SaUint32T) numOps)) {
/* Order slave to prepare */
+ LOG_WA("PBE-A failed to prepare PRTA update
Ccb:%llx/%llu towards
+PBE-B", ccbId, ccbId);
rc = SA_AIS_ERR_BAD_OPERATION;
goto done;
}
}
- ccbUtilCcbData->userData = (void *) (opCount +1);
+ /* PRTA update at 1PBE or 2PBE primary, i.e. not at 2PBE-slave. */
+ osafassert((numOps == 1) && (!sPbe2B));
- if(ccbId > 0x100000000LL) { /* PRTA update operation. */
- const SaImmAttrModificationT_2 *attMod = NULL;
- int ix=0;
- std::string objName;
- operation = ccbutil_getNextCcbOp(ccbId, NULL);
- if(operation == NULL) {
- LOG_ER("ccbutil_getNextCcbOp(%llx, NULL) returned
NULL", ccbId);
- rc = SA_AIS_ERR_BAD_OPERATION;
- goto done;
- }
-
- TRACE("Update of PERSISTENT runtime attributes in object with
DN: %s",
- operation->objectName.value);
+ TRACE("Update of PERSISTENT runtime attributes in object with DN: %s",
+ (const char *) objectName->value);
- rc = pbeBeginTrans(sDbHandle);
- if(rc != SA_AIS_OK) {
- LOG_WA("PBE failed to start sqlite transaction for PRT
attr update");
- rc = SA_AIS_ERR_NO_RESOURCES;
- goto done;
- }
- TRACE("Begin PBE transaction for rt obj update OK");
-
-
- /* Note: it is important that the code in this update case
follow
- the same logic as performed by ImmModel::rtObjectUpdate()
- We DO NOT want the PBE repository to diverge from the main
memory
- represenation of the immsv data.
- This is not the only way to solve this. In fact the current
solution is
- very unoptimal since it generates possibly several sql
commands for what
- could be one. The advantage with the current solution is
that it follows
- the logic of the ImmModel and can do so using the data
provided by the
- unmodified rtObjectUpdate upcall.
- */
- TRACE("Update of object with DN: %s",
operation->param.modify.objectName->value);
- objName.append((const char *)
operation->param.modify.objectName->value);
- attrMods = operation->param.modify.attrMods;
- while((attMod = attrMods[ix++]) != NULL) {
- switch(attMod->modType) {
- case SA_IMM_ATTR_VALUES_REPLACE:
-
objectModifyDiscardAllValuesOfAttrToPBE(sDbHandle, objName,
- &(attMod->modAttr), ccbId);
-
- if(attMod->modAttr.attrValuesNumber ==
0) {
- continue; //Ok to replace with
nothing
- }
- //else intentional fall through
-
- case SA_IMM_ATTR_VALUES_ADD:
- if(attMod->modAttr.attrValuesNumber ==
0) {
- LOG_ER("Empty value used for
adding to attribute %s",
-
attMod->modAttr.attrName);
- rc = SA_AIS_ERR_BAD_OPERATION;
- goto abort_trans;
- }
-
-
objectModifyAddValuesOfAttrToPBE(sDbHandle, objName,
- &(attMod->modAttr), ccbId);
-
- break;
-
- case SA_IMM_ATTR_VALUES_DELETE:
- if(attMod->modAttr.attrValuesNumber ==
0) {
- LOG_ER("Empty value used for
deleting from attribute %s",
-
attMod->modAttr.attrName);
- rc = SA_AIS_ERR_BAD_OPERATION;
- goto abort_trans;
- }
-
-
objectModifyDiscardMatchingValuesOfAttrToPBE(sDbHandle, objName,
- &(attMod->modAttr), ccbId);
-
- break;
- default: abort();
- }
- }
-
-
- ccbutil_deleteCcbData(ccbutil_findCcbData(ccbId));
- pbeClosePrepareTrans();
- rc = pbeCommitTrans(sDbHandle, ccbId, sEpoch,
&sLastCcbCommitTime);
- if(rc != SA_AIS_OK) {
- LOG_WA("PBE failed to commit sqlite transaction
(ccb:%llx) for PRT attr update", ccbId);
- rc = SA_AIS_ERR_NO_RESOURCES;
- goto done;
- }
- TRACE("Commit PBE transaction %llx for rt attr update OK",
ccbId);
+ rc = pbeBeginTrans(sDbHandle);
+ if(rc != SA_AIS_OK) {
+ LOG_WA("PBE failed to start sqlite transaction (ccbId:%llx) for
PRT attr update", ccbId);
+ rc = SA_AIS_ERR_NO_RESOURCES;
+ goto done;
}
+ TRACE("Build PBE transaction for rt obj update");
+
+ rc = sqlite_prepare_ccb(immOiHandle, ccbId,
ccbUtilCcbData->operationListHead);
+ if(rc != SA_AIS_OK) {
+ goto abort_prta_trans;
+ }
+
+ commit_prta_trans:
+ rc = pbeCommitTrans(sDbHandle, ccbId, sEpoch, &sLastCcbCommitTime);
+
+ /* Reset 2pbe-ccb-syncronization variables at slave. */
+ if(sPbe2B) {
+ s2PbeBCcbToCompleteAtB=0;
+ s2PbeBCcbOpCountToExpectAtB=0;
+ s2PbeBCcbOpCountNowAtB=0;
+ s2PbeBCcbUtilCcbData = NULL;
+ }
+
+ if(rc != SA_AIS_OK) {
+ LOG_WA("PBE failed to commit sqlite transaction (ccb:%llx) for
PRT attr update", ccbId);
+ rc = SA_AIS_ERR_NO_RESOURCES;
+ goto done;
+ }
+ TRACE("Commit PBE transaction %llx for rt attr update OK", ccbId);
goto done;
- abort_trans:
+
+ abort_prta_trans:
pbeAbortTrans(sDbHandle);
+
+ /* Reset 2pbe-ccb-syncronization variables at slave. */
+ if(sPbe2B) {
+ s2PbeBCcbToCompleteAtB=0;
+ s2PbeBCcbOpCountToExpectAtB=0;
+ s2PbeBCcbOpCountNowAtB=0;
+ s2PbeBCcbUtilCcbData = NULL;
+ }
+
done:
if((rc != SA_AIS_OK) && sPbe2 && (ccbId > 0x100000000LL)) {
- /* For 2PBE, PRTA update is done in parallell at primary and
slave.
- This means four possible outcommes:
- i) Ok at primary & Ok at slave => normal case.
- ii) Ok at primary _& failure at slave.
- iii) Failure at primary & Ok at slave.
- iv) Failure at primary and failure at slave.
- Current PBE implementation can not distinguish cases (11) -
(iv).
- */
- LOG_ER("2PBE can not tolerate error (%u) in PRTA update
(ccbId:%llx) - exiting", rc, ccbId);
- exit(1);
+ LOG_NO("2PBE Error (%u) in PRTA update (ccbId:%llx)", rc,
ccbId);
+ }
+
+ if(ccbUtilCcbData && (ccbId > 0x100000000LL)) {
+ /* Remove any PRTA update. */
+ ccbutil_deleteCcbData(ccbUtilCcbData);
+ ccbUtilCcbData = NULL;
}
TRACE_LEAVE();
return rc;
@@ -1424,7 +1422,9 @@ static SaAisErrorT saImmOiCcbObjectCreat
std::string classNameString(className);
struct CcbUtilOperationData *operation = NULL;
ClassInfo* classInfo = (*sClassIdMap)[classNameString];
- long long unsigned int opCount=0;
+ SaUint64T numOps=0LL;
+ unsigned int msecs_waited = 0;
+
if(parentName && parentName->length) {
TRACE_ENTER2("CREATE CALLBACK CCB:%llu class:%s parent:%s",
ccbId, className, parentName->value); @@ -1449,7 +1449,7 @@ static SaAisErrorT
saImmOiCcbObjectCreat
}
}
- opCount = (long long unsigned int) ccbUtilCcbData->userData;
+ numOps = (SaUint64T) ccbUtilCcbData->userData;
if(strncmp((char *) className, (char *) OPENSAF_IMM_CLASS_NAME,
strlen(className)) == 0) {
snprintf(buf, sBufsize,
@@ -1463,8 +1463,7 @@ static SaAisErrorT saImmOiCcbObjectCreat
goto done;
}
- /* "memorize the creation request" */
-
+ /* memorize the creation request */
operation = ccbutil_ccbAddCreateOperation(ccbUtilCcbData, className,
parentName, attr);
if(operation == NULL) {
LOG_ER("ccbutil_ccbAddCreateOperation returned NULL"); @@
-1535,49 +1534,113 @@ static SaAisErrorT saImmOiCcbObjectCreat
goto done;
}
- ccbUtilCcbData->userData = (void *) (opCount +1);
+ ccbUtilCcbData->userData = (void *) ++numOps;
- if(ccbId > 0x100000000LL) {
- TRACE("Create of PERSISTENT runtime object with DN: %s",
- operation->objectName.value);
- rc = pbeBeginTrans(sDbHandle);
- if(rc != SA_AIS_OK) {
- LOG_WA("PBE failed to start sqlite transaction
(ccbId:%llx)for PRTO create", ccbId);
- rc = SA_AIS_ERR_NO_RESOURCES;
+ if(ccbId < 0x100000000LL) {
+ /* Regular CCB only records the create */
+ goto done;
+ }
+
+ /* PRTO create operation */
+ if(sPbe2B) {
+ /* Slave PBE waits for prepare for PRTO create (weak ccb) as
admop
+invoked from primary PBE.*/
+
+ while((msecs_waited < max_waiting_time_ms) &&
+ ( (s2PbeBCcbToCompleteAtB != ccbId) ||
+ (s2PbeBCcbOpCountNowAtB == 0) ||
+ (!pbeTransIsPrepared())))
+ {
+ LOG_IN("PBE slave waiting for prepare from primary on
PRTO create ccb:%llx", ccbId);
+ usleep(sleep_delay_ms * 1000);
+ msecs_waited += sleep_delay_ms;
+ }
+
+ if((s2PbeBCcbToCompleteAtB != ccbId) ||
+ (s2PbeBCcbOpCountNowAtB == 0) ||
+ (!pbeTransIsPrepared()))
+ {
+ LOG_NO("Slave PBE time-out in waiting on porepare for
PRTO create ccb:%llx dn:%s", ccbId,
+ (const char *) operation->objectName.value);
+ rc = SA_AIS_ERR_FAILED_OPERATION;
+ goto abort_prto_trans;
+ }
+ goto commit_prto_trans;
+
+ } else if(sPbe2) {
+ /* 2PBE at primary requests PBE slave to prepare this weak ccb.
If prepare at slave
+ fails, then the weak ccb (PRTO create) is aborted also here
at
+primary */
+
+ LOG_IN("Starting distributed PBE commit for PRTO create
Ccb:%llx/%llu", ccbId, ccbId);
+ if(!pbe2_start_prepare_ccb_A_to_B(ccbId, (SaUint32T) numOps)) {
/* Order slave to prepare */
+ LOG_WA("PBE-A failed to prepare PRTO create
Ccb:%llx/%llu towards PBE-B", ccbId, ccbId);
+ rc = SA_AIS_ERR_BAD_OPERATION;
goto done;
}
+ }
- TRACE("Begin PBE transaction for rt obj create OK");
+ /* PRTO create at 1PBE or 2PBE primary, i.e. not at 2PBE-slave. */
+ osafassert((numOps == 1) && (!sPbe2B));
- objectToPBE(std::string((const char *)
operation->objectName.value),
- operation->param.create.attrValues,
- sClassIdMap, sDbHandle, ++sObjCount,
- operation->param.create.className, ccbId);
+ TRACE("Create of PERSISTENT runtime object with DN: %s",
+ (const char *) operation->objectName.value);
- ccbutil_deleteCcbData(ccbutil_findCcbData(0));
- pbeClosePrepareTrans();
- rc = pbeCommitTrans(sDbHandle, ccbId, sEpoch,
&sLastCcbCommitTime);
- if(rc != SA_AIS_OK) {
- LOG_WA("PBE failed to commit sqlite transaction
(ccbId:%llx) for PRTO create", ccbId);
- rc = SA_AIS_ERR_NO_RESOURCES;
- goto done;
- }
- TRACE("Commit PBE transaction for rt obj create OK");
+ rc = pbeBeginTrans(sDbHandle);
+ if(rc != SA_AIS_OK) {
+ LOG_WA("PBE failed to start sqlite transaction (ccbId:%llx)for
PRTO create", ccbId);
+ rc = SA_AIS_ERR_NO_RESOURCES;
+ goto done;
+ }
+ TRACE("Build PBE transaction for rt obj create");
+
+ rc = sqlite_prepare_ccb(immOiHandle, ccbId,
ccbUtilCcbData->operationListHead);
+ if(rc != SA_AIS_OK) {
+ goto abort_prto_trans;
+ }
+
+ commit_prto_trans:
+ rc = pbeCommitTrans(sDbHandle, ccbId, sEpoch, &sLastCcbCommitTime);
+
+ /* Reset 2pbe-ccb-syncronization variables at slave. */
+ if(sPbe2B) {
+ s2PbeBCcbToCompleteAtB=0;
+ s2PbeBCcbOpCountToExpectAtB=0;
+ s2PbeBCcbOpCountNowAtB=0;
+ s2PbeBCcbUtilCcbData = NULL;
+ }
+
+ if(rc != SA_AIS_OK) {
+ LOG_WA("PBE failed to commit sqlite transaction (ccbId:%llx)
for PRTO create", ccbId);
+ rc = SA_AIS_ERR_NO_RESOURCES;
+ goto done;
+ }
+ TRACE("Commit PBE transaction %llx for rt obj create OK", ccbId);
+
+
+ goto done;
+
+ abort_prto_trans:
+ pbeAbortTrans(sDbHandle);
+
+ /* Reset 2pbe-ccb-syncronization variables at slave. */
+ if(sPbe2B) {
+ s2PbeBCcbToCompleteAtB=0;
+ s2PbeBCcbOpCountToExpectAtB=0;
+ s2PbeBCcbOpCountNowAtB=0;
+ s2PbeBCcbUtilCcbData = NULL;
}
done:
if((rc != SA_AIS_OK) && sPbe2 && (ccbId > 0x100000000LL)) {
- /* For 2PBE, PRTA update is done in parallell at primary and
slave.
- This means four possible outcommes:
- i) Ok at primary & Ok at slave => normal case.
- ii) Ok at primary _& failure at slave.
- iii) Failure at primary & Ok at slave.
- iv) Failure at primary and failure at slave.
- Current PBE implementation can not distinguish cases (11) -
(iv).
- */
- LOG_ER("2PBE can not tolerate error (%u) in PRTA update -
exiting", rc);
- exit(1);
+ LOG_NO("2PBE Error (%u) in PRTO create (ccbId:%llx)", rc,
ccbId);
}
+
+ if(ccbUtilCcbData && (ccbId > 0x100000000LL)) {
+ /* Remove any PRTO create */
+ ccbutil_deleteCcbData(ccbUtilCcbData);
+ ccbUtilCcbData = NULL;
+ }
+
+
TRACE_LEAVE();
return rc;
}
------------------------------------------------------------------------------
Android apps run on BlackBerry 10
Introducing the new BlackBerry 10.2.1 Runtime for Android apps.
Now with support for Jelly Bean, Bluetooth, Mapview and more.
Get your Android app in front of a whole new audience. Start now.
http://pubads.g.doubleclick.net/gampad/clk?id=124407151&iu=/4140/ostg.clktrk
_______________________________________________
Opensaf-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel
------------------------------------------------------------------------------
Android apps run on BlackBerry 10
Introducing the new BlackBerry 10.2.1 Runtime for Android apps.
Now with support for Jelly Bean, Bluetooth, Mapview and more.
Get your Android app in front of a whole new audience. Start now.
http://pubads.g.doubleclick.net/gampad/clk?id=124407151&iu=/4140/ostg.clktrk
_______________________________________________
Opensaf-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensaf-devel