STDMETHODIMP LightOPCGroup::Write(DWORD dwCount, OPCHANDLE *phServer, VARIANT *pItemValues, DWORD dwTransactionID, DWORD *pdwCancelID, HRESULT **ppErrors) { HRESULT hr = S_FALSE; HRESULT *errs = 0; loRequest *rq = 0; unsigned items_ok = 0; LO_CHECK_STATEz1("AsyncIO2:Write", ppErrors); UL_TRACE((LOG_GRH("AsyncIO2:Write(%u)..."), dwCount)); if (!phServer || !dwCount || !pdwCancelID || !pItemValues) { hr = E_INVALIDARG; goto Return; } *pdwCancelID = 0; if (owner->q_req.metric_overload) { hr = CONNECT_E_ADVISELIMIT; goto Return; } errs = (HRESULT*)loComAlloc(dwCount * sizeof(HRESULT)); rq = lo_req_alloc(dwCount, loUPL_AsyncWrite); if (!rq || !errs) { hr = E_OUTOFMEMORY; goto Return; } loTagPair_init(rq->upl.tagpair, dwCount); rq->operation = loRQ_OP_WRITE | loRQ_CONN_DATABACK | loRQ_DEVICE; rq->group_key = ServerHandle; rq->serv_key = owner->serv_key; rq->upl.transaction_id = dwTransactionID; 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++) errs[ii] = OPC_E_BADRIGHTS; goto Unlock; } if (0 == (advise_present & loRQ_CONN_DATABACK)/*conn_databack*/) hr = CONNECT_E_NOCONNECTION; else { unsigned ii; loTagPair *tpl = rq->upl.tagpair; // HRESULT *errors = rq->upl.errors; LightOPCItem *it; loTagEntry *tags = owner->se->tags; for(ii = 0; ii < dwCount; ii++, pItemValues++) if (!(it = by_index(phServer[ii]))) errs[ii] = OPC_E_INVALIDHANDLE; else { loTagEntry *te = &tags[it->tid]; #if 0 != LO_CHECK_RIGHTS if (!(OPC_WRITEABLE & te->attr.taRights)) errs[ii] = OPC_E_BADRIGHTS; else #endif if (VT_EMPTY == V_VT(pItemValues) || /*) *errors = OPC_E_BADTYPE; else if (*/S_OK == (errs[ii] = VariantCopy(&rq->upl.variant[ii], pItemValues))) { tpl->tpTi = te->attr.taTi; tpl->tpRt = te->attr.taRt; tpl->tpAP = it->AcPath; tpl++; rq->upl.opchandle[items_ok++] = it->hClient; errs[ii] = S_OK; } }/* end of for */ } Unlock: unlock(); if (items_ok) { rq->upl.used = items_ok; rq->upl.master_err = hr = items_ok == dwCount? S_OK: S_FALSE; if (0 == (*pdwCancelID = lo_req_put_async(&owner->q_req, rq))) hr = CONNECT_E_ADVISELIMIT; rq = 0; } Return: if (rq) lo_req_free(rq); if (SUCCEEDED(hr)) { if (ppErrors) *ppErrors = errs, errs = 0; UL_NOTICE((LOG_GRH("AsyncIO2:Write(%u) = %u -> %x Ok"), dwCount, items_ok, *pdwCancelID)); } else { UL_INFO((LOG_GRH("AsyncIO2:Write(%u) = %u /%s"), dwCount, items_ok, loStrError(hr))); } if (errs) loComFree(errs); LO_FINISH(); return hr; }
static void rio_cache_read(loService *se, loUpdList *upl) { HRESULT mastererr = upl->master_err; HRESULT masterqual = upl->master_qual; HRESULT *errors = upl->errors; WORD *quality = upl->quality; VARIANT *variant = upl->variant; VARTYPE *vartype = upl->vartype; FILETIME *timestamp = upl->timestamp; loTagPair *tpl = upl->tagpair; loTagEntry *tags = se->tags; unsigned ii; unsigned localize_max = 0; unsigned localize_min = 0; lw_rw_rdlock(&se->lkPrim); for(ii = upl->used; ii--; errors++, quality++, variant++, vartype++, timestamp++, tpl++) { if (tpl->tpTi) { HRESULT hr; loTagEntry *te = &tags[tpl->tpTi]; #if 1 == LO_EV_TIMESTAMP if (!IsFILETIME(te->prim.tsTime)) *timestamp = loFT_SUBST(te->prim.tsTime, se->ts_prim); else #endif *timestamp = te->prim.tsTime; *errors = te->prim.tsError; #ifdef VAR_CHANGETYPE *quality = te->prim.tsQuality; hr = VAR_CHANGETYPE(variant, &te->primValue, *vartype); #else loCONV convtype = (loCONV)*quality; *quality = te->prim.tsQuality; switch(convtype/*lo_check_conversion(&te->attr, *vartype)*/) { case loCONV_CHANGE: hr = VARIANTCHANGEt(variant, &te->primValue, upl->rctx.cta, *vartype); break; case loCONV_COPY: hr = VariantCopy(variant, &te->primValue); break; case loCONV_ASSIGN: *variant = te->primValue; #if 1 loTagPair_init(tpl, 1); goto Cont; #else hr = S_OK; break; #endif case loCONV_CONVERT: if (S_OK == (hr = VariantCopy(variant, &te->primValue))) { if (!localize_max) localize_min = quality - upl->quality; localize_max = quality - upl->quality + 1; goto PreserveTP; } break; } loTagPair_init(tpl, 1); PreserveTP: #endif if (S_OK != hr) { LO_E_BADTYPE_QUAL(hr, *errors, *quality); masterqual = S_FALSE; mastererr = S_FALSE; continue; } Cont:; } if (OPC_QUALITY_GOOD != (OPC_QUALITY_MASK & *quality)) masterqual = S_FALSE; if (S_OK != *errors) mastererr = S_FALSE; } #if 2 == LO_EV_TIMESTAMP if (IsFILETIME(*se->ts_prim)) lo_check_ev_timestamp(upl->used, upl->timestamp, se->ts_prim); #endif lw_rw_unlock(&se->lkPrim); if (localize_max) se->driver.ldConvertTags(&upl->rctx.cactx, localize_max - localize_min, upl->tagpair + localize_min, upl->variant + localize_min, upl->quality + localize_min, upl->errors + localize_min, &mastererr, &masterqual, upl->variant + localize_min, upl->vartype + localize_min, upl->rctx.cta.vc_lcid); upl->master_qual = masterqual; /*if (upl->master_err == S_OK)*/ upl->master_err = mastererr; }
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; }