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; }
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; }
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; }