PageRenderTime 28ms CodeModel.GetById 1ms RepoModel.GetById 0ms app.codeStats 0ms

/LightOPC/src/iowrite.cpp

https://gitlab.com/fheinemann/opc_ads
C++ | 352 lines | 287 code | 47 blank | 18 comment | 80 complexity | 5339a61cdbeef340a369869b03be12db MD5 | raw file
  1. /**************************************************************************
  2. * *
  3. * Light OPC Server development library *
  4. * *
  5. * Copyright (c) 2000 Timofei Bondarenko *
  6. *
  7. LightOPCGroup::IOPC[A]SyncIO::Write() methods
  8. **************************************************************************/
  9. #include <opcerror.h>
  10. #include "privopc.h"
  11. #include LO_OLE_ERRORS_h /*CONNECT_E_NOCONNECTION*/
  12. /* IOPCSyncIO:: */
  13. STDMETHODIMP LightOPCGroup::Write(DWORD dwCount,
  14. OPCHANDLE *phServer,
  15. VARIANT *pItemValues,
  16. HRESULT **ppErrors)
  17. {
  18. HRESULT hr = S_OK;
  19. HRESULT *err = 0;
  20. unsigned items_ok = 0;
  21. loRequest *rq;
  22. LO_CHECK_STATEz1("SyncIO:Write", ppErrors);
  23. UL_TRACE((LOG_GRH("SyncIO:Write(%u)..."), dwCount));
  24. if (!phServer || !pItemValues || !dwCount)
  25. { hr = E_INVALIDARG; goto Return; }
  26. err = (HRESULT*)loComAlloc(dwCount * sizeof(HRESULT));
  27. rq = lo_req_alloc(dwCount, loUPL_variant /*| loUPL_errors*/ | loUPL_tagpair);
  28. if (!rq || !err) { hr = E_OUTOFMEMORY; goto Return; }
  29. rq->operation = loRQ_OP_WRITE | loRQ_SYNC | loRQ_DEVICE;
  30. rq->group_key = ServerHandle;
  31. rq->serv_key = owner->serv_key;
  32. rq->com_allocated = rq->upl.errors = err;
  33. loTagPair_init(rq->upl.tagpair, dwCount);
  34. rq->upl.rctx = owner->ctxt;
  35. lock_read();
  36. rq->upl.rctx.cta.vc_lcid = grLCID;
  37. if (owner->access_mode & loAM_RDONLY_OP)
  38. {
  39. unsigned ii;
  40. for(ii = 0; ii < dwCount; ii++) err[ii] = OPC_E_BADRIGHTS;
  41. }
  42. else
  43. {
  44. loService *se = owner->se;
  45. loTagEntry *tags = se->tags;
  46. loTagPair *tpl = rq->upl.tagpair;
  47. // HRESULT *errors = rq->upl.errors;
  48. VARIANT *variant = rq->upl.variant;
  49. LightOPCItem *it;
  50. unsigned ii;
  51. for(ii = 0; ii < dwCount; ii++, tpl++, pItemValues++)
  52. if (!(it = by_index(phServer[ii]))) err[ii] = OPC_E_INVALIDHANDLE;
  53. else
  54. {
  55. loTagEntry *te = &tags[it->tid];
  56. #if 0 != LO_CHECK_RIGHTS
  57. if (!(OPC_WRITEABLE & te->attr.taRights)) err[ii] = OPC_E_BADRIGHTS;
  58. else
  59. #endif
  60. if (VT_EMPTY == V_VT(pItemValues) ||/*) *errors = OPC_E_BADTYPE;
  61. else if (*/ S_OK == (err[ii] =
  62. VariantCopy(&variant[ii], pItemValues)))
  63. {
  64. err[ii] = S_OK;
  65. tpl->tpTi = te->attr.taTi;
  66. tpl->tpRt = te->attr.taRt;
  67. tpl->tpAP = it->AcPath;
  68. items_ok++;
  69. }
  70. else UL_TRACE((LOG_GRH("SyncIO:Write(%u) [ %x / %x ] %s"),
  71. ii, V_VT(pItemValues), taVTYPE(&te->attr), loStrError(err[ii])));
  72. }
  73. rq->upl.used = dwCount;
  74. }
  75. unlock();
  76. // rq->upl.used = dwCount;
  77. if (0 == items_ok)
  78. {
  79. // memcpy(err, rq->upl.errors, dwCount * sizeof(*err));
  80. rq->com_allocated = 0;
  81. lo_req_free(rq);
  82. hr = S_FALSE;
  83. }
  84. else
  85. {
  86. rq->upl.master_err = items_ok == dwCount? S_OK: S_FALSE;
  87. err = 0;
  88. if (rq = lo_req_put_sync(&owner->q_req, &owner->q_ret, rq))
  89. {
  90. hr = rq->upl.master_err;
  91. // memcpy(err, rq->upl.errors, dwCount * sizeof(*err));
  92. err = rq->upl.errors;
  93. rq->com_allocated = 0;
  94. lo_req_free(rq);
  95. }
  96. else hr = LO_E_SHUTDOWN;
  97. }
  98. Return:
  99. if (SUCCEEDED(hr))
  100. {
  101. if (ppErrors) *ppErrors = err, err = 0;
  102. // if (items_ok != dwCount && hr == S_OK) hr = S_FALSE;
  103. UL_NOTICE((LOG_GRH("SyncIO:Write(%u) = %u Ok"), dwCount, items_ok));
  104. }
  105. else
  106. {
  107. UL_INFO((LOG_GRH("SyncIO:Write(%u) = %u /%s"),
  108. dwCount, items_ok, loStrError(hr)));
  109. }
  110. if (err) loComFree(err);
  111. LO_FINISH();
  112. return hr;
  113. }
  114. #define loUPL_AsyncWrite (loUPL_variant | loUPL_tagpair | loUPL_opchandle | loUPL_errors)
  115. /********** AsyncIO1:: */
  116. STDMETHODIMP LightOPCGroup::Write(/* [in] */ DWORD dwConnection,
  117. /* [in] */ DWORD dwCount,
  118. /* [size_is][in] */ OPCHANDLE *phServer,
  119. /* [size_is][in] */ VARIANT *pItemValues,
  120. /* [out] */ DWORD *pTransactionID,
  121. /* [size_is][size_is][out] */ HRESULT **ppErrors)
  122. {
  123. HRESULT hr = S_FALSE;
  124. HRESULT *errs = 0;
  125. loRequest *rq = 0;
  126. unsigned item_ok = 0, items_ok = 0;
  127. LO_CHECK_STATEz1("AsyncIO:Write", ppErrors);
  128. UL_TRACE((LOG_GRH("AsyncIO:Write(%u)..."), dwCount));
  129. if (!phServer || !dwCount || !pTransactionID || !pItemValues)
  130. { hr = E_INVALIDARG; goto Return; }
  131. *pTransactionID = 0;
  132. if (owner->q_req.metric_overload) { hr = CONNECT_E_ADVISELIMIT; goto Return; }
  133. errs = (HRESULT*)loComAlloc(dwCount * sizeof(HRESULT));
  134. rq = lo_req_alloc(dwCount, loUPL_AsyncWrite);
  135. if (!rq || !errs) { hr = E_OUTOFMEMORY; goto Return; }
  136. loTagPair_init(rq->upl.tagpair, dwCount);
  137. rq->operation = loRQ_OP_WRITE | loRQ_CONN_WRITECOMPL | loRQ_DEVICE;
  138. rq->group_key = ServerHandle;
  139. rq->serv_key = owner->serv_key;
  140. rq->upl.rctx = owner->ctxt;
  141. lock_read();
  142. rq->upl.rctx.cta.vc_lcid = grLCID;
  143. if (owner->access_mode & loAM_RDONLY_OP)
  144. {
  145. unsigned ii;
  146. for(ii = 0; ii < dwCount; ii++) errs[ii] = OPC_E_BADRIGHTS;
  147. goto Unlock;
  148. }
  149. if (dwConnection != loRQ_CONN_WRITECOMPL ||
  150. 0 == (advise_present & loRQ_CONN_WRITECOMPL)/*conn_writecompl*/)
  151. {
  152. hr = CONNECT_E_NOCONNECTION;
  153. }
  154. else
  155. {
  156. unsigned ii;
  157. loTagPair *tpl = rq->upl.tagpair;
  158. HRESULT *errors = rq->upl.errors;
  159. LightOPCItem *it;
  160. loTagEntry *tags = owner->se->tags;
  161. for(ii = 0; ii < dwCount; ii++, tpl++, errors++, pItemValues++)
  162. if (!(it = by_index(phServer[ii]))) errs[ii] = OPC_E_INVALIDHANDLE;
  163. else
  164. {
  165. loTagEntry *te = &tags[it->tid];
  166. #if 0 != LO_CHECK_RIGHTS
  167. if (!(OPC_WRITEABLE & te->attr.taRights))
  168. { //errs[ii] = OPC_E_BADRIGHTS; - in callback
  169. *errors = OPC_E_BADRIGHTS;
  170. }
  171. else
  172. #endif
  173. if (VT_EMPTY == V_VT(pItemValues) || /*) *errors = OPC_E_BADTYPE;
  174. else if (*/S_OK == (*errors =
  175. VariantCopy(&rq->upl.variant[ii], pItemValues)))
  176. {
  177. tpl->tpTi = te->attr.taTi;
  178. tpl->tpRt = te->attr.taRt;
  179. tpl->tpAP = it->AcPath;
  180. items_ok++;
  181. }
  182. rq->upl.opchandle[ii] = it->hClient;
  183. errs[ii] = S_OK;
  184. item_ok++;
  185. }/* end of for */
  186. }
  187. Unlock:
  188. unlock();
  189. if (dwCount == item_ok)
  190. {
  191. rq->upl.used = item_ok;
  192. rq->upl.master_err = items_ok == dwCount? S_OK: S_FALSE;
  193. if (0 == (*pTransactionID = lo_req_put_async(&owner->q_req, rq)))
  194. hr = CONNECT_E_ADVISELIMIT;
  195. else hr = S_OK;
  196. rq = 0;
  197. }
  198. Return:
  199. if (rq) lo_req_free(rq);
  200. if (SUCCEEDED(hr))
  201. {
  202. if (ppErrors) *ppErrors = errs, errs = 0;
  203. UL_NOTICE((LOG_GRH("AsyncIO:Write(%u) = %u -> %x Ok"),
  204. dwCount, item_ok, *pTransactionID));
  205. }
  206. else
  207. {
  208. UL_INFO((LOG_GRH("AsyncIO:Write[conn=%x advs=%x](%u) = %u /%s"),
  209. dwConnection, advise_present,
  210. dwCount, item_ok, loStrError(hr)));
  211. }
  212. if (errs) loComFree(errs);
  213. LO_FINISH();
  214. return hr;
  215. }
  216. /********** AsyncIO2:: */
  217. STDMETHODIMP LightOPCGroup::Write(DWORD dwCount, OPCHANDLE *phServer, VARIANT *pItemValues,
  218. DWORD dwTransactionID, DWORD *pdwCancelID, HRESULT **ppErrors)
  219. {
  220. HRESULT hr = S_FALSE;
  221. HRESULT *errs = 0;
  222. loRequest *rq = 0;
  223. unsigned items_ok = 0;
  224. LO_CHECK_STATEz1("AsyncIO2:Write", ppErrors);
  225. UL_TRACE((LOG_GRH("AsyncIO2:Write(%u)..."), dwCount));
  226. if (!phServer || !dwCount || !pdwCancelID || !pItemValues)
  227. { hr = E_INVALIDARG; goto Return; }
  228. *pdwCancelID = 0;
  229. if (owner->q_req.metric_overload) { hr = CONNECT_E_ADVISELIMIT; goto Return; }
  230. errs = (HRESULT*)loComAlloc(dwCount * sizeof(HRESULT));
  231. rq = lo_req_alloc(dwCount, loUPL_AsyncWrite);
  232. if (!rq || !errs) { hr = E_OUTOFMEMORY; goto Return; }
  233. loTagPair_init(rq->upl.tagpair, dwCount);
  234. rq->operation = loRQ_OP_WRITE | loRQ_CONN_DATABACK | loRQ_DEVICE;
  235. rq->group_key = ServerHandle;
  236. rq->serv_key = owner->serv_key;
  237. rq->upl.transaction_id = dwTransactionID;
  238. rq->upl.rctx = owner->ctxt;
  239. lock_read();
  240. rq->upl.rctx.cta.vc_lcid = grLCID;
  241. if (owner->access_mode & loAM_RDONLY_OP)
  242. {
  243. unsigned ii;
  244. for(ii = 0; ii < dwCount; ii++) errs[ii] = OPC_E_BADRIGHTS;
  245. goto Unlock;
  246. }
  247. if (0 == (advise_present & loRQ_CONN_DATABACK)/*conn_databack*/)
  248. hr = CONNECT_E_NOCONNECTION;
  249. else
  250. {
  251. unsigned ii;
  252. loTagPair *tpl = rq->upl.tagpair;
  253. // HRESULT *errors = rq->upl.errors;
  254. LightOPCItem *it;
  255. loTagEntry *tags = owner->se->tags;
  256. for(ii = 0; ii < dwCount; ii++, pItemValues++)
  257. if (!(it = by_index(phServer[ii]))) errs[ii] = OPC_E_INVALIDHANDLE;
  258. else
  259. {
  260. loTagEntry *te = &tags[it->tid];
  261. #if 0 != LO_CHECK_RIGHTS
  262. if (!(OPC_WRITEABLE & te->attr.taRights)) errs[ii] = OPC_E_BADRIGHTS;
  263. else
  264. #endif
  265. if (VT_EMPTY == V_VT(pItemValues) || /*) *errors = OPC_E_BADTYPE;
  266. else if (*/S_OK == (errs[ii] =
  267. VariantCopy(&rq->upl.variant[ii], pItemValues)))
  268. {
  269. tpl->tpTi = te->attr.taTi;
  270. tpl->tpRt = te->attr.taRt;
  271. tpl->tpAP = it->AcPath;
  272. tpl++;
  273. rq->upl.opchandle[items_ok++] = it->hClient;
  274. errs[ii] = S_OK;
  275. }
  276. }/* end of for */
  277. }
  278. Unlock:
  279. unlock();
  280. if (items_ok)
  281. {
  282. rq->upl.used = items_ok;
  283. rq->upl.master_err = hr = items_ok == dwCount? S_OK: S_FALSE;
  284. if (0 == (*pdwCancelID = lo_req_put_async(&owner->q_req, rq)))
  285. hr = CONNECT_E_ADVISELIMIT;
  286. rq = 0;
  287. }
  288. Return:
  289. if (rq) lo_req_free(rq);
  290. if (SUCCEEDED(hr))
  291. {
  292. if (ppErrors) *ppErrors = errs, errs = 0;
  293. UL_NOTICE((LOG_GRH("AsyncIO2:Write(%u) = %u -> %x Ok"),
  294. dwCount, items_ok, *pdwCancelID));
  295. }
  296. else
  297. {
  298. UL_INFO((LOG_GRH("AsyncIO2:Write(%u) = %u /%s"),
  299. dwCount, items_ok, loStrError(hr)));
  300. }
  301. if (errs) loComFree(errs);
  302. LO_FINISH();
  303. return hr;
  304. }
  305. /* end of iowrite.cpp */