static void rio_cache_write(loService *se, loUpdList *upl)
{
 HRESULT  *errors = upl->errors;
 VARIANT *variant = upl->variant;
 loTagPair *tpl = upl->tagpair;
 loTagEntry *tags = se->tags;
 unsigned ii, items_fail = 0, items_clamp = 0;
 FILETIME ft;
 VARIANT var; VARIANTINIT(&var);
 loTagValue *ts;
 se->driver.ldCurrentTime(&se->cactx, &ft);

// UL_INFO((LOGID, "rio_cache_write() in %d", upl->master_err));

 if (!(ts = loCacheLock(se))) return;

 for(ii = upl->used; ii--; tpl++, errors++, variant++)
   if (tpl->tpTi)
     {
      loTagValue *tv = &ts[tpl->tpTi];
      VARTYPE cvt = taVTYPE(&tags[tpl->tpTi].attr);
      HRESULT hr;

      if (V_VT(variant) != VT_EMPTY &&
          V_VT(variant) != cvt &&
          S_OK != (hr =
#if 0
              VARIANTCHANGEt(variant, variant, upl->rctx.cta, cvt)
#else
              VariantChangeType(variant, variant, 0, cvt)
#endif
                  ))
        {
         *errors = LO_E_BADTYPE(hr); 
         items_fail = 1;
        }
      else if (tv->tvTi) 
        {
         *errors = OPC_S_CLAMP;
         items_fail = 1;
        }
      else
        {
         VARIANT tvmp;
         tv->tvTi = tpl->tpTi;
         tvmp = tv->tvValue;
         tv->tvValue = *variant;
         *variant = tvmp;
         tv->tvState.tsTime = ft;
         tv->tvState.tsError = *errors = loOPC_S_CLAMP;
         tv->tvState.tsQuality = OPC_QUALITY_LOCAL_OVERRIDE;
         items_clamp = 1;
        }
     }
 loCacheUnlock(se, 0);

 if (items_fail || items_clamp && loOPC_S_CLAMP != S_OK)
   upl->master_err = S_FALSE;
}
Exemple #2
0
HRESULT LightOPCGroup::internalValidateItems(DWORD dwCount,
                                             OPCITEMDEF *pItemDefs,
                                             loTagId *tid, void **acpath,
		                                     OPCITEMRESULT **ppResults,
                                             HRESULT **ppErrors)
{
 HRESULT hr = S_OK;
 HRESULT *err = 0;
 OPCITEMRESULT *ir = 0;
 DWORD ii;
 loService *se;
 loTagEntry *tags;
 int free_tid = 0,
     inc_ap = 0,
     ai_goal = loDAIG_ADDITEM,
     am_mask;
 loCallerx cctx;
 loAA_DECLARE(sizeof(loTagId));

 if (!tid)
   {
    free_tid = 1;
    ai_goal = loDAIG_VALIDATE;
    tid = (loTagId*)loAA_ALLOC(dwCount * sizeof(loTagId));
   }
 if (acpath) inc_ap = 1;

 UL_TRACE((LOG_GRH("loGroup::intValidateItems(%lu, %p %p %p)"),
           dwCount, pItemDefs, ppResults, ppErrors));

 if (ppResults) *ppResults = 0;
 if (ppErrors) *ppErrors = 0;

 if (!dwCount || !pItemDefs || !ppResults)
   { hr = E_INVALIDARG; goto Return; }

 cctx = owner->ctxt;
 se = owner->se; tags = se->tags;

 err = (HRESULT*)loComAlloc(dwCount * sizeof(HRESULT));
 ir = (OPCITEMRESULT*)loComAlloc(dwCount * sizeof(OPCITEMRESULT));
 if (!err || !ir || !tid) { hr = E_OUTOFMEMORY; goto Return; }
 memset(ir, 0, dwCount * sizeof(OPCITEMRESULT));

 am_mask = owner->access_mode & loAM_RDONLY_ADD?
                (loOPC_RIGHTS & ~OPC_WRITEABLE): loOPC_RIGHTS;

 lw_rw_rdlock(&se->lkMgmt);
 for(ii = 0; ii < dwCount; ii++, acpath += inc_ap)
   if (tid[ii] = loFindItemID(se, &owner->ctxt.cactx, 1,
 		              pItemDefs[ii].szItemID,
		              pItemDefs[ii].szAccessPath,
                      pItemDefs[ii].vtRequestedDataType,
                      ai_goal,
                      acpath, &err[ii]))
     {
      loTagAttrib *ta = &tags[tid[ii]].attr;
      ir[ii].dwAccessRights = am_mask/*loOPC_RIGHTS*/ & ta->taRights;
      ir[ii].vtCanonicalDataType = taVTYPE(ta);
     }
   else hr = S_FALSE;
 lw_rw_unlock(&se->lkMgmt);

 lock_read();
   cctx.cta.vc_lcid = grLCID;
 unlock();

 for(ii = 0; ii < dwCount; ii++)
   if (S_OK == err[ii])
     {
      loTagAttrib *ta = &tags[tid[ii]].attr;
      if (loTF_EMPTY & ta->taFlags)
        { 
          err[ii] = OPC_E_INVALIDITEMID;
          tid[ii] = 0; hr = S_FALSE;
          goto LogErr;
        }
      else if (
        /*VT_EMPTY != pItemDefs[ii].vtRequestedDataType &&*/
         S_OK != (err[ii] = lo_checktype(&cctx, ta,
                                pItemDefs[ii].vtRequestedDataType)))
        { 
          /*err[ii] = OPC_E_BADTYPE */; 
         tid[ii] = 0; hr = S_FALSE; 
         goto LogErr;
        }
      else
         UL_TRACE((LOG_GR("intValidateItem(%ls)(%ls) = %u"),
                          loWnul(pItemDefs[ii].szItemID),
 		                  loWnul(pItemDefs[ii].szAccessPath),
			              tid[ii]));
     }
   else 
     {
LogErr: UL_NOTICE((LOG_GR("intValidateItem(%ls)(%ls) = %s"),
	                  loWnul(pItemDefs[ii].szItemID),
	   		          loWnul(pItemDefs[ii].szAccessPath),
			          loStrError(err[ii])));
     }

Return:

 if (free_tid)
   {
    loAA_FREE(tid);
   }

 if (FAILED(hr))
   {
    UL_TRACE((LOG_GRH("intValidateItems(%lu) = %s"), dwCount, loStrError(hr)));
   }
 else
   {
    *ppResults = ir, ir = 0;
    if (ppErrors) *ppErrors = err, err = 0;

    UL_TRACE((LOG_GRH("intValidateItems(%lu) = %s"), dwCount, loStrError(hr)));
   }
 if (ir)  loComFree(ir);
 if (err) loComFree(err);
 return hr;
}
Exemple #3
0
STDMETHODIMP LightOPCGroup::Write(DWORD dwCount,
                                  OPCHANDLE  *phServer,
                                  VARIANT *pItemValues,
                                  HRESULT **ppErrors)
{
 HRESULT hr = S_OK;
 HRESULT *err = 0;
 unsigned items_ok = 0;
 loRequest *rq;

 LO_CHECK_STATEz1("SyncIO:Write", ppErrors);
 UL_TRACE((LOG_GRH("SyncIO:Write(%u)..."), dwCount));

 if (!phServer || !pItemValues || !dwCount)
   { hr = E_INVALIDARG; goto Return; }

 err = (HRESULT*)loComAlloc(dwCount * sizeof(HRESULT));
 rq = lo_req_alloc(dwCount, loUPL_variant /*| loUPL_errors*/ | loUPL_tagpair);
 if (!rq || !err) { hr = E_OUTOFMEMORY; goto Return; }
 rq->operation = loRQ_OP_WRITE | loRQ_SYNC | loRQ_DEVICE;
 rq->group_key = ServerHandle;
 rq->serv_key = owner->serv_key;
 rq->com_allocated = rq->upl.errors = err;
 loTagPair_init(rq->upl.tagpair, dwCount);
 rq->upl.rctx = owner->ctxt;

 lock_read();
 rq->upl.rctx.cta.vc_lcid = grLCID;

 if (owner->access_mode & loAM_RDONLY_OP)
   {
    unsigned ii;
    for(ii = 0; ii < dwCount; ii++) err[ii] = OPC_E_BADRIGHTS;
   }
 else
   {
    loService *se = owner->se;
    loTagEntry *tags = se->tags;
    loTagPair *tpl = rq->upl.tagpair;
//    HRESULT *errors = rq->upl.errors;
    VARIANT *variant = rq->upl.variant;
    LightOPCItem *it;
    unsigned ii;

    for(ii = 0; ii < dwCount; ii++, tpl++, pItemValues++)
      if (!(it = by_index(phServer[ii]))) err[ii] = OPC_E_INVALIDHANDLE;
      else
        {
         loTagEntry *te = &tags[it->tid];

#if 0 != LO_CHECK_RIGHTS
         if (!(OPC_WRITEABLE & te->attr.taRights)) err[ii] = OPC_E_BADRIGHTS;
         else
#endif
              if (VT_EMPTY == V_VT(pItemValues) ||/*) *errors = OPC_E_BADTYPE;
         else if (*/ S_OK == (err[ii] =
                       VariantCopy(&variant[ii], pItemValues)))
           {
            err[ii] = S_OK;
            tpl->tpTi = te->attr.taTi;
            tpl->tpRt = te->attr.taRt;
            tpl->tpAP = it->AcPath;
            items_ok++;
           }
         else UL_TRACE((LOG_GRH("SyncIO:Write(%u) [ %x / %x ] %s"),
               ii, V_VT(pItemValues), taVTYPE(&te->attr), loStrError(err[ii])));
       }
    rq->upl.used = dwCount;
   }
 unlock();
// rq->upl.used = dwCount;

 if (0 == items_ok)
   {
//    memcpy(err, rq->upl.errors, dwCount * sizeof(*err));
    rq->com_allocated = 0;
    lo_req_free(rq);
    hr = S_FALSE;
   }
 else
   {
    rq->upl.master_err = items_ok == dwCount? S_OK: S_FALSE;
    err = 0;
    if (rq = lo_req_put_sync(&owner->q_req, &owner->q_ret, rq))
      {
       hr = rq->upl.master_err;
//       memcpy(err, rq->upl.errors, dwCount * sizeof(*err));
       err = rq->upl.errors;
       rq->com_allocated = 0;
       lo_req_free(rq);
      }
    else hr = LO_E_SHUTDOWN;
   }

Return:
  if (SUCCEEDED(hr))
   {
    if (ppErrors) *ppErrors = err, err = 0;
//    if (items_ok != dwCount && hr == S_OK) hr = S_FALSE;
    UL_NOTICE((LOG_GRH("SyncIO:Write(%u) = %u Ok"), dwCount, items_ok));
   }
 else
   {
    UL_INFO((LOG_GRH("SyncIO:Write(%u) = %u /%s"),
               dwCount, items_ok, loStrError(hr)));
   }
 if (err) loComFree(err);
 LO_FINISH();
 return hr;
}