int loSetStateW(loService *se, loClient *cli, int oper, int state, const loWchar *reason) { int rv = EBADF; if (oper & ~(loOP_OPERATE | loOP_STOP | loOP_DISCONNECT | loOP_SHUTDOWN | loOP_DESTROY)) return EINVAL; if (loSERVICE_OK(se)) { lw_mutex_lock(&se->lkList); if (!se->shutdown) { LightOPCServer *los; rv = ENOENT; for(los = (LightOPCServer*)se->servlist; los; los = los->serv_next) if (!cli || los == cli) { los->set_state(oper, state, reason); rv = 0; } } lw_mutex_unlock(&se->lkList); } return rv; }
loTagValue *loCacheLock(loService *se) { if (loSERVICE_OK(se)) { lw_mutex_lock(&se->update_pipe.lk); if (se->update_pipe.tstate >= 0) return se->secondary; lw_mutex_unlock(&se->update_pipe.lk); } return 0; }
int loGetBandwidth(loService *se, loClient *cli) { int rv = -1; LightOPCServer *ls; loMilliSec bandw_time, curtime; if (!loSERVICE_OK(se)) return -1; curtime = lo_millisec(); lw_mutex_lock(&se->lkList); ls = se->servlist; if (cli) { while(ls && ls != cli) ls = ls->serv_next; if (ls) { lw_mutex_lock(&ls->async.lk); rv = (int)ls->ostatus.dwBandWidth; bandw_time = ls->bandwidth_time; lw_mutex_unlock(&ls->async.lk); rv = (int)lo_adjust_bandwidth(rv, bandw_time, curtime); } } else while(ls) { int tv; lw_mutex_lock(&ls->async.lk); tv = (int)ls->ostatus.dwBandWidth; bandw_time = ls->bandwidth_time; lw_mutex_unlock(&ls->async.lk); tv = (int)lo_adjust_bandwidth(tv, bandw_time, curtime); if (tv > rv) rv = tv; ls = ls->serv_next; } lw_mutex_unlock(&se->lkList); return rv < 0? 0: rv; }
int loTridWait(loService *se, loTrid trid) /* wait for data be moved to primary cache. */ { int rv = 0; if (!loSERVICE_OK(se)) return -1; if (!loIsTRID(trid)) return -1; lw_mutex_lock(&se->update_pipe.lk); for(;; lw_condb_wait(&se->lkTridWait, &se->update_pipe.lk)) { unsigned trdif = se->prim_trid - trid; #if 1 if (trdif < ~trdif) { rv = 1; break; } #elif 1 if (trdif <= -trdif) { rv = 1; break; } #else if ((int)trdif >= -(int)trdif) { rv = 1; break; } #endif if (se->update_pipe.tstate < 0 || se->shutdown) break; } lw_mutex_unlock(&se->update_pipe.lk); return rv; }
int loServiceDestroy(loService *se) { UL_TRACE((LOGID, "loServiceDestroy(%p)...", se)); if (!loIS_VALID(se)) return EBADF; if ((se->initphase & (ifLKLIST|ifLKSEC)) == (ifLKLIST|ifLKSEC)) { lw_mutex_lock(&se->lkList); if (se->shutdown) { lw_mutex_unlock(&se->lkList); UL_ERROR((LOGID, "loServiceDestroy(%p) shutdown started again", se)); return EBADF; } if (se->servlist) { LightOPCServer *los = (LightOPCServer*)se->servlist; se->shutdown = 1; while(los) { los->set_state(loOP_SHUTDOWN|loOP_STOP|loOP_DISCONNECT, 0, 0); los = los->serv_next; } lw_mutex_unlock(&se->lkList); UL_NOTICE((LOGID, "loServiceDestroy(%p) shutdown started", se)); return EBUSY; } se->shutdown = -1; lw_mutex_unlock(&se->lkList); #if 0 loThrControl_stop(&se->update_pipe); #endif lw_condb_broadcast_continious(&se->lkTridWait, &se->update_pipe.lk); } return loInternalServiceDestroy(se); }
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; }
lw_thrrettype loUpdatePipe(void *vse) { loService *se = (loService *)vse; if (!loIS_VALID(se)) { UL_ERROR((LOGID, "loUpdatePipe() prematurely terminated")); lw_RETURN; } UL_TRACE((LOGID, "loUpdatePipe() started...")); loThrControl_accept(&se->update_pipe); lw_mutex_lock(&se->update_pipe.lk); for(;; lw_conds_wait(&se->update_pipe.cond, &se->update_pipe.lk)) if (0 != se->update_pipe.tstate) { if (0 > se->update_pipe.tstate) break; /* terminate thread */ lw_mutex_unlock(&se->update_pipe.lk); lw_rw_wrlock(&se->lkPrim); lw_mutex_lock(&se->update_pipe.lk); if (0 > se->update_pipe.tstate) { lw_rw_unlock(&se->lkPrim); break; }/* terminate thread */ { /* do actual update here */ unsigned ii = se->lastused; loTagEntry *te = se->tags; loTagValue *ts = se->secondary; loTrid prim_changed = se->sec_trid; while(ii--) { te++; ts++; if (ts->tvTi) { if (ts->tvTi == loCH_TIMESTAMP) te->prim.tsTime = ts->tvState.tsTime; else { te->primChanged = prim_changed; te->prim = ts->tvState; #if LO_KEEP_OLD_CACHE { HRESULT hr; if (S_OK != (hr = VariantCopy(&te->primValue, &ts->tvValue))) { LO_E_BADTYPE_QUAL(hr, te->prim.tsError, te->prim.tsQuality); UL_WARNING((LOGID, "%!l loUpdatePipe(VariantCopy())", hr)); } } #else VariantClear(&te->primValue); te->primValue = ts->tvValue; VARIANTINIT(&ts->tvValue); #endif } ts->tvTi = 0; } } } se->prim_trid = se->sec_trid; #if 0 != LO_EV_TIMESTAMP if (se->ts_prim != se->ts_sec) { freeX(se->ts_prim); se->ts_prim = se->ts_sec; } memcpy(se->ts_prim, se->ts_prim + se->ts_size, se->ts_size * sizeof(FILETIME)); #endif lw_rw_unlock(&se->lkPrim); se->update_pipe.tstate = 0; lw_condb_broadcast(&se->lkTridWait); } loThrControl_finish(&se->update_pipe); lw_mutex_unlock(&se->update_pipe.lk); UL_NOTICE((LOGID, "loUpdatePipe() finished")); lw_RETURN; }