📄 lopcser.cpp
字号:
{
WR_lock(&lk_remove);
lock_write();//lw_rw_wrlock(&lk_all);
del_all(ldFlags & loDf_DWG);
unlock();//lw_rw_unlock(&lk_all);
lw_rw_unlock(&lk_remove);
}
// else del_all(initphase & ifFORCEDELETE);
}
void LightOPCServer::set_state(int oper, int state, const loWchar *reason)
{
int ost = 0xeee;
if (loIS_VALID(this))
{
UL_TRACE((LOG_SR("Server::set_state(%X/%d) ..."), oper, state));
/* DISCONNECT is possible whenever async is `outof01` but
in this case it could be done by sheduler.
here we warrant all possible disconnects will be done before
loSetStete() returned. */
if (oper & loOP_DISCONNECT)
{
unsigned gcount;
IUnknown *grp, **grpl;
UL_TRACE((LOG_SR("Server::DISCONNECT...")));
otrk.ot_disconnect_all(0);
lock_read();
grpl = (IUnknown**)grl.gl_list;
for(gcount = grl.gl_count; gcount--;)
if (grp = grpl[gcount]) LO_CO_DISCONNECT(grp, 0);
LO_CO_DISCONNECT((IOPCServer*)this, 0);
unlock();
UL_TRACE((LOG_SR("Server::DISCONNECT Enums...")));
otrk.ot_disconnect_all(0);
}
lw_mutex_lock(&async.lk);
if (!loThrControl_outof01(&async))
{
ost = otrk.ot_stopped;
if (oper & loOP_OPERATE)
{
if (otrk.ot_stopped && !(oper & loOP_STOP)) otrk.ot_stopped = 0;
if (shuttingdown && !(oper & loOP_SHUTDOWN)) shuttingdown = 0;
}
if ((oper & loOP_SHUTDOWN) &&
!shuttingdown) shuttingdown = 1;
if ((oper & (loOP_STOP | loOP_DESTROY)) &&
!otrk.ot_stopped) otrk.ot_stopped = 1;
if (0 != state) ostatus.dwServerState = (OPCSERVERSTATE)state;
if (0 != reason) loPWstrdup(&shutdown_conn.reason, reason);
if (oper & loOP_DESTROY)
{
async.tstate = 2;
lw_conds_signal(&async.cond);
}
else if (ost != otrk.ot_stopped || shuttingdown)
{
if (0 == async.tstate) async.tstate = 1;
lw_conds_signal(&async.cond);
}
} /* if (!loThControl_outof01( */
ost = otrk.ot_stopped << 8 | shuttingdown << 4 | async.tstate;
lw_mutex_unlock(&async.lk);
}
UL_TRACE((LOG_SR("Server::set_state(%X/%d) finished =%03x"), oper, state, ost));
}
int LightOPCServer::attach(void)
{
int err = EBADF;
UL_TRACE((LOG_SR("Server::attach() ...")));
if (loIS_VALID(this) && loIS_VALID(se))
{
lw_mutex_lock(&se->lkList);
if (!se->shutdown)
{
loClient *srv;
unsigned serv_id = se->serv_key;
NewKey:
if (0 == ++serv_id) ++serv_id;
srv = se->servlist;
while(srv)
if (srv->serv_key != serv_id) srv = srv->serv_next;
else goto NewKey;
se->serv_key = serv_key = serv_id;
serv_next = se->servlist;
se->servlist = this;
initphase |= ifATTACHED;
err = 0;
}
else err = ENOENT;
lw_mutex_unlock(&se->lkList);
if (0 == err)
err = loThrControl_start(&async, 1, run_client_scheduler, this);
}
UL_NOTICE((LOG_SR("Server::attach() %s"), err? "FAILED": "Ok"));
return err;
}
int LightOPCServer::detach(void)
{
int godown = 0;
UL_TRACE((LOG_SR("Server::detach() ...")));
/*
LO_CO_DISCONNECT((IOPCServer*)this, 0);
*/
clear_all();
UL_TRACE((LOG_SR("Server::detach() continued...")));
if ((initphase & ifATTACHED) && loIS_VALID(se))
{
LightOPCServer **les;
lw_mutex_lock(&se->lkList);
les = &se->servlist;
while(*les)
if (*les != this) les = &(*les)->serv_next;
else
{
*les = serv_next; serv_next = 0;
godown = (se->shutdown && !se->servlist)? -1: 1;
// break;
}
if (godown) initphase &= ~ifATTACHED;
lw_mutex_unlock(&se->lkList);
if (0 > godown)
{
UL_NOTICE((LOG_SR("going down")));
loInternalServiceDestroy(se);
}
}
clear_all();
UL_NOTICE((LOG_SR("Server::detach() finished %d"), godown));
return godown;
}
HRESULT LightOPCServer::mk_unique(loWchar buf[loUNIQUE_LEN], const void *ptr)
{
int tc;
if (!buf) return E_FAIL;
for(tc = 0; tc < 1000; tc++)
{
/*InterlockedIncrement()*/++unique_GroupName;
swprintf(buf, L"G-%03lu.%lx", unique_GroupName,
0xfffff & (((unsigned long)ptr) >> 5));
/* the value may be not same as result of InterlockedIncrement(),
but don't worried about */
if (!by_name(buf)) return S_OK;
}
UL_WARNING((LOG_SR("Can not make unique name %lu"), unique_GroupName));
return E_FAIL;
}
unsigned LightOPCServer::by_handle(OPCHANDLE sgh)
{
LightOPCGroup *grp;
unsigned uu = grl.gl_count;
while(uu--)
if ((grp = (LightOPCGroup*)grl.gl_list[uu]) && grp->ServerHandle == sgh)
return uu + 1;
return 0;
}
LightOPCGroup *LightOPCServer::by_handle_g(unsigned sgh)
{
LightOPCGroup *grp;
unsigned uu = grl.gl_count;
while(uu--)
if ((grp = (LightOPCGroup*)grl.gl_list[uu]) && grp->ServerHandle == sgh)
return grp;
return 0;
}
LightOPCGroup *LightOPCServer::by_name(const loWchar *name)
{
if (name)
{
LightOPCGroup *grp, **groups = (LightOPCGroup **)grl.gl_list;
unsigned uu = grl.gl_count;
while(uu--)
if ((grp = *groups++) && grp->name &&
!wcscmp(name, grp->name)) return grp;
}
return 0;
}
unsigned LightOPCServer::add(LightOPCGroup *grp)
{
unsigned slot;
if (!grp) return 0;
if (slot = gl_insert(&grl, grp, 0))
{
grp->AddRef();
grp->attach(this);
}
return slot;
}
int LightOPCServer::del(unsigned index, int force)
{
int rv = -1;
LightOPCGroup *grp;
if (grp = (LightOPCGroup*)gl_remove(&grl, index))
{
rv = (1 != grp->RefCount);
grp->detach(this);
if (force)
{
LO_CO_DISCONNECT((IOPCGroupStateMgt*)grp, 0);
delete grp;
rv = 0;
}
else
{
rv /*|*/= (0 != grp->Release());
}
}
return rv;
}
void LightOPCServer::del_all(int force)
{
unsigned uu;
for(uu = grl.gl_count; uu > 0; uu--) del(uu, force);
glGrowList_clear(&grl);
}
/*********************************** LightOPCGroup:: stuff **************************/
int LightOPCGroup::iam_attached(void) // for logging only
{
return loIS_VALID(this) && (initphase & ifATTACHED) && loIS_VALID(owner);
}
int LightOPCGroup::lock_state(const char *msg)
{
LightOPCServer *own = owner;
lw_rwlock *removelock = &own->lk_remove;
// UL_DEBUG((LOGID, "Group:%u(%p) <%s> Entering...", ServerHandle, this, msg? msg: ""));
if (loIS_VALID(this) && (initphase & ifATTACHED) /*&&
owner */ && !own->lock_state(msg, 0))
{
if (0 == own->RD_lock(removelock))
{
if (loIS_VALID(this) && (initphase & ifATTACHED))
{
return 0;
}
lw_rw_unlock(removelock);
}
own->unlock_state();
}
UL_WARNING((LOGID, "Group:%u(%p) <%s> interface closed",
ServerHandle, this, msg? msg: ""));
return -1;
}
#if 0
void LightOPCGroup::unlock_state(void)
{
if (!(initphase & ifATTACHED) && (gl_count || advise_present))
{
lock_write();
clear_all();
unlock();
}
lw_rw_unlock(&owner->lk_remove);
owner->unlock_state();
// UL_DEBUG((LOGID, "Group:%u(%p) Leave.Ok", ServerHandle, this));
}
#endif
LightOPCGroup::LightOPCGroup()
{
/* IUnknown implementation */
initphase = 0;
glGrowList_init(&itl);
RefCount = 0;
owner = 0;
name = 0;
ClientHandle = ServerHandle = grLCID = TimeBias = 0;
Active = 0;
justactuated = 0;
Deadband = 0.;
UpdateRate = LastUpdate = 0;
conn_databack = 0;
conn_dataonly = conn_datatime = conn_writecompl = 0;
advise_present = 0;
advise_enabled = loRQ_CONN_DATA;
active_count = 0;
last_trid = 0;
#if LO_USE_FREEMARSHALL
freemarsh = 0;
#endif
iam = this;
}
LightOPCGroup::~LightOPCGroup()
{
iam = 0;
initphase &= ~ifATTACHED;
UL_TRACE((LOGID, "~LightOPCGroup(%ls)", loWnul(name)));
LO_HEAPCHECK(this);
/*
LO_CO_DISCONNECT((IOPCGroupStateMgt*)this, 0);
*/
if (name) { freeX(name); name = 0; }
clear_all();
#if LO_USE_FREEMARSHALL
if (freemarsh) { freemarsh->Release(); freemarsh = 0; }
#endif
initphase = 0;
glGrowList_clear(&itl);
LO_HEAPCHECK(this);
}
void LightOPCGroup::clear_advise(void)
{
UL_DEBUG((LOGID, "LightOPCGroup::clear_advise(%ls)", loWnul(name)));
advise_present = 0;
if (conn_databack) loRELEASE_IFACE(conn_databack, IOPCDataCallback, initphase);
if (conn_dataonly) loRELEASE_IFACE(conn_dataonly, IAdviseSink, initphase);
if (conn_datatime) loRELEASE_IFACE(conn_datatime, IAdviseSink, initphase);
if (conn_writecompl) loRELEASE_IFACE(conn_writecompl, IAdviseSink, initphase);
}
void LightOPCGroup::clear_all(void)
{
del_all();
active_count = 0;
if (advise_present) clear_advise();
/* delete anything else here */
}
void LightOPCGroup::actuate_async(int justActuated) /* touch owner->async & set just_activated */
{
if (Active && (advise_present & advise_enabled))
{
if (justActuated) justactuated = 1, last_trid = 0;
owner->touch_scheduler();
UL_NOTICE((LOG_GRHO("group::actuate(%ls)"), loWnul(name)));
}
}
void LightOPCGroup::attach(LightOPCServer *own)
{
if (owner) UL_ERROR((LOG_GRHO("group::attach(%ls) BAD OWNER"), loWnul(name)));
if (owner = own)
{
initphase = ifATTACHED | own->ldFlags & loDf_BOTHMODEL;
#if LO_USE_FREEMARSHALL
if (own->/*se->driver.*/ldFlags & loDf_FREEMARSH)
CoCreateFreeThreadedMarshaler((IOPCGroupStateMgt*)this, &freemarsh);
/* there are nothing bad if it fails */
#endif
}
}
void LightOPCGroup::detach(LightOPCServer *own)
{
if (own == owner)
UL_TRACE((LOG_GRHO("group::detach(%ls)"), loWnul(name)));
else UL_ERROR((LOG_GRHO("group::detach(%ls) BAD OWNER"), loWnul(name)));
// LO_CO_DISCONNECT((IOPCGroupStateMgt*)this, 0);
if (initphase & ifATTACHED)
{
set_active(0);
initphase &= ~ifATTACHED;
}
clear_all();
}
int LightOPCGroup::del(unsigned indx)
{
LightOPCItem *item;
if (item = (LightOPCItem*)gl_remove(&itl, indx))
{ delete item; return 0; }
return -1;
}
void LightOPCGroup::del_all(void)
{
unsigned uu;
for(uu = itl.gl_count; uu > 0; uu--) del(uu);
glGrowList_clear(&itl);
}
/*********************** LightOPCGroup::IConnectionPoint stuff **********************/
HRESULT LightOPCGroup::icp_AddRef(void)
{
if (!AddRef()) return LO_E_SHUTDOWN;
LO_CHECK_STATEz0("Group::IConnPoint::AddRef");
return S_OK; }
}
void LightOPCGroup::icp_Release(void)
{
{ LO_FINISH();
Release();
}
loObjTracker *LightOPCGroup::icp_ObjTracker(void)
{
return owner? &owner->otrk: 0;
}
/*********************************** LightOPCItem:: stuff **************************/
LightOPCItem::LightOPCItem()
{
szItemID = 0;
szAccessPath = 0;
bActive = 0;
tid = 0;
convtype = loCONV_CHANGE;
/* hClient;*/
vtRequestedDataType = VT_EMPTY;
Quality = -1;
AcPath = 0;
last_changed = 0;
numeric = 0;
lastsent = 0;
}
LightOPCItem::~LightOPCItem()
{
if (szItemID) { freeX(szItemID); szItemID = 0; }
if (szAccessPath) { freeX(szAccessPath); szAccessPath = 0; }
if (lastsent) { freeX(lastsent); lastsent = 0; }
}
/* end of lopcser.cpp */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -