Beispiel #1
0
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);
}