static CMPIContext* prepareUpcall(CMPIContext *ctx) { /* used to invoke the internal provider in upcalls, otherwise we will * * be routed here (interOpProvider) again*/ CMPIContext *ctxLocal; ctxLocal = native_clone_CMPIContext(ctx); CMPIValue val; val.string = sfcb_native_new_CMPIString("$DefaultProvider$", NULL,0); ctxLocal->ft->addEntry(ctxLocal, "rerouteToProvider", &val, CMPI_string); return ctxLocal; }
int refillRetryQ (const CMPIContext * ctx) { _SFCB_ENTER(TRACE_INDPROVIDER, "refillRetryQ"); int qfill=0; if (RQhead==NULL) { // The queue is empty, check if there are instances to be restored CMPIObjectPath * op=CMNewObjectPath(_broker,"root/interop","SFCB_IndicationElement",NULL); CMPIEnumeration * enm = _broker->bft->enumerateInstances(_broker, ctx, op, NULL, NULL); while(enm && enm->ft->hasNext(enm, NULL)) { // get the properties from the repo instance CMPIData inst=CMGetNext(enm,NULL); CMPIData indID=CMGetProperty(inst.value.inst,"indicationID",NULL); CMPIData rcount=CMGetProperty(inst.value.inst,"retryCount",NULL); CMPIData last=CMGetProperty(inst.value.inst,"lastDelivery",NULL); CMPIData ind=CMGetProperty(inst.value.inst,"ind",NULL); CMPIData sub=CMGetProperty(inst.value.inst,"sub",NULL); CMPIData ld=CMGetProperty(inst.value.inst,"ld",NULL); _SFCB_TRACE(1,("--- Requeueing indication id:%d",indID.value.Int)); // Rebuild the queue element RTElement *element; element = (RTElement *) malloc(sizeof(*element)); element->instanceID=indID.value.Int; element->lasttry=last.value.Int; element->count=rcount.value.Int; element->ind=ind.value.ref->ft->clone(ind.value.ref,NULL); element->ref=ld.value.ref->ft->clone(ld.value.ref,NULL); element->sub=sub.value.ref->ft->clone(sub.value.ref,NULL); CMPIObjectPath * indele=CMGetObjectPath(inst.value.inst,NULL); element->SFCBIndEle=indele->ft->clone(indele,NULL); // call enq enqRetry(element,ctx,0); qfill=1; } // spawn thread if we queued anything if ((qfill == 1 ) && (retryRunning == 0)) { retryRunning=1; _SFCB_TRACE(1,("--- Starting retryExport thread")); pthread_attr_init(&tattr); pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); CMPIContext * pctx = native_clone_CMPIContext(ctx); pthread_create(&t, &tattr,&retryExport,(void *) pctx); } } _SFCB_RETURN(0); }
void ElementCapabilitiesInitInstances(const CMPIContext *ctx) { CMPIObjectPath *op = NULL, *opLeft = NULL, *opRight = NULL, *left = NULL, *right = NULL; CMPIValue val; CMPIEnumeration *enm = NULL; CMPIInstance *ci = NULL; CMPIContext *ctxLocal; ctxLocal = native_clone_CMPIContext(ctx); val.string = sfcb_native_new_CMPIString("$DefaultProvider$", NULL, 0); ctxLocal->ft->addEntry(ctxLocal, "rerouteToProvider", &val, CMPI_string); op = CMNewObjectPath(_broker, "root/interop", "SFCB_ElementCapabilities", NULL); ci = CMNewInstance(_broker, op, NULL); opLeft = CMNewObjectPath(_broker, "root/interop", "CIM_IndicationService", NULL); enm = CBEnumInstanceNames(_broker, ctx, opLeft, NULL); left = CMGetNext(enm, NULL).value.ref; opRight = CMNewObjectPath(_broker, "root/interop", "SFCB_IndicationServiceCapabilities", NULL); enm = CBEnumInstanceNames(_broker, ctx, opRight, NULL); right = CMGetNext(enm, NULL).value.ref; CMAddKey(op, "ManagedElement", &left, CMPI_ref); CMAddKey(op, "Capabilities", &right, CMPI_ref); CMSetProperty(ci, "ManagedElement", &left, CMPI_ref); CMSetProperty(ci, "Capabilities", &right, CMPI_ref); CBCreateInstance(_broker, ctxLocal, op, ci, NULL); CMRelease(ctxLocal); return; }
CMPIStatus IndCIMXMLHandlerInvokeMethod(CMPIMethodMI * mi, const CMPIContext *ctx, const CMPIResult *rslt, const CMPIObjectPath * ref, const char *methodName, const CMPIArgs * in, CMPIArgs * out) { _SFCB_ENTER(TRACE_INDPROVIDER, "IndCIMXMLHandlerInvokeMethod"); CMPIStatus st = { CMPI_RC_OK, NULL }; CMPIStatus circ = { CMPI_RC_OK, NULL }; struct timeval tv; struct timezone tz; static unsigned int indID=1; if (interOpNameSpace(ref, &st) == 0) _SFCB_RETURN(st); if (strcasecmp(methodName, "_deliver") == 0) { // On the first indication, check if reliable indications are enabled. if (RIEnabled == -1) { CMPIObjectPath *op=CMNewObjectPath(_broker,"root/interop","CIM_IndicationService",NULL); CMPIEnumeration *isenm = _broker->bft->enumerateInstances(_broker, ctx, op, NULL, NULL); CMPIData isinst=CMGetNext(isenm,NULL); CMPIData mc=CMGetProperty(isinst.value.inst,"DeliveryRetryAttempts",NULL); RIEnabled=mc.value.uint16; } CMPIInstance *indo=CMGetArg(in,"indication",NULL).value.inst; CMPIInstance *ind=CMClone(indo,NULL); CMPIContext *ctxLocal=NULL; CMPIObjectPath *iop=NULL,*subop=NULL; CMPIInstance *sub=NULL; if (RIEnabled) { ctxLocal = prepareUpcall((CMPIContext *) ctx); // Set the indication sequence values iop=CMGetObjectPath(ind,NULL); CMAddKey(iop,"SFCB_IndicationID",&indID,CMPI_uint32); CMSetProperty(ind,"SFCB_IndicationID",&indID,CMPI_uint32); // Prevent this property from showing up in the indication filterFlagProperty(ind, "SFCB_IndicationID"); sub=CMGetArg(in,"subscription",NULL).value.inst; CMPIData handler=CMGetProperty(sub, "Handler", &st); CMPIObjectPath *hop=handler.value.ref; CMPIInstance *hdlr=CBGetInstance(_broker, ctxLocal, hop, NULL, &st); // Build the complete sequence context // Get the stub from the handler CMPIString *context = CMGetProperty(hdlr, "SequenceContext", &st).value.string; // and add the sfcb start time char *cstr=malloc( (strlen(context->ft->getCharPtr(context,NULL)) + strlen(sfcBrokerStart) + 1) * sizeof(char)); sprintf(cstr,"%s%s",context->ft->getCharPtr(context,NULL),sfcBrokerStart); context = sfcb_native_new_CMPIString(cstr, NULL, 0); // and put it in the indication CMSetProperty(ind, "SequenceContext", &context, CMPI_string); free(cstr); CMRelease(context); // Get the proper sequence number CMPIValue lastseq = CMGetProperty(hdlr, "LastSequenceNumber", &st).value; lastseq.sint64++; // Handle wrapping of the signed int if (lastseq.sint64 < 0) lastseq.sint64=0; // Update the last used number in the handler CMSetProperty(hdlr, "LastSequenceNumber", &lastseq.sint64, CMPI_sint64); CBModifyInstance(_broker, ctxLocal, hop, hdlr, NULL); // And the indication CMSetProperty(ind, "SequenceNumber", &lastseq, CMPI_sint64); } // Now send the indication st = deliverInd(ref, in, ind); if (st.rc != 0) { if (RIEnabled){ _SFCB_TRACE(1,("--- Indication delivery failed, adding to retry queue")); // Indication delivery failed, send to retry queue // build an element RTElement *element; element = (RTElement *) malloc(sizeof(*element)); element->ref=ref->ft->clone(ref,NULL); // Get the OP of the subscription and indication subop=CMGetObjectPath(sub,NULL); element->sub=subop->ft->clone(subop,NULL); element->ind=iop->ft->clone(iop,NULL); // Store other attrs element->instanceID=indID; element->count=0; gettimeofday(&tv, &tz); element->lasttry=tv.tv_sec; // Push the indication to the repo CBCreateInstance(_broker, ctxLocal, iop, ind, &circ); if (circ.rc != 0) { mlogf(M_ERROR,M_SHOW,"Pushing indication instance to repository failed, rc:%d\n",circ.rc); } indID++; // Add it to the retry queue enqRetry(element,ctx,1); // And launch the thread if it isn't already running pthread_attr_init(&tattr); pthread_attr_setdetachstate(&tattr, PTHREAD_CREATE_DETACHED); if (retryRunning == 0) { retryRunning = 1; _SFCB_TRACE(1,("--- Starting retryExport thread")); CMPIContext *pctx = native_clone_CMPIContext(ctx); pthread_create(&t, &tattr, &retryExport, (void *) pctx); } CMRelease(ctxLocal); } } CMRelease(ind); } else { printf("--- ClassProvider: Invalid request %s\n", methodName); st.rc = CMPI_RC_ERR_METHOD_NOT_FOUND; } _SFCB_RETURN(st); }