Johan, I guess the abort classification only applies to the case when we 
return SA_AIS_ERR_FAILED_OPERATION, and that is the reason why some 
error strings have neither the "Resource abort" nor the "Validation 
abort" prefix in the patch below? Still I see a potential that this 
classification is forgotten, in some future modification of the code. 
Zoran, would it be possible to add some sort of assertion (or at least a 
log message) that can catch cases where the classification has been 
forgotten (or even the string has been misspelt) in the error string?

/ Anders Widell

On 09/01/2015 10:56 AM, Johan Mårtensson O wrote:
> Hi Zoran,
>
> See comments on the patch below.
>
> / Johan
>
> -----Original Message-----
> From: Zoran Milinkovic [mailto:zoran.milinko...@ericsson.com]
> Sent: den 28 augusti 2015 16:07
> To: reddy.neelaka...@oracle.com
> Cc: opensaf-devel@lists.sourceforge.net
> Subject: [devel] [PATCH 1 of 1] imm: classify abort error strings and prefix 
> existing error strings [#744]
>
>   osaf/services/saf/immsv/immnd/ImmModel.cc  |  126 
> +++++++++++++++++++++++-----
>   osaf/services/saf/immsv/immnd/ImmModel.hh  |    5 +
>   osaf/services/saf/immsv/immnd/immnd_evt.c  |   48 ++++++++++-
>   osaf/services/saf/immsv/immnd/immnd_init.h |    6 +
>   4 files changed, 156 insertions(+), 29 deletions(-)
>
>
> The patch set prefix "IMM:" to all error string that come from IMM.
> Based on CCB abort type (resource or validation abort), error strings are 
> prefixed with "IMM: Resource abort:" or "IMM: Validation abort:"
>
> 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
> @@ -2109,6 +2109,23 @@ immModel_resourceDisplay(IMMND_CB *cb,
>           resourceDisplay(reqparams, rparams, searchcount);  }
>   
> +void
> +immModel_setCcbErrorString(IMMND_CB *cb, SaUint32T ccbId, const char 
> *errorString, ...) {
> +    CcbVector::iterator cvi;
> +    va_list vl;
> +
> +    cvi = std::find_if(sCcbVector.begin(), sCcbVector.end(), CcbIdIs(ccbId));
> +    if (cvi == sCcbVector.end()) {
> +        /* Cannot find CCB. Error string will be ignored.
> +         * This case should never happen. */
> +        return;
> +    }
> +
> +    va_start(vl, errorString);
> +    ImmModel::instance(&cb->immModel)->setCcbErrorString(*cvi, errorString, 
> vl);
> +    va_end(vl);
> +}
> +
>   /*====================================================================*/
>   
>   ImmModel::ImmModel() :
> @@ -4982,6 +4999,8 @@ ImmModel::ccbApply(SaUint32T ccbId,
>               LOG_NO("ERR_BAD_HANDLE: Admin owner id %u does not exist",
>                   ccb->mAdminOwnerId);
>               ccb->mVeto = SA_AIS_ERR_BAD_HANDLE;
> +            /* Later in the code, error code will be set to 
> SA_AIS_ERR_FAILED_OPERATION */
> +            setCcbErrorString(ccb, "IMM: Resource abort: Admin owner
> + does not exist");
>           } else if(ccb->mState > IMM_CCB_READY) {
>               if(ccb->mState == IMM_CCB_VALIDATING) {
>                   LOG_IN("Ccb <%u> in incorrect state 'CCB_VALIDATING for "
> @@ -5003,6 +5022,8 @@ ImmModel::ccbApply(SaUint32T ccbId,
>                               /* apply callback needs to be sent to 
> implementers. */
>                              err = SA_AIS_ERR_INTERRUPT;
>                           }
> +                    } else if(err == SA_AIS_ERR_FAILED_OPERATION) {
> +                        setCcbErrorString(ccb, "IMM: Validation abort:
> + Completed validation failed");
>                       }
>                       goto done;
>                  }
> @@ -5033,9 +5054,11 @@ ImmModel::ccbApply(SaUint32T ccbId,
>               }
>               err = SA_AIS_ERR_FAILED_OPERATION;
>               ccb->mVeto = SA_AIS_ERR_FAILED_OPERATION;
> +            setCcbErrorString(ccb, "IMM: Validation abort: Parent is
> + missing");
>           } else if(!validateNoDanglingRefs(ccb)) {
>               err = SA_AIS_ERR_FAILED_OPERATION;
>               ccb->mVeto = SA_AIS_ERR_FAILED_OPERATION;
> +            setCcbErrorString(ccb, "IMM: Validation abort: No dangling
> + validation failed");
>           } else {
>               /* sMissingParents must be empty if err is SA_AIS_OK */
>               osafassert(sMissingParents.empty());
> @@ -5074,6 +5097,8 @@ ImmModel::ccbApply(SaUint32T ccbId,
>                           "refusing apply", 
> impInfo->mImplementerName.c_str());
>                       err = SA_AIS_ERR_FAILED_OPERATION;
>                       ccb->mVeto = SA_AIS_ERR_FAILED_OPERATION;
> +                    setCcbErrorString(ccb,
> +                            "IMM: Resource abort: Lost connection with
> + implementer");
>                       break;
>                   }
>                   //Wait for ack, possibly remote @@ -5662,7 +5687,7 @@ 
> ImmModel::ccbAbort(SaUint32T ccbId, Conn
>              not really any error at all, but mVeto should not be SA_AIS_OK.
>           */
>           ccb->mVeto = SA_AIS_ERR_NO_RESOURCES;
> -        setCcbErrorString(ccb, "Resource Error: CCB abort due to either "
> +        setCcbErrorString(ccb, "IMM: Resource abort: CCB abort due to either 
> "
>               "OI timeout or explicit abort request.");
>       }
>   
> @@ -6050,6 +6075,7 @@ ImmModel::ccbAugmentInit(immsv_oi_ccb_up
>              rsp->inv, ccbId);
>           if(ccb->mVeto == SA_AIS_OK) {
>               ccb->mVeto = SA_AIS_ERR_FAILED_OPERATION;
> +            /* Note: This error code is returned to OI. Parent CCB is
> + aborted */
>               err = SA_AIS_ERR_BAD_OPERATION;
>           }
>           goto done;
> @@ -6071,6 +6097,7 @@ ImmModel::ccbAugmentInit(immsv_oi_ccb_up
>           TRACE("Ccb %u is already in an error state %u, can not accept 
> augmentation",
>                ccbId, ccb->mVeto);
>           err = SA_AIS_ERR_FAILED_OPERATION; /*ccb->mVeto;*/
> +        setCcbErrorString(ccb, "IMM: Resource abort: CCB is in an error
> + state");
>           goto done;
>       }
>   
> @@ -6823,6 +6850,7 @@ SaAisErrorT ImmModel::ccbObjectCreate(Im
>           LOG_NO("ERR_FAILED_OPERATION: ccb %u is in an error state "
>               "rejecting ccbObjectCreate operation ", ccbId);
>           err = SA_AIS_ERR_FAILED_OPERATION;
> +        setCcbErrorString(ccb, "IMM: Resource abort: CCB is in an error
> + state");
>           goto ccbObjectCreateExit;
>       }
>   
> @@ -6830,6 +6858,7 @@ SaAisErrorT ImmModel::ccbObjectCreate(Im
>           LOG_NO("ERR_FAILED_OPERATION: ccb %u is not in an expected state:%u 
> "
>               "rejecting ccbObjectCreate operation ", ccbId, ccb->mState);
>           err = SA_AIS_ERR_FAILED_OPERATION;
> +        setCcbErrorString(ccb, "IMM: Resource abort: CCB is not in an
> + expected state");
>           goto ccbObjectCreateExit;
>       }
>   
> @@ -6859,13 +6888,14 @@ SaAisErrorT ImmModel::ccbObjectCreate(Im
>               LOG_WA("ERR_FAILED_OPERATION: Inconsistency between Ccb 
> admoId:%u and AdminOwner-id:%u",
>                   adminOwner->mId, ccb->mAdminOwnerId);
>               err = SA_AIS_ERR_FAILED_OPERATION;
> +            setCcbErrorString(ccb, "IMM: Resource abort: Inconsistency
> + between CCB and AdminOwner");
>               goto ccbObjectCreateExit;
>           }
>       }
>   
>       if (i3 == sClassMap.end()) {
>           TRACE_7("ERR_NOT_EXIST: class '%s' does not exist", 
> className.c_str());
> -        setCcbErrorString(ccb, "ERR_NOT_EXIST: class '%s' does not exist", 
> className.c_str());
> +        setCcbErrorString(ccb, "IMM: ERR_NOT_EXIST: class '%s' does not
> + exist", className.c_str());
>           err = SA_AIS_ERR_NOT_EXIST;
>           goto ccbObjectCreateExit;
>       } else if(sPbeRtMutations.find(className) != sPbeRtMutations.end()) { 
> @@ -6961,6 +6991,9 @@ SaAisErrorT ImmModel::ccbObjectCreate(Im
>       if (i4 == classInfo->mAttrMap.end()) {
>           LOG_WA("ERR_FAILED_OPERATION: No RDN attribute found in class!");
>           err = SA_AIS_ERR_FAILED_OPERATION;     //Should never happen!
> +        // Here IMMND should assert ??? It cannot happen that class does not 
> have RDN.
> +        // This could happen due to memory corruption or heap overflow
> +        setCcbErrorString(ccb, "IMM: Resource abort: No RDN found in a
> + class");
>           goto ccbObjectCreateExit;
>       }
>   
> @@ -7192,7 +7225,7 @@ SaAisErrorT ImmModel::ccbObjectCreate(Im
>               
>               if (i6 == object->mAttrValueMap.end()) {
>                   TRACE_7("ERR_NOT_EXIST: attr '%s' not defined", 
> attrName.c_str());
> -                setCcbErrorString(ccb, "ERR_NOT_EXIST: attr '%s' not 
> defined",
> +                setCcbErrorString(ccb, "IMM: ERR_NOT_EXIST: attr '%s'
> + not defined",
> Johan: Shouldn't this be "IMM: Resource abort: attr '%s' not defined" to be 
> consistent with the other strings?
>                           attrName.c_str());
>                   err = SA_AIS_ERR_NOT_EXIST;
>                   break; //out of for-loop @@ -7493,6 +7526,7 @@ SaAisErrorT 
> ImmModel::ccbObjectCreate(Im
>                       ccb->mVeto = err;
>                       LOG_WA("ERR_FAILED_OPERATION: Persistent back end is 
> down "
>                              "ccb %u is aborted", ccbId);
> +                    setCcbErrorString(ccb, "IMM: Resource abort: PBE is
> + down");
>                   } else {
>                       /* Pristine ccb can not start because PBE down */
>                       TRACE_5("ERR_TRY_AGAIN: Persistent back end is down"); 
> @@ -7574,7 +7608,7 @@ SaAisErrorT ImmModel::ccbObjectCreate(Im
>                       }
>                   } else {
>                       setCcbErrorString(ccb,
> -                        "ERR_BAD_OPERATION: Imm not allowing creates of 
> instances of class '%s'",
> +                        "IMM: ERR_BAD_OPERATION: Imm not allowing
> + creates of instances of class '%s'",
> Johan: Should this be "IMM: Validation abort: Imm does not allow creates of 
> instances of class '%s'" for consistency?
>                           immMngtClass.c_str());
>                       err = SA_AIS_ERR_BAD_OPERATION;
>                   }
> @@ -7592,10 +7626,12 @@ SaAisErrorT ImmModel::ccbObjectCreate(Im
>                                       "but attribute 'longDnsAllowed' is not 
> defined in class %s",
>                                       immClassName.c_str());
>                               err = SA_AIS_ERR_FAILED_OPERATION;
> +                            setCcbErrorString(ccb, "IMM: Resource
> + abort: Long DN is used, but attribute longDnsAllowed in not defined");
>                           } else if(!i6->second->getValue_int()) {
>                               LOG_WA("ERR_FAILED_OPERATION: Long DN is used 
> during the loading initial data, "
>                                       "but longDnsAllowed is set to 0");
>                               err = SA_AIS_ERR_FAILED_OPERATION;
> +                            setCcbErrorString(ccb, "IMM: Resource
> + abort: Long DN is used when longDnsAllowed is set to 0");
>                           }
>                       } else {
>                           /* 'else' branch is not needed. Only for small 
> performance issue.
> @@ -7607,7 +7643,7 @@ SaAisErrorT ImmModel::ccbObjectCreate(Im
>                       }
>                   } else {
>                       setCcbErrorString(ccb,
> -                        "ERR_BAD_OPERATION: Imm not allowing creates of 
> instances of class '%s'",
> +                        "IMM: ERR_BAD_OPERATION: Imm not allowing
> + creates of instances of class '%s'",
> Johan: Should this also be "Validation abort" as suggested above?
>                           immClassName.c_str());
>                       err = SA_AIS_ERR_BAD_OPERATION;
>                   }
> @@ -7621,7 +7657,7 @@ SaAisErrorT ImmModel::ccbObjectCreate(Im
>                           "implementer and flag SA_IMM_CCB_REGISTERED_OI is 
> set",
>                           className.c_str());
>                       setCcbErrorString(ccb,
> -                            "ERR_NOT_EXIST: class '%s' does not have an "
> +                            "IMM: ERR_NOT_EXIST: class '%s' does not have an 
> "
> Johan: Should this be a "Resource abort"?
>                               "implementer and flag SA_IMM_CCB_REGISTERED_OI 
> is set",
>                               className.c_str());
>                       err = SA_AIS_ERR_NOT_EXIST; @@ -7950,6 +7986,7 @@ 
> ImmModel::ccbObjectModify(const ImmsvOmC
>           LOG_NO("ERR_FAILED_OPERATION: ccb %u is in an error state "
>               "rejecting ccbObjectModify operation ", ccbId);
>           err = SA_AIS_ERR_FAILED_OPERATION;
> +        setCcbErrorString(ccb, "IMM: Resource abort: CCB is in an error
> + state");
>           goto ccbObjectModifyExit;
>       }
>       
> @@ -7957,6 +7994,7 @@ ImmModel::ccbObjectModify(const ImmsvOmC
>           LOG_WA("ERR_FAILED_OPERATION: ccb %u is not in an expected state: 
> %u "
>               "rejecting ccbObjectModify operation ", ccbId, ccb->mState);
>           err = SA_AIS_ERR_FAILED_OPERATION;
> +        setCcbErrorString(ccb, "IMM: Resource abort: CCB is not in an
> + expected state");
>           goto ccbObjectModifyExit;
>       }
>       
> @@ -7975,6 +8013,7 @@ ImmModel::ccbObjectModify(const ImmsvOmC
>           LOG_WA("ERR_FAILED_OPERATION: Inconsistency between Ccb-admoId:%u 
> and "
>               "AdminOwnerId:%u", adminOwner->mId, ccb->mAdminOwnerId);
>           err = SA_AIS_ERR_FAILED_OPERATION;
> +        setCcbErrorString(ccb, "IMM: Resource abort: Inconsistency
> + between CCB and AdminOwner");
>           goto ccbObjectModifyExit;
>       }
>       
> @@ -8120,7 +8159,7 @@ ImmModel::ccbObjectModify(const ImmsvOmC
>               TRACE_7("ERR_BAD_OPERATION: attr '%s' in IMM object %s is not 
> supported",
>                   attrName.c_str(), objectName.c_str());
>               setCcbErrorString(ccb,
> -                "ERR_BAD_OPERATION: attr '%s' in IMM object %s is not 
> supported",
> +                "IMM: ERR_BAD_OPERATION: attr '%s' in IMM object %s is
> + not supported",
> Johan: Should this be a "Validation abort"?
>                   attrName.c_str(), objectName.c_str());
>               err = SA_AIS_ERR_BAD_OPERATION;
>               break; //out of for-loop
> @@ -8130,14 +8169,14 @@ ImmModel::ccbObjectModify(const ImmsvOmC
>               /* ENABLE_PBE defined in immnd.h */
>               LOG_NO("ERR_BAD_OPERATION:  imm has not been built with 
> --enable-imm-pbe");
>               setCcbErrorString(ccb,
> -                "ERR_BAD_OPERATION:  imm has not been built with 
> --enable-imm-pbe");
> +                "IMM: ERR_BAD_OPERATION:  imm has not been built with
> + --enable-imm-pbe");
> Johan: Should this be a "Resource abort"?
>               err = SA_AIS_ERR_BAD_OPERATION;
>               break;
>           }
>           
>           if(modifiedRim && !pbeFile) {
>               LOG_NO("ERR_BAD_OPERATION: PBE file is not configured");
> -            setCcbErrorString(ccb, "ERR_BAD_OPERATION: PBE file is not 
> configured");
> +            setCcbErrorString(ccb, "IMM: ERR_BAD_OPERATION: PBE file is
> + not configured");
> Johan: Can this be a "Resource abort"?
>               err = SA_AIS_ERR_BAD_OPERATION;
>               break;
>           }
> @@ -8147,7 +8186,7 @@ ImmModel::ccbObjectModify(const ImmsvOmC
>               TRACE_7("ERR_NOT_EXIST: attr '%s' does not exist in object %s",
>                   attrName.c_str(), objectName.c_str());
>               setCcbErrorString(ccb,
> -                "ERR_NOT_EXIST: attr '%s' does not exist in object %s",
> +                "IMM: ERR_NOT_EXIST: attr '%s' does not exist in object
> + %s",
> Johan: Should this be a "Resource abort"?
>                   attrName.c_str(), objectName.c_str());
>               err = SA_AIS_ERR_NOT_EXIST;
>               break; //out of for-loop
> @@ -8329,7 +8368,7 @@ ImmModel::ccbObjectModify(const ImmsvOmC
>                           TRACE_7("ERR_BAD_OPERATION: attr '%s' in IMM object 
> %s can not have value %u",
>                               attrName.c_str(), objectName.c_str(), newRim);
>                           setCcbErrorString(ccb,
> -                            "ERR_BAD_OPERATION: attr '%s' in IMM object %s 
> can not have value %u",
> +                            "IMM: ERR_BAD_OPERATION: attr '%s' in IMM
> + object %s can not have value %u",
> Johan: Should this be a "Validation abort"?
>                               attrName.c_str(), objectName.c_str(), newRim);
>                           err = SA_AIS_ERR_BAD_OPERATION;
>                           break;
> @@ -8392,7 +8431,7 @@ ImmModel::ccbObjectModify(const ImmsvOmC
>                       TRACE_7("ERR_BAD_OPERATION: attr '%s' in IMM object %s 
> must not be empty",
>                           attrName.c_str(), objectName.c_str());
>                       setCcbErrorString(ccb,
> -                        "ERR_BAD_OPERATION: attr '%s' in IMM object %s must 
> not be empty",
> +                        "IMM: ERR_BAD_OPERATION: attr '%s' in IMM
> + object %s must not be empty",
> Johan: This could be either a validation abort or resource abort.
>                           attrName.c_str(), objectName.c_str());
>                       err = SA_AIS_ERR_BAD_OPERATION;
>                       break;
> @@ -8459,6 +8498,7 @@ ImmModel::ccbObjectModify(const ImmsvOmC
>                   ccb->mVeto = err;
>                   LOG_WA("ERR_FAILED_OPERATION: Persistent back end is down "
>                          "ccb %u is aborted", ccbId);
> +                setCcbErrorString(ccb, "IMM: Resource abort: PBE is
> + down");
>               } else {
>                   /* Pristine ccb can not start because PBE down */
>                   TRACE_5("ERR_TRY_AGAIN: Persistent back end is down"); @@ 
> -8616,9 +8656,9 @@ ImmModel::ccbObjectModify(const ImmsvOmC
>               if(longDnsPermitted != longDnsAllowedAfter) {
>                   if(ccbIdLongDnGuard) {
>                       /* This case should never happen since it is guarded by 
> regular ccb handling. */
> -                    setCcbErrorString(ccb, "ERR_BUSY: Other Ccb (%u) already 
> using %s",
> +                    setCcbErrorString(ccb, "IMM: ERR_BUSY: Other Ccb
> + (%u) already using %s",
> Johan: Is this a resource abort?
>                           ccbIdLongDnGuard, immLongDnsAllowed.c_str());
> -                    LOG_IN("ERR_BUSY: Other Ccb (%u) already using %s",
> +                    LOG_IN("IMM: ERR_BUSY: Other Ccb (%u) already using
> + %s",
> Johan: Should this also be set in the error string in addition to logging?
>                           ccbIdLongDnGuard, immLongDnsAllowed.c_str());
>                       err = SA_AIS_ERR_BUSY;
>                   } else {
> @@ -8730,6 +8770,7 @@ ImmModel::ccbObjectModify(const ImmsvOmC
>                       err = SA_AIS_ERR_FAILED_OPERATION;
>                       //Let the timeout handling take care of it on other 
> nodes.
>                       //This really needs to be tested! But how ?
> +                    setCcbErrorString(ccb, "IMM: Resource abort: Lost
> + connection with implementer");
>                   } else {
>                       *continuationId = sLastContinuationId;
>                   }
> @@ -8751,7 +8792,7 @@ ImmModel::ccbObjectModify(const ImmsvOmC
>                       "implementer and flag SA_IMM_CCB_REGISTERED_OI is set",
>                       objectName.c_str());
>                   setCcbErrorString(ccb,
> -                        "ERR_NOT_EXIST: object '%s' exist but "
> +                        "IMM: ERR_NOT_EXIST: object '%s' exist but "
> Johan: This should be a resource abort.
>                           "no implementer (which is required)",
>                           objectName.c_str());
>                   err = SA_AIS_ERR_NOT_EXIST; @@ -8788,6 +8829,7 @@ 
> ImmModel::ccbObjectModify(const ImmsvOmC
>           if(chainedOp) {
>               err = SA_AIS_ERR_FAILED_OPERATION;
>               ccb->mVeto = err; //Corrupted chain => corrupted ccb
> +            setCcbErrorString(ccb, "IMM: Resource abort: Corrupted
> + CCB");
>           } else { //First op on this object => ccb can survive
>               if(afim) {
>                   //Delete the cloned afim.
> @@ -8893,6 +8935,7 @@ ImmModel::ccbObjectDelete(const ImmsvOmC
>           LOG_NO("ERR_FAILED_OPERATION: ccb %u is in an error state "
>               "rejecting ccbObjectDelete operation ", ccbId);
>           err = SA_AIS_ERR_FAILED_OPERATION;
> +        setCcbErrorString(ccb, "IMM: Resource abort: CCB in error
> + state");
>           goto ccbObjectDeleteExit;
>       }
>       
> @@ -8900,6 +8943,7 @@ ImmModel::ccbObjectDelete(const ImmsvOmC
>           LOG_WA("ERR_FAILED_OPERATION: ccb %u is not in an expected state:%u 
> "
>               "rejecting ccbObjectDelete operation ", ccbId, ccb->mState);
>           err = SA_AIS_ERR_FAILED_OPERATION;
> +        setCcbErrorString(ccb, "IMM: Resource abort: CCB is not in an
> + expected state");
>           goto ccbObjectDeleteExit;
>       }
>       
> @@ -8923,6 +8967,7 @@ ImmModel::ccbObjectDelete(const ImmsvOmC
>       if(adminOwner->mId !=  ccb->mAdminOwnerId) {
>           LOG_WA("ERR_FAILED_OPERATION: Inconsistency between Ccb and 
> AdminOwner");
>           err = SA_AIS_ERR_FAILED_OPERATION;
> +        setCcbErrorString(ccb, "IMM: Resource abort: Inconsistency
> + between CCB and AdminOwner");
>           goto ccbObjectDeleteExit;
>       }
>       
> @@ -8956,6 +9001,7 @@ ImmModel::ccbObjectDelete(const ImmsvOmC
>                   ccb->mVeto = err;
>                   LOG_WA("ERR_FAILED_OPERATION: Persistent back end is down "
>                          "ccb %u is aborted", ccbId);
> +                setCcbErrorString(ccb, "IMM: Resource abort: PBE is
> + down");
>               } else {
>                   /* Pristine ccb can not start because PBE down */
>                   TRACE_5("ERR_TRY_AGAIN: Persistent back end is down"); @@ 
> -9176,7 +9222,7 @@ ImmModel::deleteObject(ObjectMap::iterat
>           /* Prevent delete of imm service objects, even when there is no OI 
> for them */
>           if(oi->first == immManagementDn || oi->first == immObjectDn) {
>               setCcbErrorString(ccb,
> -                "ERR_BAD_OPERATION: Imm not allowing delete of object '%s'",
> +                "IMM: ERR_BAD_OPERATION: Imm not allowing delete of
> + object '%s'",
> Johan: Could this be a validation abort since the user is trying to do 
> something IMM doesn't allow?
>                   oi->first.c_str());
>               return SA_AIS_ERR_BAD_OPERATION;
>           }
> @@ -9191,7 +9237,7 @@ ImmModel::deleteObject(ObjectMap::iterat
>                       "and flag SA_IMM_CCB_REGISTERED_OI is set",
>                       oi->first.c_str());
>                   setCcbErrorString(ccb,
> -                        "ERR_NOT_EXIST: object '%s' exist but "
> +                        "IMM: ERR_NOT_EXIST: object '%s' exist but "
> Johan: This should be a resource abort.
>                           "no implementer (which is required)",
>                           oi->first.c_str());
>                   return SA_AIS_ERR_NOT_EXIST; @@ -9364,24 +9410,21 @@ 
> ImmModel::deleteObject(ObjectMap::iterat
>   }
>   
>   void
> -ImmModel::setCcbErrorString(CcbInfo *ccb, const char *errorString, ...) -{
> +ImmModel::setCcbErrorString(CcbInfo *ccb, const char *errorString,
> +va_list vl) {
>       int errLen = strlen(errorString) + 1;
>       char *fmtError = (char *)malloc(errLen);
>       int len;
> -    va_list vl;
> -
> -    va_start(vl, errorString);
> -    len = vsnprintf(fmtError, errLen, errorString, vl);
> -    va_end(vl);
> +    va_list args;
> +
> +    va_copy(args, vl);
> +    len = vsnprintf(fmtError, errLen, errorString, args);
> +    va_end(args);
>   
>       osafassert(len >= 0);
>       len++;     /* Reserve one byte for null-terminated sign '\0' */
>       if(len > errLen) {
>           fmtError = (char *)realloc(fmtError, len);
> -        va_start(vl, errorString);
>           osafassert(vsnprintf(fmtError, len, errorString, vl) >= 0);
> -        va_end(vl);
>       }
>   
>       unsigned int ix=0;
> @@ -9411,6 +9454,16 @@ ImmModel::setCcbErrorString(CcbInfo *ccb
>       }
>   }
>   
> +void
> +ImmModel::setCcbErrorString(CcbInfo *ccb, const char *errorString, ...)
> +{
> +    va_list vl;
> +
> +    va_start(vl, errorString);
> +    setCcbErrorString(ccb, errorString, vl);
> +    va_end(vl);
> +}
> +
>   bool
>   ImmModel::hasLocalClassAppliers(ClassInfo* classInfo)  { @@ -9451,6 +9504,9 
> @@ ImmModel::ccbWaitForDeleteImplAck(SaUint
>           TRACE_5("CCb %u terminated during ccbObjectDelete processing, "
>               "ccb must be aborted", ccbId);
>           *err = SA_AIS_ERR_FAILED_OPERATION;
> +        if(i1 != sCcbVector.end()) {
> +            setCcbErrorString(*i1, "IMM: Resource abort: CCB is terminated 
> during ccbObjectDelete processing");
> +        }
>           return false;
>       }
>       CcbInfo* ccb = *i1;
> @@ -9515,6 +9571,9 @@ ImmModel::ccbWaitForCompletedAck(SaUint3
>           TRACE_5("Ccb %u terminated during ccbCompleted processing, "
>               "ccb must be aborted", ccbId);
>           *err = SA_AIS_ERR_FAILED_OPERATION;
> +        if(i1 != sCcbVector.end()) {
> +            setCcbErrorString(*i1, "IMM: Resource abort: CCB is terminated");
> +        }
>           return false;
>       }
>       CcbInfo* ccb = *i1;
> @@ -9614,6 +9673,7 @@ ImmModel::ccbWaitForCompletedAck(SaUint3
>               *err = ccb->mVeto;
>               LOG_WA("ERR_FAILED_OPERATION: Persistent back end is down "
>                              "ccb %u is aborted", ccbId);
> +            setCcbErrorString(ccb, "IMM: Resource abort: PBE is down");
>           }
>       }
>   
> @@ -9644,6 +9704,7 @@ ImmModel::ccbObjDelContinuation(immsv_oi
>           LOG_WA("Not a proper object name: %s", objectName.c_str());
>           if(ccb->mVeto == SA_AIS_OK) {
>               ccb->mVeto = SA_AIS_ERR_FAILED_OPERATION;
> +            setCcbErrorString(ccb, "IMM: Validation abort: Not a proper
> + object name");
>           }
>           return;
>       }
> @@ -9657,6 +9718,7 @@ ImmModel::ccbObjDelContinuation(immsv_oi
>               if((rsp->result == SA_AIS_OK) && ccb->isActive()) {
>                   LOG_NO("Vetoing ccb %u with ERR_FAILED_OPERATION", ccbId);
>                   ccb->mVeto = SA_AIS_ERR_FAILED_OPERATION;
> +                setCcbErrorString(ccb, "IMM: Resource abort: CCB is
> + interrupted in augmentation");
>               }
>           }
>           ccb->mOriginatingConn = ccb->mAugCcbParent->mOriginatingConn;
> @@ -9677,6 +9739,7 @@ ImmModel::ccbObjDelContinuation(immsv_oi
>               objectName.c_str());
>           if(ccb->mVeto == SA_AIS_OK) {
>               ccb->mVeto = SA_AIS_ERR_FAILED_OPERATION;
> +            setCcbErrorString(ccb, "IMM: Validation abort: Object is
> + not found in CCB");
>           }
>       } else {
>           osafassert(omuti->second->mWaitForImplAck);
> @@ -9694,6 +9757,7 @@ ImmModel::ccbObjDelContinuation(immsv_oi
>                       "implementer returned error, Ccb aborted with error: 
> %u",
>                        rsp->result);
>                   ccb->mVeto = SA_AIS_ERR_FAILED_OPERATION;
> +                setCcbErrorString(ccb, "IMM: Validation abort:
> + Implementer returned error: ", rsp->result);
>                   //TODO: This is perhaps more drastic than the specification
>                   //demands. We are here aborting the entire Ccb, whereas the 
> spec
>                   //seems to allow for a non-ok returnvalue from implementer 
> @@ -9768,6 +9832,7 @@ ImmModel::ccbCompletedContinuation(immsv
>               LOG_WA("Completed continuation: implementer '%u' Not found "
>                   "in ccb %u aborting ccb", rsp->implId, ccbId);
>               ccb->mVeto = SA_AIS_ERR_FAILED_OPERATION;
> +            setCcbErrorString(ccb, "IMM: Resource abort: Implementer
> + not found");
>           } else {
>               LOG_WA("Completed continuation: implementer '%u' Not found "
>                   "in ccb %u in state(%u), can not abort", rsp->implId, @@ 
> -9811,17 +9876,20 @@ ImmModel::ccbCompletedContinuation(immsv
>                       case SA_AIS_ERR_BAD_OPERATION:
>                           LOG_NO("Validation error (BAD_OPERATION) reported 
> by implementer '%s', "
>                                  "Ccb %u will be aborted", 
> ix->second->mImplementer->mImplementerName.c_str(), ccbId);
> +                        setCcbErrorString(ccb, "IMM: Validation abort:
> + Completed validation fails (ERR_BAD_OPERATION)");
>                           break;
>   
>                       case SA_AIS_ERR_NO_MEMORY:
>                       case SA_AIS_ERR_NO_RESOURCES:
>                              LOG_NO("Resource error %u reported by 
> implementer '%s', Ccb %u will be aborted",
>                                  rsp->result, 
> ix->second->mImplementer->mImplementerName.c_str(), ccbId);
> +                           setCcbErrorString(ccb, "IMM: Validation
> + abort: Completed validation fails (Error code: %u)", rsp->result);
>                           break;
>   
>                      default:
>                              LOG_NO("Invalid error reported implementer '%s', 
> Ccb %u will be aborted",
>                                  
> ix->second->mImplementer->mImplementerName.c_str(), ccbId);
> +                           setCcbErrorString(ccb, "IMM: Validation
> + abort: Completed validation fails (Error code: %u)", rsp->result);
>                   }
>                   ccb->mVeto = SA_AIS_ERR_FAILED_OPERATION;
>               }
> @@ -9906,6 +9974,7 @@ ImmModel::ccbObjCreateContinuation(SaUin
>               invocation, ccbId);
>           if(ccb->mVeto == SA_AIS_OK) {
>               ccb->mVeto = SA_AIS_ERR_FAILED_OPERATION;
> +            setCcbErrorString(ccb, "IMM: Resource abort: Create
> + invocation is not found in CCB");
>           }
>       } else {
>           osafassert(omuti->second->mWaitForImplAck);
> @@ -9922,6 +9991,7 @@ ImmModel::ccbObjCreateContinuation(SaUin
>               if((error == SA_AIS_OK) && ccb->isActive()) {
>                   LOG_IN("Vetoing ccb %u with ERR_FAILED_OPERATION", ccbId);
>                   error = SA_AIS_ERR_FAILED_OPERATION;
> +                setCcbErrorString(ccb, "IMM: Resource abort: CCB was
> + interrupted in augmentation");
>               }
>           }
>           ccb->mOriginatingConn = ccb->mAugCcbParent->mOriginatingConn;
> @@ -9941,6 +10011,7 @@ ImmModel::ccbObjCreateContinuation(SaUin
>               "implementer returned error, Ccb aborted with error: %u",
>               error);
>           ccb->mVeto = SA_AIS_ERR_FAILED_OPERATION;
> +        setCcbErrorString(ccb, "IMM: Validation abort: Implementer
> + returned error: %u", error);
>           //TODO: This is perhaps more drastic than the specification demands.
>           //We are here aborting the entire Ccb, whereas the spec seems to 
> allow
>           //for a non-ok returnvalue from implementer (in this callback) to 
> @@ -9990,6 +10061,7 @@ ImmModel::ccbObjModifyContinuation(SaUin
>               invocation, ccbId);
>           if(ccb->mVeto == SA_AIS_OK) {
>               ccb->mVeto = SA_AIS_ERR_FAILED_OPERATION;
> +            setCcbErrorString(ccb, "IMM: Resource abort: Mofidy
> + invocation is not found in CCB");
> Johan: Change Mofidy to Modify
>           }
>       } else {
>           osafassert(omuti->second->mWaitForImplAck);
> @@ -10006,6 +10078,7 @@ ImmModel::ccbObjModifyContinuation(SaUin
>               if((error == SA_AIS_OK) && ccb->isActive()) {
>                   LOG_IN("Vetoing ccb %u with ERR_FAILED_OPERATION", ccbId);
>                   error = SA_AIS_ERR_FAILED_OPERATION;
> +                setCcbErrorString(ccb, "IMM: Resource abort: CCB was
> + interrupted in augmentation");
>               }
>           }
>           ccb->mOriginatingConn = ccb->mAugCcbParent->mOriginatingConn;
> @@ -10024,6 +10097,7 @@ ImmModel::ccbObjModifyContinuation(SaUin
>           LOG_IN("ImmModel::ccbObjModifyContinuation: "
>               "implementer returned error, Ccb aborted with error: %u", 
> error);
>           ccb->mVeto = SA_AIS_ERR_FAILED_OPERATION;
> +        setCcbErrorString(ccb, "IMM: Validation abort: Implementer
> + returned error: %u", error);
>           //TODO: This is perhaps more drastic than the specification demands.
>           //We are here aborting the entire Ccb, whereas the spec seems to 
> allow
>           //for a non-ok returnvalue from implementer (in this callback) to 
> 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
> @@ -273,6 +273,11 @@ public:
>       void                setCcbErrorString(
>                                             CcbInfo *ccb,
>                                             const char *errorString,
> +                                          va_list vl);
> +
> +    void                setCcbErrorString(
> +                                          CcbInfo *ccb,
> +                                          const char *errorString,
>                                             ...);
>   
>       bool                hasLocalClassAppliers(ClassInfo* classInfo);
> 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
> @@ -3604,7 +3604,12 @@ static void immnd_evt_proc_ccb_obj_modif
>               IMMSV_ATTR_NAME_LIST strList;
>               
>               if (evt->info.ccbUpcallRsp.result != SA_AIS_OK) {
> -                     evt->info.ccbUpcallRsp.result = 
> SA_AIS_ERR_FAILED_OPERATION;
> +                     if(evt->info.ccbUpcallRsp.result != 
> SA_AIS_ERR_FAILED_OPERATION) {
> +                             immModel_setCcbErrorString(cb, 
> evt->info.ccbUpcallRsp.ccbId,
> +                                             "IMM: Resource abort: Upcall 
> failed with error code: %u",
> +                                             evt->info.ccbUpcallRsp.result);
> +                             evt->info.ccbUpcallRsp.result = 
> SA_AIS_ERR_FAILED_OPERATION;
> +                     }
>                       if (evt->info.ccbUpcallRsp.errorString.size) {
>                               osafassert(evt->type == 
> IMMND_EVT_A2ND_CCB_OBJ_MODIFY_RSP_2);
>                               strList.next = NULL;
> @@ -3674,7 +3679,12 @@ static void immnd_evt_proc_ccb_obj_creat
>               IMMSV_ATTR_NAME_LIST strList;
>   
>               if (evt->info.ccbUpcallRsp.result != SA_AIS_OK) {
> -                     evt->info.ccbUpcallRsp.result = 
> SA_AIS_ERR_FAILED_OPERATION;
> +                     if(evt->info.ccbUpcallRsp.result != 
> SA_AIS_ERR_FAILED_OPERATION) {
> +                             immModel_setCcbErrorString(cb, 
> evt->info.ccbUpcallRsp.ccbId,
> +                                             "IMM: Resource abort: Upcall 
> failed with error code: %u",
> +                                             evt->info.ccbUpcallRsp.result);
> +                             evt->info.ccbUpcallRsp.result = 
> SA_AIS_ERR_FAILED_OPERATION;
> +                     }
>                       if (evt->info.ccbUpcallRsp.errorString.size) {
>                               osafassert(evt->type == 
> IMMND_EVT_A2ND_CCB_OBJ_CREATE_RSP_2);
>                               strList.next = NULL;
> @@ -5902,6 +5912,8 @@ static void immnd_evt_proc_object_create
>                          should prevent any apply to succeed.
>                       */
>                       err = SA_AIS_ERR_FAILED_OPERATION;
> +                     immModel_setCcbErrorString(cb, 
> evt->info.objCreate.ccbId,
> +                                     "IMM: Resource abort: PBE is down");
>                       immnd_proc_global_abort_ccb(cb, 
> evt->info.objCreate.ccbId);
>               } else {
>                       memset(&send_evt, '\0', sizeof(IMMSV_EVT)); @@ -5921,6 
> +5933,8 @@ static void immnd_evt_proc_object_create
>                               LOG_ER("Upcall over MDS for ccbObjectCreate "
>                                      "to PBE failed! - aborting");
>                               err = SA_AIS_ERR_FAILED_OPERATION;
> +                             immModel_setCcbErrorString(cb, 
> evt->info.objCreate.ccbId,
> +                                             "IMM: Resource abort: Upcall 
> over MDS to PBE failed");
>                               immnd_proc_global_abort_ccb(cb, 
> evt->info.objCreate.ccbId);
>                       }
>                       implHandle = 0LL;
> @@ -5942,6 +5956,8 @@ static void immnd_evt_proc_object_create
>                               LOG_WA("Client died");
>                               err = SA_AIS_ERR_FAILED_OPERATION;
>                               delayedReply = SA_FALSE;
> +                             immModel_setCcbErrorString(cb, 
> evt->info.objCreate.ccbId,
> +                                             "IMM: Resource abort: Client 
> died");
>                       } else {
>                               memset(&send_evt, '\0', sizeof(IMMSV_EVT));
>                               send_evt.type = IMMSV_EVT_TYPE_IMMA; @@ -5961,6 
> +5977,8 @@ static void immnd_evt_proc_object_create
>                                                      
> oi_cl_node->agent_mds_dest, &send_evt) != NCSCC_RC_SUCCESS) {
>                                       LOG_ER("Agent upcall over MDS for 
> ccbObjectCreate failed");
>                                       err = SA_AIS_ERR_FAILED_OPERATION;
> +                                     immModel_setCcbErrorString(cb, 
> evt->info.objCreate.ccbId,
> +                                                     "IMM: Resource abort: 
> Agent upcall over MDS failed");
>                               }
>                       }
>               }
> @@ -6133,6 +6151,8 @@ static void immnd_evt_proc_object_modify
>                          should prevent any apply to succeed.
>                       */
>                       err = SA_AIS_ERR_FAILED_OPERATION;
> +                     immModel_setCcbErrorString(cb, 
> evt->info.objModify.ccbId,
> +                                     "IMM: Resource abort: PBE is down");
>                       immnd_proc_global_abort_ccb(cb, 
> evt->info.objModify.ccbId);
>               } else {
>                       memset(&send_evt, '\0', sizeof(IMMSV_EVT)); @@ -6153,6 
> +6173,8 @@ static void immnd_evt_proc_object_modify
>                               LOG_ER("Upcall over MDS for ccbObjectModify "
>                                       "to PBE failed! - aborting");
>                               err = SA_AIS_ERR_FAILED_OPERATION;
> +                             immModel_setCcbErrorString(cb, 
> evt->info.objModify.ccbId,
> +                                             "IMM: Resource abort: Upcall 
> over MDS to PBE failed");
>                               immnd_proc_global_abort_ccb(cb, 
> evt->info.objModify.ccbId);
>                       }
>                       implHandle = 0LL;
> @@ -6172,9 +6194,11 @@ static void immnd_evt_proc_object_modify
>                       immnd_client_node_get(cb, implHandle, &oi_cl_node);
>                       osafassert(oi_cl_node != NULL);
>                       if (oi_cl_node->mIsStale) {
> -                             LOG_WA("OI Client went down so nod modify 
> upcall");
> +                             LOG_WA("OI Client went down so no modify 
> upcall");
>                               err = SA_AIS_ERR_FAILED_OPERATION;
>                               delayedReply = SA_FALSE;
> +                             immModel_setCcbErrorString(cb, 
> evt->info.objModify.ccbId,
> +                                             "IMM: Resource abort: OI client 
> went down");
>                       } else {
>                               memset(&send_evt, '\0', sizeof(IMMSV_EVT));
>                               send_evt.type = IMMSV_EVT_TYPE_IMMA; @@ -6197,6 
> +6221,8 @@ static void immnd_evt_proc_object_modify
>                                                      
> oi_cl_node->agent_mds_dest, &send_evt) != NCSCC_RC_SUCCESS) {
>                                       LOG_ER("Agent upcall over MDS for 
> ccbObjectModify failed");
>                                       err = SA_AIS_ERR_FAILED_OPERATION;
> +                                     immModel_setCcbErrorString(cb, 
> evt->info.objModify.ccbId,
> +                                                     "IMM: Resource abort: 
> Agent upcall over MDS failed");
>                               }
>                       }
>               }
> @@ -6711,6 +6737,10 @@ static void immnd_evt_ccb_abort(IMMND_CB
>                       send_evt.info.imma.info.errRsp.error =
>                           timeout ? SA_AIS_ERR_TIMEOUT : 
> SA_AIS_ERR_FAILED_OPERATION;
>   
> +                     if(send_evt.info.imma.info.errRsp.error == 
> SA_AIS_ERR_FAILED_OPERATION) {
> +                             immModel_setCcbErrorString(cb, ccbId, "IMM: 
> Resource abort:");
> Johan: Should you add any information here, like "..(ERR FAILED OPERATION)"?
> +                     }
> +
>                       send_evt.info.imma.info.errRsp.errStrings =
>                               immModel_ccbGrabErrStrings(cb, ccbId);
>                       if(send_evt.info.imma.info.errRsp.errStrings) { @@ 
> -6825,6 +6855,8 @@ static void immnd_evt_proc_object_delete
>                          should prevent any apply to succeed.
>                       */
>                       err = SA_AIS_ERR_FAILED_OPERATION;
> +                     immModel_setCcbErrorString(cb, 
> evt->info.objDelete.ccbId,
> +                                     "IMM: Resource abort: PBE is down");
>                       immnd_proc_global_abort_ccb(cb, 
> evt->info.objDelete.ccbId);                     
>               } else {
>                       /* We have obtained PBE handle & dest info for PBE.
> @@ -6850,6 +6882,8 @@ static void immnd_evt_proc_object_delete
>                                               "to PBE failed! - aborting ccb 
> %u",
>                                               evt->info.objDelete.ccbId);
>                                       err = SA_AIS_ERR_FAILED_OPERATION;
> +                                     immModel_setCcbErrorString(cb, 
> evt->info.objDelete.ccbId,
> +                                                     "IMM: Resource abort: 
> Upcall over MDS to PBE failed");
>                                       immnd_proc_global_abort_ccb(cb, 
> evt->info.objDelete.ccbId);
>                               }
>                       }
> @@ -6885,6 +6919,8 @@ static void immnd_evt_proc_object_delete
>                                       /* This should cause the ccb-operation 
> to timeout on wait for the reply. */
>                                       err = SA_AIS_ERR_FAILED_OPERATION;
>                                       delayedReply = SA_FALSE;
> +                                     immModel_setCcbErrorString(cb, 
> evt->info.objDelete.ccbId,
> +                                                     "IMM: Resource abort: 
> Client went down");
>                               } else {
>                                       /* Generate an implementer upcall for 
> each deleted config object.
>                                          No implementer upcalls are generated 
> for any runtime objects @@ -6906,6 +6942,8 @@ static void 
> immnd_evt_proc_object_delete
>                                               /* This should cause the 
> ccb-operation to timeout. */
>                                               err = 
> SA_AIS_ERR_FAILED_OPERATION;
>                                               delayedReply = SA_FALSE;
> +                                             immModel_setCcbErrorString(cb, 
> evt->info.objDelete.ccbId,
> +                                                             "IMM: Resource 
> abort: Upcall over MDS failed");
>                                       }
>                               }
>                       }       /*for */
> @@ -7484,6 +7522,8 @@ static void immnd_evt_proc_ccb_apply(IMM
>                                       LOG_WA("IMMND - Client went down so no 
> response");
>                                       err = SA_AIS_ERR_FAILED_OPERATION;
>                                       delayedReply = SA_FALSE;
> +                                     immModel_setCcbErrorString(cb, 
> evt->info.ccbId,
> +                                                     "IMM: Resource abort: 
> Client went down");
>                               } else {
>                                       send_evt.info.imma.info.ccbCompl.ccbId 
> = evt->info.ccbId;
>                                       send_evt.info.imma.info.ccbCompl.implId 
> = implIdArr[ix]; @@ -7498,6 +7538,8 @@ static void 
> immnd_evt_proc_ccb_apply(IMM
>                                               err = 
> SA_AIS_ERR_FAILED_OPERATION;
>                                               /* should abort the entire ccb 
> */
>                                               delayedReply = SA_FALSE;
> +                                             immModel_setCcbErrorString(cb, 
> evt->info.ccbId,
> +                                                             "IMM: Resource 
> abort: Upcall over MDS failed");
>                                       } else {
>                                               TRACE_2("IMMND UPCALL TO OI, 
> SEND SUCCEEDED");
>                                       }
> 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
> @@ -423,6 +423,12 @@ extern "C" {
>               const struct ImmsvAdminOperationParam *reqparams,
>               struct ImmsvAdminOperationParam **rparams);
>   
> +     void
> +     immModel_setCcbErrorString(IMMND_CB *cb,
> +             SaUint32T ccbId,
> +             const char *errorString,
> +             ...);
> +
>   #ifdef __cplusplus
>   }
>   #endif
>
> ------------------------------------------------------------------------------
> _______________________________________________
> Opensaf-devel mailing list
> Opensaf-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/opensaf-devel
>
> ------------------------------------------------------------------------------
> _______________________________________________
> Opensaf-devel mailing list
> Opensaf-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/opensaf-devel
>



------------------------------------------------------------------------------
Monitor Your Dynamic Infrastructure at Any Scale With Datadog!
Get real-time metrics from all of your servers, apps and tools
in one place.
SourceForge users - Click here to start your Free Trial of Datadog now!
http://pubads.g.doubleclick.net/gampad/clk?id=241902991&iu=/4140
_______________________________________________
Opensaf-devel mailing list
Opensaf-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to