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

📄 cacheupd.c

📁 OPCSERVER源代码
💻 C
字号:
/**************************************************************************
 *                                                                        *
 * Light OPC Server development library                                   *
 *                                                                        *
 *   Copyright (c) 2000 by Timofei Bondarenko                             *
                                                                          *
 Cache updating & related routines
 **************************************************************************/
#include <errno.h>
#include "loserv.h"
#include "util.h"

/**************************************************************************/

loTrid loTridLast(loService *se) /* get the last id of primary cache update. */
{
 loTrid trid;
 if (!loSERVICE_OK(se)) return 0;
 lw_rw_rdlock(&se->lkPrim);
 trid = se->update_pipe.tstate < 0? 0: se->prim_trid;
 lw_rw_unlock(&se->lkPrim);
 return trid;
}

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 loTridOrder(loTrid earlier, loTrid latter)
{
 unsigned trdif = latter - earlier;
 return (earlier && latter && trdif < ~trdif);
}

/**************************************************************************/

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;
}

loTrid loCacheUnlock(loService *se, FILETIME *timestamp)
{
 if (!loIS_VALID(se)) return 0;
 if (se->update_pipe.tstate >= 0) se->update_pipe.tstate = 1;
 if (se->sec_trid == se->prim_trid) ++se->sec_trid;
 if (loTRIDmin > se->sec_trid) se->sec_trid = loTRIDmin;
#if 0 != LO_EV_TIMESTAMP
 if (timestamp) se->ts_sec[se->ts_size] = *timestamp;
#endif
 lw_conds_signal(&se->update_pipe.cond);
 lw_mutex_unlock(&se->update_pipe.lk);
 return se->sec_trid;
}

int loCacheTimestamp(loService *se, unsigned count, const FILETIME ts[])
{
 int rv = 0;

 if (!loSERVICE_OK(se)) return EBADF; /*ERROR:EARG*/
#if 0 != LO_EV_TIMESTAMP
 if (!ts) return EINVAL;
 if (count > se->ts_size)
   {
    FILETIME *tsn;

    if (count > 0xffff) return EINVAL;    
    
    tsn = (FILETIME*)reallocX(se->ts_sec != se->ts_prim? 
                              se->ts_sec: 0, 
                              count * 2 * sizeof(FILETIME));
    if (tsn) se->ts_sec = tsn, se->ts_size = count;
    else rv = ENOMEM, count = se->ts_size;
   }
 memcpy(se->ts_sec + se->ts_size, ts, count * sizeof(FILETIME));
#endif
 return rv;
}

loTrid loCacheUpdate(loService *se, unsigned count, loTagValue taglist[], FILETIME *timestamp)
{
 unsigned ii;
 loTagValue *ts;
#if 0 != LO_FILL_TIMESTAMP
 FILETIME ft;
#endif
// UL_DEBUG((LOGID, "loCacheUpdate(%p %u %p)", se, count, taglist));
 if (!loSERVICE_OK(se)) return 0;//EBADF; /*ERROR:EARG*/
 if (!timestamp && (0 >= count || !taglist)) return 0;
#if 0 != LO_FILL_TIMESTAMP
#if 1 == LO_FILL_TIMESTAMP
 se->driver.ldCurrentTime(&se->cactx, &ft);
#else
 if (timestamp) ft = *timestamp;
 else memset(&ft, 0, sizeof(ft));
#endif
#endif

 if (!(ts = loCacheLock(se)))
   {
    UL_INFO((LOGID, "loCacheUpdate() lock failed"));
    return 0;//-1; /*ERROR:out-of-service*/
   }

 for(ii = 0; ii < count; ii++, taglist++)
   {
    loTagId ti;

    if (0 == (ti = taglist->tvTi)) continue;
    else if (ti < 1 || ti > se->lastused/*tag_count*/)
      {
       /*rv = -1;*//*ERROR:BAD ti*/
       UL_INFO((LOGID, "loCacheUpdate(BAD ti:%u)", ii));
       continue;
      }
    else
      {
       HRESULT hr;
       loTagValue *tv = &ts[ti];
       tv->tvState = taglist->tvState;
#if 0 != LO_FILL_TIMESTAMP
       if (!IsFILETIME(tv->tvState.tsTime)) tv->tvState.tsTime = ft;
#endif
/*     hr = (V_ISBYREF(&taglist->tvValue)?
                       VariantCopyInd(&tv->tvValue, &taglist->tvValue):
                       VariantCopy(&tv->tvValue, &taglist->tvValue)); */
       hr = VariantCopy(&tv->tvValue, &taglist->tvValue);
       if (S_OK != hr)
         {
          LO_E_BADTYPE_QUAL(hr, tv->tvState.tsError,
                            tv->tvState.tsQuality);
          /*rv = -1;*//*ERROR:BAD VALUE*/
          UL_WARNING((LOGID, "%!l loCacheUpdate(VariantCopy())", hr));
         }
       tv->tvTi = ti;
      }
   }
 return loCacheUnlock(se, timestamp);
/* return rv; */
}

/**************************************************************************/

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;
}

#if 2 == LO_EV_TIMESTAMP

void lo_check_ev_timestamp(unsigned count, FILETIME *timestamp, 
                           const FILETIME *master)
{
 while(count--)
   {
    if (!IsFILETIME(*timestamp)) 
      *timestamp = loFT_SUBST(*timestamp, master);
    timestamp++;
   }
}

#endif
/**************************************************************************/
/* cacheupd.c */

⌨️ 快捷键说明

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