static void rio_refresh(LightOPCServer *cli, loRequest *rq) { LightOPCGroup *grp; unsigned group_key = rq->group_key; int operation = rq->operation; loRqid trqid = rq->upl.trqid; DWORD transid = rq->upl.transaction_id; loUpdList upl; lo_upl_init(&upl, loUPL_variant | loUPL_timestamp | loUPL_quality | loUPL_errors | loUPL_opchandle); upl.trqid = trqid; upl.transaction_id = transid; lo_req_free(rq); cli->lock_read(); if ((grp = cli->by_handle_g(group_key)) && (grp->advise_present & operation & loRQ_CONN_DATA)) { lo_refresh_items(cli->se, &upl, grp); cli->send_callback(grp, 0, &upl, operation); } else { cli->unlock(); UL_INFO((LOGID, "Refresh(%x) Aborted: No such group or connection", trqid)); } lo_upl_clear(&upl); }
STDMETHODIMP LightOPCServer::RemoveGroup(OPCHANDLE groupHandleID, BOOL bForce) { HRESULT hr = loOPC_E_INVALIDHANDLE; LO_CHECK_STATEz0("RemoveGroup"); UL_TRACE((LOG_SR("RemoveGroup(%u %s)"), groupHandleID, bForce? "FORCE": "")); if (groupHandleID) { #if LO_USE_BOTHMODEL if (ldFlags & loDf_BOTHMODEL) { loRequest *rq = lo_req_alloc(0, 0); UL_DEBUG((LOG_SR("RemoveGroup() going to async"))); if (!rq) hr = E_OUTOFMEMORY; else { rq->operation = loRQ_SYNC | loRQ_OP_REMOVE_GROUP | (bForce? loRQ_OF_REMOVE_FORCE: 0); rq->group_key = groupHandleID; rq->serv_key = serv_key; if (rq = lo_req_put_sync(&q_req, &q_ret, rq)) { hr = rq->upl.master_err; lo_req_free(rq); } else hr = E_FAIL; } } else #endif hr = internalRemoveGroup(groupHandleID, bForce); } if (S_OK != hr) UL_INFO((LOG_SR("RemoveGroup(%u %s) =%s"), groupHandleID, bForce? "FORCE": "", loStrError(hr))); else UL_NOTICE((LOG_SR("RemoveGroup(%u %s) =Ok"), groupHandleID, bForce? "FORCE": "")); LO_FINISH(); return hr; }
int lo_rio_requests(LightOPCServer *cli) { loRequest *rq; loService *se = cli->se; while(rq = cli->q_req.req) { int operation = rq->operation; loTrid trid; if (loThrControl_outof01(&cli->async)) return -1; cli->q_req.req = rq->rq_next; if (operation & loRQ_OPER_IO) cli->q_req.metric_overload = 0; lw_mutex_unlock(&cli->async.lk); UL_TRACE((LOGID, "REQUEST Retreived %x / %x", operation, rq->upl.trqid)); switch(operation & (loRQ_OPER_MASK | loRQ_DEVICE)) { #if LO_USE_BOTHMODEL case loRQ_OP_ADVISE: { void *aconn = 0; if (rq->conn_stream) { rq->upl.master_err = CoGetInterfaceAndReleaseStream(rq->conn_stream, *rq->conn_iface, &aconn); rq->conn_stream = 0; } else rq->upl.master_err = S_OK; if (SUCCEEDED(rq->upl.master_err)) rq->upl.master_err = cli->sync_advise(operation, &aconn, rq->group_key); if (aconn) ((IUnknown*)aconn)->Release(); if (operation & loRQ_SYNC) lo_req_put_bcast(&cli->q_ret, rq); else lo_req_free(rq); } break; case loRQ_OP_REMOVE_GROUP: rq->upl.master_err = cli->internalRemoveGroup(rq->group_key, operation & loRQ_OF_REMOVE_FORCE); if (operation & loRQ_SYNC) lo_req_put_bcast(&cli->q_ret, rq); else lo_req_free(rq); break; #endif /********************************************/ case loRQ_OP_WRITE|loRQ_DEVICE: if (se->driver.ldWriteTags) { int rv; loLOCK_DRIVER(se); rv = se->driver.ldWriteTags(&rq->upl.rctx.cactx, rq->upl.used, rq->upl.tagpair, rq->upl.variant, rq->upl.errors, &rq->upl.master_err, rq->upl.rctx.cta.vc_lcid); loUNLOCK_DRIVER(se); if (rv == loDW_ALLDONE) { if (operation & loRQ_SYNC) lo_req_put_bcast(&cli->q_ret, rq); else { cli->send_callback(0, rq->group_key, &rq->upl, operation); lo_req_free(rq); } break; } } // UL_ERROR((LOGID, "DEV WRITE failed")); case loRQ_OP_WRITE: rio_cache_write(se, &rq->upl); if (operation & loRQ_SYNC) lo_req_put_bcast(&cli->q_ret, rq); else { cli->send_callback(0, rq->group_key, &rq->upl, operation); lo_req_free(rq); } break; /********************************************/ case loRQ_OP_READ|loRQ_DEVICE: if (se->driver.ldReadTags /*&& !(cli->access_mode & (loAM_NOREAD_DEV | loAM_ERREAD_DEV))*/) { HRESULT m_err = rq->upl.master_err, m_qual = rq->upl.master_qual; loLOCK_DRIVER(se); trid = se->driver.ldReadTags(&rq->upl.rctx.cactx, rq->upl.used, rq->upl.tagpair, rq->upl.variant, rq->upl.quality, rq->upl.timestamp, rq->upl.errors, &m_err, &m_qual, rq->upl.vartype, rq->upl.rctx.cta.vc_lcid); loUNLOCK_DRIVER(se); if (loDR_STORED == trid) { if (S_OK != m_err) rq->upl.master_err = S_FALSE; if (S_OK != m_qual) rq->upl.master_qual = S_FALSE; if (operation & loRQ_SYNC) lo_req_put_bcast(&cli->q_ret, rq); else { cli->send_callback(0, rq->group_key, &rq->upl, operation); lo_req_free(rq); } break; } else if (loDR_CACHED != trid) loTridWait(se, trid); } case loRQ_OP_READ: rio_cache_read(se, &rq->upl); if (operation & loRQ_SYNC) lo_req_put_bcast(&cli->q_ret, rq); else { cli->send_callback(0, rq->group_key, &rq->upl, operation); lo_req_free(rq); } break; /********************************************/ case loRQ_OP_REFRESH|loRQ_DEVICE: if (se->driver.ldReadTags /*&& !(cli->access_mode & (loAM_NOREAD_DEV | loAM_ERREAD_DEV))*/) { loLOCK_DRIVER(se); trid = se->driver.ldReadTags(&rq->upl.rctx.cactx, rq->upl.used, rq->upl.tagpair, 0, 0, 0, 0, 0, 0, 0, 0 /*rq->upl.variant, rq->upl.quality, rq->upl.timestamp, rq->upl.errors, &master_err, &master_qual, rq->upl.vartype, rq->upl.gr_lcid*/); loUNLOCK_DRIVER(se); if (loDR_CACHED != trid) loTridWait(se, trid); } case loRQ_OP_REFRESH: if (operation & loRQ_SYNC) UL_ERROR((LOGID, "SYNC REFRESH is invalid %x / %x", rq->operation, rq->upl.trqid)); rio_refresh(cli, rq); break; /********************************************/ case loRQ_OP_CANCEL: cli->send_callback(0, rq->group_key, &rq->upl, operation); lo_req_free(rq); break; /********************************************/ default: UL_ERROR((LOGID, "BAD REQUEST %x / %x", rq->operation, rq->upl.trqid)); lo_req_free(rq); break; } #if 0 if (rq) /*??*/ { if (operation & loRQ_SYNC) lo_req_put_bcast(&cli->q_ret, rq); else { if (operation & loRQ_OPER_IO) cli->send_callback(0, rq->group_key, &rq->upl, operation); lo_req_free(rq); } } #endif lw_mutex_lock(&cli->async.lk); } return 0; }
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; }
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; }