コード例 #1
0
long epicsShareAPI dbtr(const char *pname)
{
    DBADDR addr;
    long status;
    struct dbCommon *precord;

    if (!pname || !*pname) {
        printf("Usage: dbtr \"pv name\"\n");
        return 1;
    }

    if (nameToAddr(pname, &addr))
        return -1;

    precord = (struct dbCommon*)addr.precord;
    if (precord->pact) {
        printf("record active\n");
        return 1;
    }

    dbScanLock(precord);
    status = dbProcess(precord);
    dbScanUnlock(precord);

    if (status)
        recGblRecordError(status, precord, "dbtr(dbProcess)");

    dbpr(pname, 3);
    return 0;
}
コード例 #2
0
ファイル: dbPvPut.cpp プロジェクト: pheest/pvaSrv
void DbPvPut::put(PVStructurePtr const &pvStructure, BitSetPtr const & bitSet)
{
    if (DbPvDebug::getLevel() > 0) printf("dbPvPut::put()\n");

    this->pvStructure = pvStructure;
    this->bitSet = bitSet;

    if (block && process) {
        dbProcessNotify(pNotify.get());
        return;
    }

    Lock lock(dataMutex);
    PVFieldPtr pvField = pvStructure.get()->getPVFields()[0];
    if (propertyMask & dbUtil->dbPutBit) {
        status = dbUtil->putField(
                    channelPutRequester,
                    propertyMask,
                    dbPv->getDbChannel(),
                    pvField);
    } else {
        dbScanLock(dbChannelRecord(dbPv->getDbChannel()));
        status = dbUtil->put(
                    channelPutRequester, propertyMask, dbPv->getDbChannel(), pvField);
        if (process) dbProcess(dbChannelRecord(dbPv->getDbChannel()));
        dbScanUnlock(dbChannelRecord(dbPv->getDbChannel()));
    }
    lock.unlock();
    channelPutRequester->putDone(status, getPtrSelf());
}
コード例 #3
0
ファイル: dbPvPut.cpp プロジェクト: dhickin/pvaSrv
void DbPvPut::put(PVStructurePtr const &pvStructure, BitSetPtr const & bitSet)
{
    if(DbPvDebug::getLevel()>0) printf("dbPvPut::put()\n");
    Lock lock(dataMutex);
    this->pvStructure = pvStructure;
    this->bitSet = bitSet;
    PVFieldPtr pvField = pvStructure.get()->getPVFields()[0];
    if(propertyMask&dbUtil->dbPutBit) {
        Status status = dbUtil->putField(
            channelPutRequester,propertyMask,dbAddr,pvField);
        lock.unlock();
        channelPutRequester->putDone(status,getPtrSelf());
        return;
    }
    dbScanLock(dbAddr.precord);
    Status status = dbUtil->put(
                channelPutRequester, propertyMask, dbAddr, pvField);
    if (process && !block) dbProcess(dbAddr.precord);
    dbScanUnlock(dbAddr.precord);
    lock.unlock();
    if (block && process) {
        epicsUInt8 value = 1;
        pNotify.get()->pbuffer = &value;
        dbPutNotify(pNotify.get());
    } else {
        channelPutRequester->putDone(status, getPtrSelf());
    }
}
コード例 #4
0
ファイル: devAsynFloat64.c プロジェクト: epics-modules/asyn
static void outputCallbackCallback(CALLBACK *pcb)
{
    devPvt *pPvt; 
    static const char *functionName="outputCallbackCallback";

    callbackGetUser(pPvt, pcb);
    {
        dbCommon *pr = pPvt->pr;
        dbScanLock(pr);
        epicsMutexLock(pPvt->devPvtLock);
        pPvt->newOutputCallbackValue = 1;
        dbProcess(pr);
        if (pPvt->newOutputCallbackValue != 0) {
            /* We called dbProcess but the record did not process, perhaps because PACT was 1 
             * Need to remove ring buffer element */
            asynPrint(pPvt->pasynUser, ASYN_TRACE_ERROR, 
                "%s %s::%s warning dbProcess did not process record, PACT=%d\n", 
                pr->name, driverName, functionName,pr->pact);
            getCallbackValue(pPvt);
            pPvt->newOutputCallbackValue = 0;
        }
        epicsMutexUnlock(pPvt->devPvtLock);
        dbScanUnlock(pr);
    }
}
コード例 #5
0
ファイル: dbScan.c プロジェクト: T-A-R-L-A/EPICS-Base
static void scanList(scan_list *psl)
{
    /* When reading this code remember that the call to dbProcess can result
     * in the SCAN field being changed in an arbitrary number of records.
     */

    scan_element *pse;
    scan_element *prev = NULL;
    scan_element *next = NULL;

    epicsMutexMustLock(psl->lock);
    psl->modified = FALSE;
    pse = (scan_element *)ellFirst(&psl->list);
    if (pse) next = (scan_element *)ellNext(&pse->node);
    epicsMutexUnlock(psl->lock);

    while (pse) {
        struct dbCommon *precord = pse->precord;

        dbScanLock(precord);
        dbProcess(precord);
        dbScanUnlock(precord);

        epicsMutexMustLock(psl->lock);
        if (!psl->modified) {
            prev = pse;
            pse = (scan_element *)ellNext(&pse->node);
            if (pse) next = (scan_element *)ellNext(&pse->node);
        } else if (pse->pscan_list == psl) {
            /*This scan element is still in same scan list*/
            prev = pse;
            pse = (scan_element *)ellNext(&pse->node);
            if (pse) next = (scan_element *)ellNext(&pse->node);
            psl->modified = FALSE;
        } else if (prev && prev->pscan_list == psl) {
            /*Previous scan element is still in same scan list*/
            pse = (scan_element *)ellNext(&prev->node);
            if (pse) {
                prev = (scan_element *)ellPrevious(&pse->node);
                next = (scan_element *)ellNext(&pse->node);
            }
            psl->modified = FALSE;
        } else if (next && next->pscan_list == psl) {
            /*Next scan element is still in same scan list*/
            pse = next;
            prev = (scan_element *)ellPrevious(&pse->node);
            next = (scan_element *)ellNext(&pse->node);
            psl->modified = FALSE;
        } else {
            /*Too many changes. Just wait till next period*/
            epicsMutexUnlock(psl->lock);
            return;
        }
        epicsMutexUnlock(psl->lock);
    }
}
コード例 #6
0
ファイル: dbAccess.c プロジェクト: ukaea/epics
/*
 *  Process a record if its scan field is passive.
 *     Will notify if processing is complete by callback.
 *       (only if you are interested in completion)
 */
long dbScanPassive(dbCommon *pfrom, dbCommon *pto)
{
    /* if not passive just return success */
    if (pto->scan != 0)
        return 0;

    if (pfrom && pfrom->ppn)
        dbNotifyAdd(pfrom,pto);
    return dbProcess(pto);
}
コード例 #7
0
ファイル: dbAccess.c プロジェクト: T-A-R-L-A/EPICS-Base
/*
 *  Process a record if its scan field is passive.
 *     Will notify if processing is complete by callback.
 *       (only if you are interested in completion)
 */
long epicsShareAPI dbScanPassive(dbCommon *pfrom, dbCommon *pto)
{
    long status;
	
    /* if not passive just return success */
    if(pto->scan != 0) return(0);

    if(pfrom && pfrom->ppn) dbNotifyAdd(pfrom,pto);
    status = dbProcess(pto);
    return(status);
}
コード例 #8
0
ファイル: dbAccess.c プロジェクト: T-A-R-L-A/EPICS-Base
/*KLUDGE: Following needed so that dbPutLink to PROC field works correctly*/
long epicsShareAPI dbScanLink(dbCommon *pfrom, dbCommon *pto)
{
    long		status;
    unsigned char	pact;

    if(pfrom && pfrom->ppn) dbNotifyAdd(pfrom,pto);
    pact = pfrom->pact;
    pfrom->pact = TRUE;
    status = dbProcess(pto);
    pfrom->pact = pact;
    return(status);
}
コード例 #9
0
ファイル: subIfDriver.cpp プロジェクト: Sangil-Lee/RefCode
static long subIfNetworkCalc(subRecord *precord)
{
#if 1
	DBADDR *pdbAddrA = dbGetPdbAddrFromLink(&precord->inpa);
	DBADDR *pdbAddrB = dbGetPdbAddrFromLink(&precord->inpb);
	DBADDR *pdbAddrC = dbGetPdbAddrFromLink(&precord->inpc);
	DBADDR *pdbAddrD = dbGetPdbAddrFromLink(&precord->inpd);
	DBADDR *pdbAddrE = dbGetPdbAddrFromLink(&precord->inpe);
	DBADDR *pdbAddrF = dbGetPdbAddrFromLink(&precord->inpf);
	//double *pfieldLinkA =  (double*)&pdbAddrA->pfield;
	//double *pfieldLinkB =  (double*)&pdbAddrB->pfield;
	if(!pdbAddrA || !pdbAddrB || !pdbAddrC || !pdbAddrD || !pdbAddrE || !pdbAddrF) return (1);

	aiRecord *pairecordLinkA = (aiRecord *)pdbAddrA->precord;
	aiRecord *pairecordLinkB = (aiRecord *)pdbAddrB->precord;
	aiRecord *pairecordLinkC = (aiRecord *)pdbAddrC->precord;
	aiRecord *pairecordLinkD = (aiRecord *)pdbAddrD->precord;
	aiRecord *pairecordLinkE = (aiRecord *)pdbAddrE->precord;
	aiRecord *pairecordLinkF = (aiRecord *)pdbAddrF->precord;

#if 0
	unsigned char pact = precord->pact;
	if(precord->udf == FALSE) 
	{
		recGblSetSevr(precord, UDF_ALARM, INVALID_ALARM);
		return 1;
	};
#endif

#if 1
	pifdriver->IfGetstats();
	//pifdriver->PrintByte();
	//printf("OutKB:%fKB, InKB:%fKB  \n", pifdriver->DiffKByteOut(5), pifdriver->DiffKByteIn(5));
		//pairecordLinkA->val = pifdriver->DiffKByteIn(5);
		//pairecordLinkB->val = pifdriver->DiffKByteOut(5);
		//pifdriver->DiffKByteCalc(pairecordLinkA->val,pairecordLinkB->val,5);
	if(pifdriver->IsEth1() == 0)
		pifdriver->DiffKByteCalc(pairecordLinkA->val,pairecordLinkB->val,precord->scan);
	else if(pifdriver->IsEth1() == 1 && pifdriver->IsEth2() == 0 )
		pifdriver->DiffKByteCalc(pairecordLinkA->val,pairecordLinkB->val,
						pairecordLinkC->val,pairecordLinkD->val, precord->scan);
	else 
		pifdriver->DiffKByteCalc(pairecordLinkA->val,pairecordLinkB->val,
						pairecordLinkC->val,pairecordLinkD->val, 
						pairecordLinkE->val,pairecordLinkF->val, precord->scan);
#endif
#endif
	dbProcess((dbCommon*)pairecordLinkA);
	dbProcess((dbCommon*)pairecordLinkB);
	dbProcess((dbCommon*)pairecordLinkC);
	dbProcess((dbCommon*)pairecordLinkD);
	dbProcess((dbCommon*)pairecordLinkE);
	dbProcess((dbCommon*)pairecordLinkF);
	return (0);
}
コード例 #10
0
ファイル: dbNotify.c プロジェクト: ukaea/epics
static void putNotifyCommon(putNotify *ppn,dbCommon *precord)
{
    long	status=0;
    dbFldDes	*pfldDes = ppn->paddr->pfldDes;
    putNotifyPvt *pputNotifyPvt = (putNotifyPvt *)ppn->pputNotifyPvt;

    if(precord->ppn && pputNotifyPvt->state!=putNotifyRestartCallbackRequested)
    { /*another putNotify owns the record */
        pputNotifyPvt->state = putNotifyWaitForRestart; 
        ellSafeAdd(&precord->ppnr->restartList,&ppn->restartNode);
        epicsMutexUnlock(pnotifyGlobal->lock);
        dbScanUnlock(precord);
        return;
    } else if(precord->ppn){
        assert(precord->ppn==ppn);
        assert(pputNotifyPvt->state==putNotifyRestartCallbackRequested);
    }
    if(precord->pact) {
        precord->ppn = ppn;
        ellSafeAdd(&pputNotifyPvt->waitList,&precord->ppnr->waitNode);
        pputNotifyPvt->state = putNotifyRestartInProgress; 
        epicsMutexUnlock(pnotifyGlobal->lock);
        dbScanUnlock(precord);
        return;
    }
    status=dbPut(ppn->paddr,ppn->dbrType,ppn->pbuffer,ppn->nRequest);
    ppn->status = (status==0) ? putNotifyOK : putNotifyError;
    /* Check to see if dbProcess should not be called */
    if(!status /*dont process if dbPut returned error */
    &&((ppn->paddr->pfield==(void *)&precord->proc) /*If PROC call dbProcess*/
       || (pfldDes->process_passive && precord->scan==0))) {
        precord->ppn = ppn;
        ellSafeAdd(&pputNotifyPvt->waitList,&precord->ppnr->waitNode);
        pputNotifyPvt->state = putNotifyPutInProgress;
        epicsMutexUnlock(pnotifyGlobal->lock);
        dbProcess(precord);
        dbScanUnlock(precord);
        return;
    }
    if(pputNotifyPvt->state==putNotifyRestartCallbackRequested) {
        restartCheck(precord->ppnr);
    }
    pputNotifyPvt->state = putNotifyUserCallbackActive;
    assert(precord->ppn!=ppn);
    callUser(precord,ppn);
}
コード例 #11
0
ファイル: dbAccess.c プロジェクト: T-A-R-L-A/EPICS-Base
long epicsShareAPI dbPutField(DBADDR *paddr, short dbrType,
    const void *pbuffer, long nRequest)
{
    long	status = 0;
    long	special  = paddr->special;
    dbFldDes	*pfldDes = paddr->pfldDes;
    dbCommon	*precord = paddr->precord;
    short	dbfType  = paddr->field_type;

    if (special == SPC_ATTRIBUTE)
        return S_db_noMod;

    /*check for putField disabled*/
    if (precord->disp &&
        (void *)(&precord->disp) != paddr->pfield)
        return S_db_putDisabled;

    if (dbfType >= DBF_INLINK && dbfType <= DBF_FWDLINK)
        return dbPutFieldLink(paddr, dbrType, pbuffer, nRequest);

    dbScanLock(precord);
    status = dbPut(paddr, dbrType, pbuffer, nRequest);
    if (status == 0) {
        if (paddr->pfield == (void *)&precord->proc ||
            (pfldDes->process_passive &&
             precord->scan == 0 &&
             dbrType < DBR_PUT_ACKT)) {
            if (precord->pact) {
                if (precord->tpro)
                    printf("%s: Active %s\n",
                        epicsThreadGetNameSelf(), precord->name);
                precord->rpro = TRUE;
            } else {
                /* indicate that dbPutField called dbProcess */
                precord->putf = TRUE;
                status = dbProcess(precord);
            }
        }
    }
    dbScanUnlock(precord);
    return status;
}
コード例 #12
0
ファイル: boRecord.c プロジェクト: epicsdeb/epics-base
static void myCallbackFunc(CALLBACK *arg)
{
    myCallback *pcallback;
    boRecord *prec;

    callbackGetUser(pcallback,arg);
    prec=(boRecord *)pcallback->precord;
    dbScanLock((struct dbCommon *)prec);
    if(prec->pact) {
	if((prec->val==1) && (prec->high>0)){
	    myCallback *pcallback;
	    pcallback = (myCallback *)(prec->rpvt);
            callbackSetPriority(prec->prio, &pcallback->callback);
            callbackRequestDelayed(&pcallback->callback,(double)prec->high);
	}
    } else {
	prec->val = 0;
	dbProcess((struct dbCommon *)prec);
    }
    dbScanUnlock((struct dbCommon *)prec);
}
コード例 #13
0
ファイル: dbScan.c プロジェクト: T-A-R-L-A/EPICS-Base
static void onceTask(void *arg)
{
    taskwdInsert(0, NULL, NULL);
    epicsEventSignal(startStopEvent);

    while (TRUE) {
        void *precord;

        epicsEventMustWait(onceSem);
        while ((precord = epicsRingPointerPop(onceQ))) {
            if (precord == &exitOnce) goto shutdown;
            dbScanLock(precord);
            dbProcess(precord);
            dbScanUnlock(precord);
        }
    }

shutdown:
    taskwdRemove(0);
    epicsEventSignal(startStopEvent);
}
コード例 #14
0
/*
 *  Process a record without printing it.
 */
long epicsShareAPI dbprc(char *record_name)
{
  struct dbAddr addr;
  struct dbCommon *precord;
  long status;

 /*
  *  Convert name to address
  */
  status = dbNameToAddr(record_name, &addr);
  if (status == S_db_notFound)
      printf("   BKPT> Record %s not found\n", record_name);
  if (status != 0) return(status);

  precord = addr.precord;

 /* lock lockset, process record, unlock lockset */
  dbScanLock(precord);
  status = dbProcess(precord);
  dbScanUnlock(precord);

  return(status);
}
コード例 #15
0
/*
 *  Task for continuing record processing
 *     1. Find lockset in stack for precord.
 *       DO 2-3 while breakpoints exist in the lockset.
 *        2. Wait on execution semaphore ...
 *        3. Run through every entrypoint in queue, processing
 *             those that are scheduled.
 *     4. Free resources for lockset, and exit task.
 */
static void dbBkptCont(dbCommon *precord)
{
  struct LS_LIST *pnode;
  struct EP_LIST *pqe = NULL;

 /*
  *  Reset breakpoint, process record, and
  *    reset bkpt field in record
  */
  epicsMutexMustLock(bkpt_stack_sem);

  FIND_LOCKSET(precord, pnode);

  if (pnode == NULL) {
    printf("   BKPT> Logic error in dbBkptCont()\n");
    return;
  }

 /*
  *  For every entrypoint scheduled, process.  Run process
  *    until there are no more breakpoints remaining in a
  *    lock set.
  */
  do {
   /* Give up semaphore before waiting to run ... */
    epicsMutexUnlock(bkpt_stack_sem);

   /* Wait to run */
    epicsEventMustWait(pnode->ex_sem);

   /* Bkpt stack must still be stable ! */
    epicsMutexMustLock(bkpt_stack_sem);

    pqe = (struct EP_LIST *) ellFirst(&pnode->ep_queue);

   /* Run through entrypoint queue */
    while (pqe != NULL) {
        /* check if entrypoint is currently scheduled */
         if (pqe->sched) {
             /* save current entrypoint */
              pnode->current_ep = pqe->entrypoint;

             /* lock the lockset, process record, unlock */
              dbScanLock(precord);
              dbProcess(pqe->entrypoint);
              dbScanUnlock(precord);

             /* reset schedule and stepping flag - Do this AFTER processing */
              pqe->sched = 0;
              pnode->step = 0;
         }
         pqe = (struct EP_LIST *) ellNext((ELLNODE *)pqe);
    }

   /* Reset precord. (Since no records are at a breakpoint) */
    pnode->precord = NULL;
  } while (ellCount(&pnode->bp_list) != 0);

 /* remove node from lockset stack */
  ellDelete(&lset_stack, (ELLNODE *)pnode);
  --lset_stack_count;

 /* free entrypoint queue */
  ellFree(&pnode->ep_queue);

 /* remove execution semaphore */
  epicsEventDestroy(pnode->ex_sem);

  printf("\n   BKPT> End debug of lockset %lu\n-> ", pnode->l_num);

 /* free list node */
  free(pnode);

  epicsMutexUnlock(bkpt_stack_sem);
}
コード例 #16
0
ファイル: dbNotify.c プロジェクト: epicsdeb/epics-base
static void processNotifyCommon(processNotify *ppn,dbCommon *precord)
{
    notifyPvt *pnotifyPvt = (notifyPvt *) ppn->pnotifyPvt;
    int didPut = 0;
    int doProcess = 0;

    if (precord->ppn &&
        pnotifyPvt->state != notifyRestartCallbackRequested) {
        /* Another processNotify owns the record */
        pnotifyPvt->state = notifyWaitForRestart; 
        ellSafeAdd(&precord->ppnr->restartList, &ppn->restartNode);
        epicsMutexUnlock(pnotifyGlobal->lock);
        dbScanUnlock(precord);
        return;
    } else if (precord->ppn) {
        assert(precord->ppn == ppn);
        assert(pnotifyPvt->state == notifyRestartCallbackRequested);
    }
    if (precord->pact) {
        precord->ppn = ppn;
        ellSafeAdd(&pnotifyPvt->waitList, &precord->ppnr->waitNode);
        pnotifyPvt->state = notifyRestartInProgress; 
        epicsMutexUnlock(pnotifyGlobal->lock);
        dbScanUnlock(precord);
        return;
    }
    if (ppn->requestType == putProcessRequest ||
        ppn->requestType == putProcessGetRequest) {
        /* Check if puts disabled */
        if (precord->disp && (dbChannelField(ppn->chan) != (void *) &precord->disp)) {
            ppn->putCallback(ppn, putDisabledType);
        } else {
            didPut = ppn->putCallback(ppn, putType);
        }
    }
    /* Check if dbProcess should be called */
    if (didPut &&
        ((dbChannelField(ppn->chan) == (void *) &precord->proc) ||
        (dbChannelFldDes(ppn->chan)->process_passive && precord->scan == 0)))
       doProcess = 1;
    else
        if (ppn->requestType == processGetRequest &&
            precord->scan == 0)
            doProcess = 1;

    if (doProcess) {
        ppn->wasProcessed = 1;
        precord->ppn = ppn;
        ellSafeAdd(&pnotifyPvt->waitList, &precord->ppnr->waitNode);
        pnotifyPvt->state = notifyProcessInProgress;
        epicsMutexUnlock(pnotifyGlobal->lock);
        dbProcess(precord);
        dbScanUnlock(precord);
        return;
    }
    if (pnotifyPvt->state == notifyRestartCallbackRequested) {
        restartCheck(precord->ppnr);
    }
    pnotifyPvt->state = notifyUserCallbackActive;
    assert(precord->ppn!=ppn);
    callDone(precord, ppn);
}
コード例 #17
0
ファイル: compressTest.c プロジェクト: ukaea/epics
static
void testFIFOCirc(void)
{
    aiRecord *vrec;
    compressRecord *crec;
    double *cbuf;

    testDiag("Test FIFO");

    testdbPrepare();

    testdbReadDatabase("recTestIoc.dbd", NULL, NULL);

    recTestIoc_registerRecordDeviceDriver(pdbbase);

    testdbReadDatabase("compressTest.db", NULL, "ALG=Circular Buffer,BALG=FIFO Buffer,NSAM=4");

    vrec = (aiRecord*)testdbRecordPtr("val");
    crec = (compressRecord*)testdbRecordPtr("comp");

    eltc(0);
    testIocInitOk();
    eltc(1);

    dbScanLock((dbCommon*)crec);
    cbuf = crec->bptr;

    testOk1(crec->off==0);
    testOk1(crec->inx==0);
    testOk1(crec->nuse==0);

    testDiag("Push 1.1");
    vrec->val = 1.1;
    dbProcess((dbCommon*)crec);

    /* In FIFO mode the valid elements are
     *   cbuf[(off-nuse-1) % size] through cbuf[(off-1) % size]
     */
    testOk1(crec->off==1);
    testOk1(crec->inx==0);
    testOk1(crec->nuse==1);
    testDEq(cbuf[0], 1.1, 0.1);
    testDEq(cbuf[1], 0.0, 0.1);
    testDEq(cbuf[2], 0.0, 0.1);
    testDEq(cbuf[3], 0.0, 0.1);
    checkArrD("comp", 1, 1.1, 0, 0, 0);

    testDiag("Push 2.1");
    vrec->val = 2.1;
    dbProcess((dbCommon*)crec);

    testOk1(crec->off==2);
    testOk1(crec->inx==0);
    testOk1(crec->nuse==2);
    testDEq(cbuf[0], 1.1, 0.1);
    testDEq(cbuf[1], 2.1, 0.1);
    testDEq(cbuf[2], 0.0, 0.1);
    testDEq(cbuf[3], 0.0, 0.1);
    checkArrD("comp", 2, 1.1, 2.1, 0, 0);

    testDiag("Push 3.1");
    vrec->val = 3.1;
    dbProcess((dbCommon*)crec);

    testOk1(crec->off==3);
    testOk1(crec->inx==0);
    testOk1(crec->nuse==3);
    testDEq(cbuf[0], 1.1, 0.1);
    testDEq(cbuf[1], 2.1, 0.1);
    testDEq(cbuf[2], 3.1, 0.1);
    testDEq(cbuf[3], 0.0, 0.1);
    checkArrD("comp", 3, 1.1, 2.1, 3.1, 0);

    testDiag("Push 4.1");
    vrec->val = 4.1;
    dbProcess((dbCommon*)crec);

    testOk1(crec->off==0);
    testOk1(crec->inx==0);
    testOk1(crec->nuse==4);
    testDEq(cbuf[0], 1.1, 0.1);
    testDEq(cbuf[1], 2.1, 0.1);
    testDEq(cbuf[2], 3.1, 0.1);
    testDEq(cbuf[3], 4.1, 0.1);
    checkArrD("comp", 4, 1.1, 2.1, 3.1, 4.1);

    testDiag("Push 5.1");
    vrec->val = 5.1;
    dbProcess((dbCommon*)crec);

    testOk1(crec->off==1);
    testOk1(crec->inx==0);
    testOk1(crec->nuse==4);
    testDEq(cbuf[0], 5.1, 0.1);
    testDEq(cbuf[1], 2.1, 0.1);
    testDEq(cbuf[2], 3.1, 0.1);
    testDEq(cbuf[3], 4.1, 0.1);
    checkArrD("comp", 4, 2.1, 3.1, 4.1, 5.1);

    testDiag("Push 6.1");
    vrec->val = 6.1;
    dbProcess((dbCommon*)crec);

    testOk1(crec->off==2);
    testOk1(crec->inx==0);
    testOk1(crec->nuse==4);
    testDEq(cbuf[0], 5.1, 0.1);
    testDEq(cbuf[1], 6.1, 0.1);
    testDEq(cbuf[2], 3.1, 0.1);
    testDEq(cbuf[3], 4.1, 0.1);
    checkArrD("comp", 4, 3.1, 4.1, 5.1, 6.1);

    dbScanUnlock((dbCommon*)crec);

    testDiag("Reset");
    testdbPutFieldOk("comp.RES", DBF_LONG, 0);

    dbScanLock((dbCommon*)crec);
    testOk1(crec->off==0);
    testOk1(crec->inx==0);
    testOk1(crec->nuse==0);
    checkArrD("comp", 0, 0, 0, 0, 0);
    dbScanUnlock((dbCommon*)crec);

    testIocShutdownOk();

    testdbCleanup();
}