⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lopcser.cpp

📁 OPCSERVER源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/**************************************************************************
 *                                                                        *
 * Light OPC Server development library                                   *
 *                                                                        *
 *   Copyright (c) 2000 by Timofei Bondarenko, Kostya Volovich            *
                                                                          *
 Main part of LightOPCServer
 **************************************************************************/

#include <wchar.h> /* swprintf() */
#include <stdio.h> /* sprintf() */
#include <errno.h>
#include "privopc.h"
//#include "connpnt.h"
#if 0
#include <malloc.h>
#define LO_HEAPCHECK(pp) { int hc; if (_HEAPOK != (hc = _heapchk())) \
        UL_ERROR((LOGID, "heapchk() %d %p %s %d", hc, pp, __FILE__, __LINE__)); }
#else
#define LO_HEAPCHECK(pp)
#endif

static const struct
	{
	 char build[10];
	 char date[32];
	} identify =
#define sh(v,x) ('0' + (v >> x & 15))
#define stri(v) sh(v,28),sh(v,24),sh(v,20),sh(v,16),sh(v,12),sh(v,8),sh(v,4),sh(v,0)
	{ { '\r', '\n', stri(LIGHTOPC_H) }, " " __DATE__ " " __TIME__ " sign @\r\n"	};

/*********************************** LightOPCServer:: stuff **************************/
#define ifATTACHED    (1<< 0)
#define ifLKALL       (1<< 1)
#define ifLKBROWSE    (1<< 2)
#define ifLKASYNC     (1<< 3)
#define ifLKREMOVE    (1<< 4)
#define ifREQQUEUE    (1<< 5)
#define ifRETQUEUE    (1<< 7)
#define ifOBJTRACK    (1<< 8)
//#define ifLKVALUES  (1<<4)
#if ifATTACHED & loDf_BOTHMODEL
#error LightOPCGroup::initphase flags conflict
#endif

int LightOPCServer::lock_state(const char *msg, const IID *riid_nostrict)
{
 LO_HEAPCHECK(this);
 UL_DEBUG((LOGID, "Entering <%s>...", msg? msg: ""));
 if (loIS_VALID(this))
   {
    if (!otrk.ot_stopped || riid_nostrict && (!shuttingdown ||
#if LO_USE_FREEMARSHALL
                    IsEqualIID(*riid_nostrict, IID_IMarshal) ||
#endif
                    IsEqualIID(*riid_nostrict, IID_IUnknown) ) )
      {
       InterlockedIncrement(&RefCount);
       return 0;
      }
   }
 if (riid_nostrict)
   {
    char ifa[40];
    UL_NOTICE((LOG_SR("Server::<%s> interface %s closed: va=%d st=%d sd=%d rc=%d"),
      msg? msg: "", loTranslateIID(ifa, sizeof(ifa), riid_nostrict),
      loIS_VALID(this), otrk.ot_stopped, shuttingdown, RefCount));
   }
 else UL_WARNING((LOG_SR("Server::<%s> interface closed"), msg? msg: ""));
 return -1;
}

static lw_thrrettype run_client_scheduler(void *cli)
{
 UL_NOTICE((LOGID, "client_scheduler(%p) starting...", cli));
 if (cli /*loIS_VALID(cli)*/)
   ((LightOPCServer*)cli)->client_scheduler();
 /* when "self-stopping" is actual loIS_VALID() will return 0 */
 UL_TRACE((LOGID, "client_scheduler(%p) exiting...", cli));

 lw_RETURN;
}

LightOPCServer::LightOPCServer()
{
 iam = 0;
 initphase = 0;
 glGrowList_init(&grl);
 ldFlags = 0;
 access_mode = loAM_RDWR;
 qi_chain = 0;
 se = 0;
 release_handle = 0;
 release_handle_arg = 0;
 unique_GroupName = 0;
 unique_GroupHandle = 0;
 loStringBuf_init(&browsepos);
 serv_next = 0; serv_key = 0;
 shuttingdown = 0;
 otrk.ot_stopped = 0;
#if LO_USE_FREEMARSHALL
 freemarsh = 0;
#endif
#if LO_USE_BOTHMODEL
 ole_initialized = 0;
 lml_rd_lock = lw_rw_timedrdlock;
 lml_wr_lock = lw_rw_timedwrlock;
#endif
 /* IUnknown implementation */
 RefCount = 0;

 /* IOPCCommon implementation */
 client_name[1] = identify.build[8];
 memset(&ctxt, 0, sizeof(ctxt));
/* ctxt.cta.vc_lcid = 0;
   ctxt.cta.vc_tfl = 0; *//* VariantChangeType() flags:
 VARIANT_ALPHABOOL | VARIANT_LOCALBOOL |
 VARIANT_NOUSEROVERRIDE | VARIANT_NOVALUEPROP */
 memset(client_name, 0, sizeof(client_name));
// *client_name = '-';
 sprintf(client_name, "[%03X:%03X]", 0xffff & (unsigned)GetCurrentProcessId(),
                                     0xffff & (unsigned)this);

/* IConnectionPoint methods */
 loShutdownConn_init(&shutdown_conn);

 /* OPCSERVERSTATUS */
 memset(&ostatus, 0, sizeof(ostatus));
 ostatus.dwBandWidth = 0xffffffff;
 bandwidth_time = 0;

 iam = this; /****/
}

int LightOPCServer::initialize(loService *serv, int ld_flags,
                               const loVendorInfo *vi)
{
 int err = 0;

 if (!loIS_VALID(this) || se ||
     ostatus.szVendorInfo || initphase) return EINVAL;
 if (!loSERVICE_OK(serv)) { err = EINVAL; goto Fail; }
 se = serv;
 ctxt.cactx = se->cactx;
// ctxt.cactx.ca_cli = this;

 ldFlags = ld_flags | se->driver.ldFlags;
 if (ld_flags & loDf_FREEMODEL) ldFlags &= ~loDf_BOTHMODEL;
#if LO_USE_BOTHMODEL
 if (ldFlags & loDf_BOTHMODEL)
   {
    lml_rd_lock = lw_rw_timedrdlock_lml;
    lml_wr_lock = lw_rw_timedwrlock_lml;
   }
#endif

 if (vi)
   {
    ostatus.wMajorVersion = vi->lviMajor;
    ostatus.wMinorVersion = vi->lviMinor;
    ostatus.wBuildNumber = vi->lviBuild;
    ostatus.wReserved = vi->lviReserv;
    if (vi->lviInfo &&
        !(ostatus.szVendorInfo = loMWstrdup(vi->lviInfo)))
      { err = ENOMEM; goto Fail; }
   }

 se->driver.ldCurrentTime(&ctxt.cactx, &ostatus.ftStartTime);
 ostatus.dwServerState = OPC_STATUS_NOCONFIG;

 if (err = lw_rwlock_init(&lk_all, 0)) goto Fail;
 initphase |= ifLKALL;

 if (err = lw_rwlock_init(&lk_remove, 0)) goto Fail;
 initphase |= ifLKREMOVE;

 if (err = lw_mutex_init(&lk_browse, 0)) goto Fail;
 initphase |= ifLKBROWSE;

 if (err = loQueueBcast_init(&q_ret, ldFlags & loDf_BOTHMODEL)) goto Fail;
 initphase |= ifRETQUEUE;

 if (err = loQueueAsync_init(&q_req, &async, se->driver.ldQueueMax)) goto Fail;
 initphase |= ifREQQUEUE;

 if (err = loThrControl_init(&async)) goto Fail;
 initphase |= ifLKASYNC;

#if LO_USE_OBJTRACK
 if (err = lw_rmutex_init(&otrk.ot_lk, 0)) goto Fail;
 initphase |= ifOBJTRACK;
#endif

#if LO_USE_FREEMARSHALL
 if (/*se->driver.*/ldFlags & loDf_FREEMARSH)
   CoCreateFreeThreadedMarshaler((IOPCServer*)this, &freemarsh);
 UL_DEBUG((LOGID, "LightOPCServer( free marsh %p)",freemarsh));
 /* there are nothing bad if it fails */
#endif
 /* final step */
// iam = this;
Fail:
 UL_TRACE((LOGID, "%!e LightOPCServer(%ls)", err, loWnul(ostatus.szVendorInfo)));
 return err;
}

void LightOPCServer::selfdestroy(void)
{
#if 0
 void (*rh)(void *, loService *, loClient *) = release_handle; release_handle = 0;
 void  *rha = release_handle_arg; release_handle_arg = 0;
 loService *service = se;
 loClient *client = (loClient*)this;
 delete this;
 if (rh) rh(rha, service, client);  /* When we should call release_handle() ? */
#else
 delete this;
#endif
}

#define loDf_ALL (loDf_DWG | loDf_NOFORCE | loDf_EE_SFALSE |\
                  loDf_FREEMARSH|loDf_BOTHMODEL|loDf_FREEMODEL)

int loClientCreate_agg(loService *se, loClient **cli, 
                   IUnknown *outer, IUnknown **inner,
                   int ldFlags,
                   const loVendorInfo *vi,
                   void (*release_handle)(void *, loService *, loClient *),
                   void *release_handle_arg)
{
 int rv = 0;
 LightOPCServer *srv;

 if (cli) *cli = 0;
 if (inner) *inner = 0;
 if (!cli || (ldFlags & ~loDf_ALL)) return EINVAL;

 if (!loSERVICE_OK(se)) return EBADF;

/******************************************************************/
class LightOPCServer_aggregator: public LightOPCServer
{
public:
  class LightOPCServer_delegator: public IUnknown
  {
  public:
    LightOPCServer *inner;
    STDMETHOD_ (ULONG, AddRef)(void)  { return inner->LightOPCServer::AddRef(); }
    STDMETHOD_ (ULONG, Release)(void) { return inner->LightOPCServer::Release(); }
    STDMETHOD (QueryInterface)(REFIID riid, void **ppv)
         { 
           if (IsEqualIID(riid, IID_IUnknown)) 
             { *ppv = (void*)this; AddRef(); return S_OK; }
           return inner->LightOPCServer::QueryInterface(riid, ppv); 
         }
  } delegator;
  IUnknown *outer;

  STDMETHOD_ (ULONG, AddRef)(void)  { return outer->AddRef(); }
  STDMETHOD_ (ULONG, Release)(void) { return outer->Release(); }
  STDMETHOD (QueryInterface)(REFIID riid, void **ppv)
       { return outer->QueryInterface(riid, ppv); }     

  LightOPCServer_aggregator(IUnknown *Outer) 
    { delegator.inner = this; outer = Outer; }
} *agg = 0;
/******************************************************************/

 if (outer)
   {
    if (!inner) return EINVAL;
    agg = new LightOPCServer_aggregator(outer);
    if (srv = agg) agg->delegator.AddRef();
    else return ENOMEM;
   }
 else if (srv = new LightOPCServer) srv->AddRef();
 else return ENOMEM;
 
 if ((rv = srv->initialize(se, ldFlags, vi)))
   {
    UL_ERROR((LOGID, "%!e loClientCreate()::initialize(%p) FAILED", rv, srv));
   }
 else if ((rv = srv->attach())/* && loIS_VALID(srv)*/)
   {
    UL_ERROR((LOGID, "%!e loClientCreate()::attach(%p) FAILED", rv, srv));
   }
 else
   {
    srv->release_handle = release_handle;
    srv->release_handle_arg = release_handle_arg;
    srv->ctxt.cactx.ca_cli_arg = release_handle_arg;
    srv->ctxt.cactx.ca_cli = srv;
    *cli = srv;
    if (agg) *inner = &agg->delegator;
    return 0; /*** Success ***/
   }
 //srv->Release(); /* Release doesn't check for initialize() faults*/
 delete srv;
 return rv;
}

int loClientCreate(loService *se, loClient **cli, int ldFlags,
                   const loVendorInfo *vi,
                   void (*release_handle)(void *, loService *, loClient *),
                   void *release_handle_arg)
{
  return loClientCreate_agg(se, cli, NULL, NULL, 
                            ldFlags, vi, 
                            release_handle, release_handle_arg);
}

int loClientChain(loClient *cli,
                  HRESULT (*qi_chain)(void *rha, loService *, loClient *,
                                      const IID *, LPVOID *),
                  void (*release_handle)(void *rha, loService *, loClient *),
                  void *release_handle_arg)
{
 if (!loIS_VALID(cli)) return EBADF;

 cli->qi_chain = qi_chain;
 cli->ctxt.cactx.ca_cli_arg = release_handle_arg;
 cli->release_handle_arg = release_handle_arg;
 cli->release_handle = release_handle;
 return 0;
}

int loClientAccessMode(loService *se, loClient *cli, int accmode)
{
 int rv = EBADF;

 if (accmode != loAM_RDWR &&
    (accmode & ~(loAM_RDONLY_OP | loAM_RDONLY_ADD | loAM_RDONLY_BROWSE |
                 loAM_NOREAD_DEV | loAM_ERREAD_DEV))) return EINVAL;
 if (loSERVICE_OK(se))
   {
    lw_mutex_lock(&se->lkList);
    if (!se->shutdown)
      {
       LightOPCServer *los = (LightOPCServer*)se->servlist;
       for(rv = ENOENT; los; los = los->serv_next)
         if (!cli || los == cli)
           {
            los->access_mode = accmode;
            rv = 0;
           }
      }
    lw_mutex_unlock(&se->lkList);
   }
 return rv;
}

LightOPCServer::~LightOPCServer()
{
 iam = 0;

 if (!otrk.ot_stopped) otrk.ot_stopped = 1;
 UL_TRACE((LOG_SR("~LightOPCServer(%ls)"), loWnul(ostatus.szVendorInfo)));
 LO_HEAPCHECK(this);

 if (initphase & ifLKASYNC)
   {
    loThrControl_stop(&async);
    loQueueBcast_abort(&q_ret);
    loQueueAsync_clear(&q_req);
   }

 if (grl.gl_count)
   UL_WARNING((LOG_SR("Still unreleased %d groups"), grl.gl_count));

 if (shutdown_conn.request)
   UL_WARNING((LOG_SR("Unsafe Shutdown notification aborted")));
// loShutdownConn_call(&shutdown_conn);
 loShutdownConn_clear(&shutdown_conn);

 if (initphase & ifATTACHED)
   {
    loQueueBcast_abort(&q_ret);
    /* clear_all(); - performed in detach() */
    detach(); initphase &= ~ifATTACHED;
   }

 if ((initphase & ifOBJTRACK) && otrk.ot_disconnect_all(1))
   UL_WARNING((LOG_SR("Some Enumerators left unreleased")));

#if LO_USE_FREEMARSHALL
 if (freemarsh) { freemarsh->Release(); freemarsh = 0; }
#endif

 if (initphase & ifRETQUEUE)
   {
    loQueueBcast_destroy(&q_ret); initphase &= ~ifRETQUEUE;
   }
 if (initphase & ifREQQUEUE)
   {
    loQueueAsync_destroy(&q_req); initphase &= ~ifREQQUEUE;
   }

 if (initphase & ifLKASYNC)
   {
    loThrControl_destroy(&async); initphase &= ~ifLKASYNC;
   }

 if (initphase & ifLKALL)
   {
    lw_rwlock_destroy(&lk_all); initphase &= ~ifLKALL;
   }
 if (initphase & ifLKREMOVE)
   {
    lw_rwlock_destroy(&lk_remove); initphase &= ~ifLKREMOVE;
   }
 if (initphase & ifLKBROWSE)
   {
    lw_mutex_destroy(&lk_browse); initphase &= ~ifLKBROWSE;
   }

#if LO_USE_OBJTRACK
 if (initphase & ifOBJTRACK)
   {
    lw_rmutex_destroy(&otrk.ot_lk); initphase &= ~ifOBJTRACK;
   }
#endif

 del_all();

 loStringBuf_clear(&browsepos);

 if (ostatus.szVendorInfo) freeX(ostatus.szVendorInfo), ostatus.szVendorInfo = 0;
#if LO_USE_BOTHMODEL
 if (ole_initialized)
   UL_ERROR((LOGID, "OLE didn't uninitialized!"));
#endif
 if (initphase)
   UL_ERROR((LOGID, "Left unreleased: 0x%X", initphase));

 loShutdownConn_clear(&shutdown_conn);
 glGrowList_clear(&grl);

 if (release_handle) release_handle(release_handle_arg, se, (loClient*)this),
                     release_handle = 0;
 LO_HEAPCHECK(this);
}

void LightOPCServer::clear_all(void)
{
// if (initphase & ifLKBROWSE)
   {
    lw_mutex_lock(&lk_browse);
    loStringBuf_clear(&browsepos);
    lw_mutex_unlock(&lk_browse);
   }
// else if (br_position) freeX(br_position), br_position = 0, br_size = 0;
 loQueueAsync_clear(&q_req);
 loQueueBcast_abort(&q_ret);
// if (initphase & ifLKALL)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -