Esempio n. 1
0
int epicsShareAPI astac(const char *pname,const char *user,const char *location)
{
    DBADDR	*paddr;
    long	status;
    ASCLIENTPVT	*pasclientpvt=NULL;
    dbCommon	*precord;
    dbFldDes	*pflddes;
    char	*puser;
    char	*plocation;

    paddr = dbCalloc(1,sizeof(DBADDR) + sizeof(ASCLIENTPVT));
    pasclientpvt = (ASCLIENTPVT *)(paddr + 1);
    status=dbNameToAddr(pname,paddr);
    if(status) {
	errMessage(status,"dbNameToAddr error");
	return(1);
    }
    precord = paddr->precord;
    pflddes = paddr->pfldDes;
    puser = asCalloc(1,strlen(user)+1);
    strcpy(puser,user);
    plocation = asCalloc(1,strlen(location)+1);
    strcpy(plocation,location);

    status = asAddClient(pasclientpvt,precord->asp,
	(int)pflddes->as_level,puser,plocation);
    if(status) {
	errMessage(status,"asAddClient error");
	return(1);
    } else {
	asPutClientPvt(*pasclientpvt,(void *)precord->name);
	asRegisterClientCallback(*pasclientpvt,astacCallback);
    }
    return(0);
}
Esempio n. 2
0
static
void checkArrI(const char *pv, long elen, epicsInt32 a, epicsInt32 b, epicsInt32 c, epicsInt32 d)
{
    epicsInt32 buf[4];
    epicsInt32 expect[4];
    long nReq = NELEMENTS(buf), i;
    unsigned match;
    DBADDR addr;

    expect[0] = a;
    expect[1] = b;
    expect[2] = c;
    expect[3] = d;

    if (dbNameToAddr(pv, &addr))
        testAbort("Unknown PV '%s'", pv);

    if (dbGet(&addr, DBR_LONG, buf, NULL, &nReq, NULL))
        testAbort("Failed to get '%s'", pv);

    match = elen==nReq;
    for (i=0; i<nReq && i<elen; i++) {
        match &= buf[i]==expect[i];
    }
    testOk(match, "dbGet(\"%s\") matches", pv);
    if (elen!=nReq)
        testDiag("lengths don't match %ld != %ld", elen, nReq);
    for (i=0; i<nReq && i<elen; i++) {
        if(buf[i]!=expect[i])
            testDiag("[%ld] -> %d != %d", i, (int)expect[i], (int)buf[i]);
    }
}
Esempio n. 3
0
long epicsShareAPI dbtpn(char	*pname,char *pvalue)
{
    long	status;
    tpnInfo     *ptpnInfo;
    DBADDR	*pdbaddr=NULL;
    putNotify	*ppn=NULL;
    char	*psavevalue;
    int		len;

    len = strlen(pvalue);
    /*allocate space for value immediately following DBADDR*/
    pdbaddr = dbCalloc(1,sizeof(DBADDR) + len+1);
    psavevalue = (char *)(pdbaddr + 1);
    strcpy(psavevalue,pvalue);
    status = dbNameToAddr(pname,pdbaddr);
    if(status) {
	errMessage(status, "dbtpn: dbNameToAddr");
	free((void *)pdbaddr);
	return(-1);
    }
    ppn = dbCalloc(1,sizeof(putNotify));
    ppn->paddr = pdbaddr;
    ppn->pbuffer = psavevalue;
    ppn->nRequest = 1;
    ppn->dbrType = DBR_STRING;
    ppn->userCallback = dbtpnCallback;
    ptpnInfo = dbCalloc(1,sizeof(tpnInfo));
    ptpnInfo->ppn = ppn;
    ptpnInfo->callbackDone = epicsEventCreate(epicsEventEmpty);
    ppn->usrPvt = ptpnInfo;
    epicsThreadCreate("dbtpn",epicsThreadPriorityHigh,
        epicsThreadGetStackSize(epicsThreadStackMedium),
        tpnThread,ptpnInfo);
    return(0);
}
Esempio n. 4
0
/* toggle printing after processing a certain record */
long epicsShareAPI dbap(const 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;

 /*
  *  Toggle print after process field in record
  */
  if (precord->bkpt & BKPT_PRINT_MASK) {
     printf("   BKPT> Auto print off for record %s\n", precord->name);
     precord->bkpt &= BKPT_PRINT_OFF_MASK;
  }
  else {
     printf("   BKPT> Auto print on for record %s\n", precord->name);
     precord->bkpt |= BKPT_PRINT_MASK;
  }

  return(0);
}
Esempio n. 5
0
static
void checkArrD(const char *pv, long elen, double a, double b, double c, double d)
{
    double buf[4];
    double expect[4];
    long nReq = NELEMENTS(buf), i;
    unsigned match;
    DBADDR addr;

    expect[0] = a;
    expect[1] = b;
    expect[2] = c;
    expect[3] = d;

    if (dbNameToAddr(pv, &addr))
        testAbort("Unknown PV '%s'", pv);

    if (dbGet(&addr, DBR_DOUBLE, buf, NULL, &nReq, NULL))
        testAbort("Failed to get '%s'", pv);

    match = elen==nReq;
    for (i=0; i<nReq && i<elen; i++) {
        match &= fabs(buf[i]-expect[i])<0.01;
    }
    testOk(match, "dbGet(\"%s\") matches", pv);
    if (elen!=nReq)
        testDiag("lengths don't match %ld != %ld", elen, nReq);
    for (i=0; i<nReq && i<elen; i++) {
        if (fabs(buf[i]-expect[i])>=0.01)
            testDiag("[%ld] -> %f != %f", i, expect[i], buf[i]);
    }
}
Esempio n. 6
0
static long initSiWriteRead(stringinRecord *precord)
{
    DBLINK        *plink = &precord->inp;
    devPvt        *pdevPvt;
    asynStatus    status;
    asynUser      *pasynUser;
    asynInterface *pasynInterface;
    asynOctet     *poctet;
    char          *userParam = 0;

    pdevPvt = callocMustSucceed(1,sizeof(*pdevPvt),"devTestBlock::initCommon");
    precord->dpvt = pdevPvt;
    pdevPvt->precord = (dbCommon *)precord;
    /* Create asynUser */
    pasynUser = pasynManager->createAsynUser(callbackSiWriteRead, 0);
    pasynUser->userPvt = pdevPvt;
    pdevPvt->pasynUser = pasynUser;
    status = pasynEpicsUtils->parseLink(pasynUser, plink, 
                &pdevPvt->portName, &pdevPvt->addr,&userParam);
    if (status != asynSuccess) {
        printf("%s devTestBlock::initCommon error in link %s\n",
                     precord->name, pasynUser->errorMessage);
        goto bad;
    }
    /* see if initial VAL is "blockAll" */
    if(strcmp(precord->val,"blockAll")==0) pdevPvt->blockAll = 1;
    /* let queueDelay just be .1*/
    pdevPvt->queueDelay = .1;
    /* Connect to device */
    status = pasynManager->connectDevice(pasynUser,
        pdevPvt->portName, pdevPvt->addr);
    if (status != asynSuccess) {
        printf("%s devTestBlock::initCommon connectDevice failed %s\n",
                     precord->name, pasynUser->errorMessage);
        goto bad;
    }
    pasynInterface = pasynManager->findInterface(pasynUser,asynOctetType,1);
    if(!pasynInterface) {
        printf("%s devTestBlock::initCommon interface %s not found\n",
            precord->name,asynOctetType);
        goto bad;
    }
    pdevPvt->poctet = poctet = pasynInterface->pinterface;
    pdevPvt->octetPvt = pasynInterface->drvPvt;
    callbackSetCallback(queueItDelayed,&pdevPvt->callback);
    callbackSetUser(pdevPvt,&pdevPvt->callback);
    if(dbNameToAddr(userParam,&pdevPvt->dbAddr)) {
        printf("%s devTestBlock:initDbAddr record %s not present\n",
            precord->name,userParam);
        precord->pact = 1;
    }
    return(0);

bad:
   precord->pact=1;
   return(-1);
}
Esempio n. 7
0
static long nameToAddr(const char *pname, DBADDR *paddr)
{
    long status = dbNameToAddr(pname, paddr);

    if (status) {
        printf("PV '%s' not found\n", pname);
    }
    return status;
}
Esempio n. 8
0
bool DbPvPut::init(PVStructure::shared_pointer const &pvRequest)
{
    propertyMask = dbUtil->getProperties(
        channelPutRequester,
        pvRequest,
        dbAddr,
        true);
    if(propertyMask==dbUtil->noAccessBit) return false;
    if(propertyMask==dbUtil->noModBit) {
        channelPutRequester->message(
             "field not allowed to be changed",errorMessage);
        return 0;
    }
    pvStructure = PVStructure::shared_pointer(
        dbUtil->createPVStructure(
            channelPutRequester,
            propertyMask,
            dbAddr,
            pvRequest));
    if (!pvStructure.get()) return false;
    if (propertyMask & dbUtil->dbPutBit) {
        if (propertyMask & dbUtil->processBit) {
            channelPutRequester->message(
                        "process determined by dbPutField", errorMessage);
        }
    } else if (propertyMask&dbUtil->processBit) {
        process = true;
        pNotify.reset(new (struct putNotify)());
        notifyAddr.reset(new DbAddr());
        memcpy(notifyAddr.get(), &dbAddr, sizeof(DbAddr));
        DbAddr *paddr = notifyAddr.get();
        struct dbCommon *precord = paddr->precord;
        char buffer[sizeof(precord->name) + 10];
        strcpy(buffer, precord->name);
        strcat(buffer, ".PROC");
        if (dbNameToAddr(buffer, paddr)) {
            throw std::logic_error("dbNameToAddr failed");
        }
        struct putNotify *pn = pNotify.get();
        pn->userCallback = this->notifyCallback;
        pn->paddr        = paddr;
        pn->nRequest     = 1;
        pn->dbrType      = DBR_CHAR;
        pn->usrPvt       = this;
        if (propertyMask & dbUtil->blockBit) block = true;
    }
    int numFields = pvStructure->getNumberFields();
    bitSet.reset(new BitSet(numFields));
    channelPutRequester->channelPutConnect(
       Status::Ok,
       getPtrSelf(),
       pvStructure->getStructure());
    return true;
}
Esempio n. 9
0
/*
 *  Fills out pnode and precord structures for dbc() and dbs()
 *      MUST LOCK OUT STACK BEFORE ENTRY
 */
static long FIND_CONT_NODE(
  const char *record_name,
  struct LS_LIST **ppnode,
  struct dbCommon **pprecord)
{
  struct dbAddr addr; 
  struct LS_LIST *pnode;
  struct dbCommon *precord = NULL;
  long status = 0;

  if (record_name == NULL) {
    /*
     *  Search through stack, taking the first entry that
     *    is currently stopped at a breakpoint.
     */
     pnode = (struct LS_LIST *) ellFirst(&lset_stack); 
     while (pnode != NULL) {
        if (pnode->precord != NULL) {
           precord = pnode->precord;
           break;
        }
        pnode = (struct LS_LIST *) ellNext((ELLNODE *)pnode);
     }
  
     if (pnode == NULL) {
        printf("   BKPT> No records are currently stopped\n");
        return(S_db_notStopped);
     }
  }
  else {
    /*
     *  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;

     FIND_LOCKSET(precord, pnode);

     if (pnode == NULL || pnode->precord == NULL) {
        printf("   BKPT> Currently not stopped in this lockset\n");
        return(S_db_notStopped);
     }
  }

  *pprecord = precord;
  *ppnode = pnode;
  return(0);
}
Esempio n. 10
0
LOCAL int connect(void **pab1771IXPvt,DBLINK *plink,boolean *isEng)
{
    DBENTRY       dbEntry;
    DBENTRY       *pdbEntry = &dbEntry;
    DBADDR        dbAddr;
    deviceData	  *pdeviceData;
    ab1771IXRecord *precord;
    recordPvt	  *precordPvt;
    long	  status;
    char          buffer[MAX_BUFFER];
    char          *recordname = &buffer[0];
    char          *pstring;
    unsigned short signal;
    char          *pLeftbracket;
    char          *pRightbracket;

    if(plink->type!=INST_IO) return(ab1771IXFatalError);
    pstring = plink->value.instio.string;
    if(strlen(pstring)>=MAX_BUFFER) return(ab1771IXFatalError);
    strcpy(buffer,pstring);
    pLeftbracket = strchr(buffer,'['); pRightbracket = strchr(buffer,']');
    if(!pLeftbracket || !pRightbracket) {
	errlogPrintf("link was not of the form record[signal]\n");
	return(ab1771IXFatalError);
    }
    *pLeftbracket++ = '\0'; *pRightbracket = '\0';
    sscanf(pLeftbracket,"%hu",&signal);
    dbInitEntry(pdbbase,pdbEntry);
    status = dbFindRecord(pdbEntry,recordname);
    if(status) return(ab1771IXNoRecord);
    if(strcmp(dbGetRecordTypeName(pdbEntry),"ab1771IX")!=0)
	return(ab1771IXIllegalRecordType);
    dbFinishEntry(pdbEntry);
    status = dbNameToAddr(recordname,&dbAddr);
    if(status) return(ab1771IXNoRecord);
    precord = (ab1771IXRecord *)dbAddr.precord;
    if(!(precordPvt = (recordPvt *)precord->dpvt)) {
	printf("%s precordPvt is NULL ?\n",precord->name);
	return(ab1771IXFatalError);
    }
    if(signal>=NUM_CHANS) return(ab1771IXIllegalType);
    if(signal<=3) {
	*isEng = ((precord->typa==ab1771IX_TYPE_MV)?FALSE:TRUE);
    } else {
	*isEng = ((precord->typb==ab1771IX_TYPE_MV)?FALSE:TRUE);
    }
    pdeviceData = dbCalloc(1,sizeof(deviceData));
    pdeviceData->precord = precord;
    pdeviceData->signal = signal;
    *pab1771IXPvt = (void *)pdeviceData;
    return(ab1771IXOK);
}
Esempio n. 11
0
/*utility routine to dump raw messages*/
int ab1771IXpm(char *recordname)
{
    DBENTRY       dbEntry;
    DBENTRY       *pdbEntry = &dbEntry;
    DBADDR        dbAddr;
    ab1771IXRecord *precord;
    recordPvt	  *precordPvt;
    long	  status;
    short	  *pdata;
    int           i;

    dbInitEntry(pdbbase,pdbEntry);
    status = dbFindRecord(pdbEntry,recordname);
    if(status) {
	printf("Cant find %s\n",recordname);
	return(0);
    }
    if(strcmp(dbGetRecordTypeName(pdbEntry),"ab1771IX")!=0) {
	printf("Not a ab1771IXRecord\n");
	return(0);
    }
    dbFinishEntry(pdbEntry);
    status = dbNameToAddr(recordname,&dbAddr);
    if(status) {
	printf("Cant find %s\n",recordname);
	return(0);
    }
    precord = (ab1771IXRecord *)dbAddr.precord;
    if(!(precordPvt = (recordPvt *)precord->dpvt)) {
	printf("dpvt is NULL\n");
	return(0);
    }
    printf("output message");
    pdata = precord->outm;
    for(i=0; i< NUM_WORDS_OUT; i++) {
	if(i%10 == 0) printf("\n");
	printf(" %4hx",*pdata);
	pdata++;
    }
    printf("\ninput message");
    pdata = precord->inpm;
    for(i=0; i< NUM_WORDS_IN; i++) {
	if(i%10 == 0) printf("\n");
	printf(" %4hx",*pdata);
	pdata++;
    }
    printf("\n");
    return(0);
}
static long init_record_subArray( subArrayRecord *pior) {

	/* parse device dependent option string and set data pointer */
	struct dbAddr *pWfDbAddr;
	waveformRecord *pwf;

	dbNameToAddr(pior->inp.value.constantStr, pWfDbAddr);
	pwf = (waveformRecord*) pWfDbAddr->precord;
	if( pwf == 0 ) {
	    printf(__FILE__":%d: Error Can't find %s \n", __LINE__, pior->inp.value.constantStr);
	    exit(1);
	  }

	pior->dpvt = (void*) pwf;

	return(0);
}
Esempio n. 13
0
ChannelFind::shared_pointer DbPvProvider::channelFind(
    string const & channelName,
    ChannelFindRequester::shared_pointer const &channelFindRequester)
{
    struct dbAddr dbAddr;
    long result = dbNameToAddr(channelName.c_str(),&dbAddr);
    if(result==0) {
        channelFindRequester->channelFindResult(
            Status::Ok,
            channelFinder,
            true);
    } else {
        Status notFoundStatus(Status::STATUSTYPE_ERROR,"pv not found");
        channelFindRequester.get()->channelFindResult(
            notFoundStatus,
            channelFinder,
            false);
    }
    return channelFinder;
}
Esempio n. 14
0
void mdsPlusShotID(int param)
{
    int status;
    char buf[40];
    DBADDR    *paddr;

    paddr = (DBADDR *)dbCalloc(1, sizeof(struct dbAddr));

    /* sleep */
    epicsThreadSleep(2.0);
    /*status = dbPutLink(shotIdOutLink, DBR_LONG, &shotId, 1);*/
    /* Put next pulse number */
    sprintf(buf, "icrf:pulseid.VAL");
    status = dbNameToAddr(buf, paddr);
    status = dbPutField(paddr, DBR_LONG, &shotId, 1);

    free(paddr);
    if(genSubDebug > 0)
         printf("genSub: mdsPlusShotID()  next shot number [%ld]. Status=%d\n",shotId,status);

}
Esempio n. 15
0
/* Try to parse scan period from record's SCAN field.
 * Sounds simple, but I ended up with this mess.
 * Is there a more elegant way to get this?
 * Returns <= 0 for error.
 */
static double get_period(dbCommon *rec)
{
    char          *buf = 0, *p;
    size_t        buf_size = 0, len;
    struct dbAddr scan_field;
    long          options=0, count=1;
    double        period = -1.0;

    if (rec->scan < SCAN_1ST_PERIODIC)
        return period;
    
    /* Best guess for holding SCAN field name and value */
    if (! EIP_reserve_buffer((void**)&buf, &buf_size, 50))
        return period;
    /* Get SCAN field's address */
    len = strlen (rec->name);
    if (! EIP_reserve_buffer((void**)&buf, &buf_size, len+6))
        goto leave;
    memcpy(buf, rec->name, len);
    memcpy(buf+len, ".SCAN", 6);
    if (dbNameToAddr(buf, &scan_field) != 0)
        goto leave;

    /* Get value */
    len = dbBufferSize(DBR_STRING, options, count);
    if (! EIP_reserve_buffer((void**)&buf, &buf_size, len))
        goto leave;
    if (dbGet(&scan_field, DBR_STRING, buf, &options, &count, 0) != 0)
        goto leave;
    if (! strstr(buf, "second"))
        goto leave;
    period = strtod(buf, &p);
    if (p==buf || period==HUGE_VAL || period==-HUGE_VAL)
        period = -1.0;
  leave:
    free(buf);
    return period;
}
Esempio n. 16
0
static void hookPass1(initHookState state)
{
    DBENTRY entry;
    DBADDR  addr;
    if(state!=initHookAfterInitDatabase)
        return;
    testDiag("initHookAfterInitDatabase");

    dbInitEntry(pdbbase, &entry);

    if(dbFindRecord(&entry, "rec0.VAL")==0) {
        aoRecord *prec = entry.precnode->precord;
        testOk(prec->val==3, "VAL %d==3 (init_record value)", (int)prec->val);
        testOk1(dbPutString(&entry, "4")==0);
        testOk(prec->val==4, "VAL %d==4", (int)prec->val);
    } else{
        testFail("Missing rec0");
        testSkip(1, "missing record");
    }

    /* Can't restore links in pass 1 */

    if(dbNameToAddr("rec1.VAL", &addr)) {
        testFail("missing rec1");
        testSkip(3, "missing record");
    } else {
        struct rset *prset = dbGetRset(&addr);
        dbfType ftype = addr.field_type;
        long count=-1, offset=-1, maxcount = addr.no_elements;
        testOk1(prset && prset->get_array_info && prset->put_array_info);
        testOk1((*prset->get_array_info)(&addr, &count, &offset)==0);
        /* count is ignored */
        testOk1((*dbPutConvertRoutine[DBF_DOUBLE][ftype])(&addr, values, NELEMENTS(values), maxcount,offset)==0);
        testOk1((*prset->put_array_info)(&addr, NELEMENTS(values))==0);
    }

    dbFinishEntry(&entry);
}
Esempio n. 17
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);
}
Esempio n. 18
0
Channel::shared_pointer DbPvProvider::createChannel(
    string const & channelName,
    ChannelRequester::shared_pointer  const &channelRequester,
    short priority,
    string const & address)
{
    struct dbAddr dbAddr;
    long result = dbNameToAddr(channelName.c_str(),&dbAddr);
    if(result!=0) {
        Status notFoundStatus(Status::STATUSTYPE_ERROR,"pv not found");
        channelRequester->channelCreated(
            notFoundStatus,
            Channel::shared_pointer());
        return Channel::shared_pointer();
    }
    std::tr1::shared_ptr<DbAddr> addr(new DbAddr());
    memcpy(addr.get(),&dbAddr,sizeof(dbAddr));
    DbPvPtr v3Channel(new DbPv(
            getPtrSelf(),
            channelRequester,channelName,addr));
    v3Channel->init();
    channelRequester->channelCreated(Status::Ok,v3Channel);
    return v3Channel;
}
Esempio n. 19
0
static void checkLinks(acalcoutRecord *pcalc)
{
	DBLINK			*plink;
	rpvtStruct		*prpvt = (rpvtStruct *)pcalc->rpvt;
	int i;
	int				isCaLink   = 0;
	int				isCaLinkNc = 0;
	unsigned short	*plinkValid;
	dbAddr			Addr;
	dbAddr			*pAddr = &Addr;

	if (aCalcoutRecordDebug >= 10) printf("checkLinks() for %p\n", (void *)pcalc);

	plink   = &pcalc->inpa;
	plinkValid = &pcalc->inav;

	for (i=0; i<MAX_FIELDS+ARRAY_MAX_FIELDS+1; i++, plink++, plinkValid++) {
		if (plink->type == CA_LINK) {
			isCaLink = 1;
			if (dbCaIsLinkConnected(plink)) {
				if (*plinkValid == acalcoutINAV_EXT_NC) {
					*plinkValid = acalcoutINAV_EXT;
					db_post_events(pcalc,plinkValid,DBE_VALUE);
				}
				/* If this is the outlink, get the type of field it's connected to.  If it's connected
				 * to a link field, and the outlink is not a CA link, complain, because this won't work.
				 * Also, if .WAIT, then the link must be a CA link.
				 */
				if (plink == &pcalc->out) {
					prpvt->outlink_field_type = dbCaGetLinkDBFtype(plink);
					if (aCalcoutRecordDebug >= 10)
						printf("acalcout:checkLinks: outlink type = %d\n",
							prpvt->outlink_field_type);
					if (!dbNameToAddr(plink->value.pv_link.pvname, pAddr)) {
						if ((pAddr->field_type >= DBF_INLINK) &&
								(pAddr->field_type <= DBF_FWDLINK)) {
							if (!(plink->value.pv_link.pvlMask & pvlOptCA)) {
								printf("aCalcoutRecord(%s):checkLinks:non-CA link to link field\n",
									plink->value.pv_link.pvname);
							}
						}
					}
					if (pcalc->wait && !(plink->value.pv_link.pvlMask & pvlOptCA)) {
						printf("aCalcoutRecord(%s):checkLinks: Can't wait with non-CA link attribute\n",
							plink->value.pv_link.pvname);
					}
				}
			} else {
				if (*plinkValid == acalcoutINAV_EXT_NC) {
					isCaLinkNc = 1;
				}
				else if (*plinkValid == acalcoutINAV_EXT) {
					*plinkValid = acalcoutINAV_EXT_NC;
					db_post_events(pcalc,plinkValid,DBE_VALUE);
					isCaLinkNc = 1;
				}
				if (plink == &pcalc->out)
					prpvt->outlink_field_type = DBF_NOACCESS; /* don't know type */
			} 
		}
	}
	if (isCaLinkNc)
		prpvt->caLinkStat = CA_LINKS_NOT_OK;
	else if (isCaLink)
		prpvt->caLinkStat = CA_LINKS_ALL_OK;
	else
		prpvt->caLinkStat = NO_CA_LINKS;

	if (!prpvt->wd_id_1_LOCK && isCaLinkNc) {
		/* Schedule another CALLBACK */
		prpvt->wd_id_1_LOCK = 1;
		callbackRequestDelayed(&prpvt->checkLinkCb,.5);
	}
}
Esempio n. 20
0
static void check(short dbr_type) {
    dbChannel *pch;
    db_field_log *pfl, *pfl2;
    dbAddr valaddr;
    dbAddr offaddr;
    const char *offname = NULL, *valname = NULL, *typname = NULL;
    epicsInt32 ar[10] = {10,11,12,13,14,15,16,17,18,19};
    epicsInt32 *ar10_0_1 = ar;
    epicsInt32 ar10_4_1[10] = {14,15,16,17,18,19,10,11,12,13};
    epicsInt32 ar5_0_1[10] = {12,13,14,15,16};
    epicsInt32 ar5_3_1[10] = {15,16,17,18,19};
    epicsInt32 ar5_5_1[10] = {17,18,19,10,11};
    epicsInt32 ar5_9_1[10] = {11,12,13,14,15};
    epicsInt32 ar5_0_2[10] = {12,14,16};
    epicsInt32 ar5_3_2[10] = {15,17,19};
    epicsInt32 ar5_5_2[10] = {17,19,11};
    epicsInt32 ar5_9_2[10] = {11,13,15};
    epicsInt32 ar5_0_3[10] = {12,15};
    epicsInt32 ar5_3_3[10] = {15,18};
    epicsInt32 ar5_5_3[10] = {17,10};
    epicsInt32 ar5_9_3[10] = {11,14};
    epicsInt32 off = 0;

    switch (dbr_type) {
    case DBR_LONG:
        offname = "x.OFF";
        valname = "x.VAL";
        typname = "long";
        break;
    case DBR_DOUBLE:
        offname = "y.OFF";
        valname = "y.VAL";
        typname = "double";
        break;
    case DBR_STRING:
        offname = "z.OFF";
        valname = "z.VAL";
        typname = "string";
        break;
    default:
        testDiag("Invalid data type %d", dbr_type);
    }

    (void) dbNameToAddr(offname, &offaddr);

    (void) dbNameToAddr(valname, &valaddr);
    (void) dbPutField(&valaddr, DBR_LONG, ar, 10);

    /* Default: should not change anything */

    testHead("Ten %s elements from rec, increment 1, full size (default)", typname);
    createAndOpen(valname, "{\"arr\":{}}", "(default)", &pch, 1);
    testOk(pch->final_type == valaddr.field_type,
           "final type unchanged (%d->%d)", valaddr.field_type, pch->final_type);
    testOk(pch->final_no_elements == valaddr.no_elements,
           "final no_elements unchanged (%ld->%ld)", valaddr.no_elements, pch->final_no_elements);
    TEST1(10, 0, 1, "no offset");
    TEST1(10, 4, 1, "wrapped");
    dbChannelDelete(pch);

    testHead("Ten %s elements from rec, increment 1, out-of-bound start parameter", typname);
    createAndOpen(valname, "{\"arr\":{\"s\":-500}}", "out-of-bound start", &pch, 1);
    testOk(pch->final_type == valaddr.field_type,
           "final type unchanged (%d->%d)", valaddr.field_type, pch->final_type);
    testOk(pch->final_no_elements == valaddr.no_elements,
           "final no_elements unchanged (%ld->%ld)", valaddr.no_elements, pch->final_no_elements);
    TEST1(10, 4, 1, "wrapped");
    dbChannelDelete(pch);

    testHead("Ten %s elements from rec, increment 1, out-of-bound end parameter", typname);
    createAndOpen(valname, "{\"arr\":{\"e\":500}}", "out-of-bound end", &pch, 1);
    testOk(pch->final_type == valaddr.field_type,
           "final type unchanged (%d->%d)", valaddr.field_type, pch->final_type);
    testOk(pch->final_no_elements == valaddr.no_elements,
           "final no_elements unchanged (%ld->%ld)", valaddr.no_elements, pch->final_no_elements);
    TEST1(10, 4, 1, "wrapped");
    dbChannelDelete(pch);

    testHead("Ten %s elements from rec, increment 1, zero increment parameter", typname);
    createAndOpen(valname, "{\"arr\":{\"i\":0}}", "zero increment", &pch, 1);
    testOk(pch->final_type == valaddr.field_type,
           "final type unchanged (%d->%d)", valaddr.field_type, pch->final_type);
    testOk(pch->final_no_elements == valaddr.no_elements,
           "final no_elements unchanged (%ld->%ld)", valaddr.no_elements, pch->final_no_elements);
    TEST1(10, 4, 1, "wrapped");
    dbChannelDelete(pch);

    testHead("Ten %s elements from rec, increment 1, invalid increment parameter", typname);
    createAndOpen(valname, "{\"arr\":{\"i\":-30}}", "invalid increment", &pch, 1);
    testOk(pch->final_type == valaddr.field_type,
           "final type unchanged (%d->%d)", valaddr.field_type, pch->final_type);
    testOk(pch->final_no_elements == valaddr.no_elements,
           "final no_elements unchanged (%ld->%ld)", valaddr.no_elements, pch->final_no_elements);
    TEST1(10, 4, 1, "wrapped");
    dbChannelDelete(pch);

#define TEST5(Incr, Left, Right, Type) \
    testHead("Five %s elements from rec, increment " #Incr ", " Type " addressing", typname); \
    createAndOpen(valname, "{\"arr\":{\"s\":" #Left ",\"e\":" #Right ",\"i\":" #Incr "}}", \
                  "(" #Left ":" #Incr ":" #Right ")", &pch, 1); \
    testOk(pch->final_type == valaddr.field_type, \
           "final type unchanged (%d->%d)", valaddr.field_type, pch->final_type); \
    testOk(pch->final_no_elements == 4 / Incr + 1, \
           "final no_elements correct (%ld->%ld)", valaddr.no_elements, pch->final_no_elements); \
    TEST1(5, 0, Incr, "no offset"); \
    TEST1(5, 3, Incr, "from upper block"); \
    TEST1(5, 5, Incr, "wrapped"); \
    TEST1(5, 9, Incr, "from lower block"); \
    dbChannelDelete(pch);

    /* Contiguous block of 5 */

    TEST5(1,  2,  6, "regular");
    TEST5(1, -8,  6, "left side from-end");
    TEST5(1,  2, -4, "right side from-end");
    TEST5(1, -8, -4, "both sides from-end");

    /* 5 elements with increment 2 */

    TEST5(2,  2,  6, "regular");
    TEST5(2, -8,  6, "left side from-end");
    TEST5(2,  2, -4, "right side from-end");
    TEST5(2, -8, -4, "both sides from-end");

    /* 5 elements with increment 3 */

    TEST5(3,  2,  6, "regular");
    TEST5(3, -8,  6, "left side from-end");
    TEST5(3,  2, -4, "right side from-end");
    TEST5(3, -8, -4, "both sides from-end");

    /* From buffer (plugin chain) */

#define TEST5B(Incr, Left, Right, Type) \
    testHead("Five %s elements from buffer, increment " #Incr ", " Type " addressing", typname); \
    createAndOpen(valname, "{\"arr\":{},\"arr\":{\"s\":" #Left ",\"e\":" #Right ",\"i\":" #Incr "}}", \
                  "(" #Left ":" #Incr ":" #Right ")", &pch, 2); \
    testOk(pch->final_type == valaddr.field_type, \
           "final type unchanged (%d->%d)", valaddr.field_type, pch->final_type); \
    testOk(pch->final_no_elements == 4 / Incr + 1, \
           "final no_elements correct (%ld->%ld)", valaddr.no_elements, pch->final_no_elements); \
    TEST1(5, 0, Incr, "no offset"); \
    dbChannelDelete(pch);

    /* Contiguous block of 5 */

    TEST5B(1,  2,  6, "regular");
    TEST5B(1, -8,  6, "left side from-end");
    TEST5B(1,  2, -4, "right side from-end");
    TEST5B(1, -8, -4, "both sides from-end");

    /* 5 elements with increment 2 */

    TEST5B(2,  2,  6, "regular");
    TEST5B(2, -8,  6, "left side from-end");
    TEST5B(2,  2, -4, "right side from-end");
    TEST5B(2, -8, -4, "both sides from-end");

    /* 5 elements with increment 3 */

    TEST5B(3,  2,  6, "regular");
    TEST5B(3, -8,  6, "left side from-end");
    TEST5B(3,  2, -4, "right side from-end");
    TEST5B(3, -8, -4, "both sides from-end");
}
Esempio n. 21
0
static long dbPutFieldLink(DBADDR *paddr,
    short dbrType, const void *pbuffer, long nRequest)
{
    dbLinkInfo  link_info;
    DBADDR      *pdbaddr = NULL;
    dbCommon    *precord = paddr->precord;
    dbCommon    *lockrecs[2];
    dbLocker    locker;
    dbFldDes    *pfldDes = paddr->pfldDes;
    long        special = paddr->special;
    struct link *plink = (struct link *)paddr->pfield;
    const char  *pstring = (const char *)pbuffer;
    struct dsxt *old_dsxt = NULL;
    struct dset *new_dset = NULL;
    struct dsxt *new_dsxt = NULL;
    devSup      *new_devsup = NULL;
    long        status;
    int         isDevLink;
    short       scan;

    STATIC_ASSERT(DBLOCKER_NALLOC>=2);

    switch (dbrType) {
    case DBR_CHAR:
    case DBR_UCHAR:
        if (pstring[nRequest - 1] != '\0')
            return S_db_badDbrtype;
        break;

    case DBR_STRING:
        break;

    default:
        return S_db_badDbrtype;
    }

    status = dbParseLink(pstring, pfldDes->field_type, &link_info);
    if (status)
        return status;

    if (link_info.ltype == PV_LINK &&
        (link_info.modifiers & (pvlOptCA | pvlOptCP | pvlOptCPP)) == 0) {
        DBADDR tempaddr;

        if (dbNameToAddr(link_info.target, &tempaddr)==0) {
            /* This will become a DB link. */
            pdbaddr = malloc(sizeof(*pdbaddr));
            if (!pdbaddr) {
                status = S_db_noMemory;
                goto cleanup;
            }
            *pdbaddr = tempaddr; /* struct copy */
        }
    }

    isDevLink = ellCount(&precord->rdes->devList) > 0 &&
                pfldDes->isDevLink;

    memset(&locker, 0, sizeof(locker));
    lockrecs[0] = precord;
    lockrecs[1] = pdbaddr ? pdbaddr->precord : NULL;
    dbLockerPrepare(&locker, lockrecs, 2);

    dbScanLockMany(&locker);

    scan = precord->scan;

    if (isDevLink) {
        new_devsup = dbDTYPtoDevSup(precord->rdes, precord->dtyp);
        if (new_devsup) {
            new_dset = new_devsup->pdset;
            new_dsxt = new_devsup->pdsxt;
        }
    }

    if (dbCanSetLink(plink, &link_info, new_devsup)) {
        /* link type mis-match prevents assignment */
        status = S_dbLib_badField;
        goto unlock;
    }

    if (isDevLink) {
        if (precord->dset) {
            devSup *old_devsup = dbDSETtoDevSup(precord->rdes, precord->dset);

            if (old_devsup)
                old_dsxt = old_devsup->pdsxt;
        }

        if (new_dsxt == NULL ||
            new_dsxt->add_record == NULL ||
            (precord->dset && old_dsxt == NULL) ||
            (old_dsxt && old_dsxt->del_record == NULL)) {
            status = S_db_noSupport;
            goto unlock;
        }

        if (scan == menuScanI_O_Intr) {
            scanDelete(precord);
            precord->scan = menuScanPassive;
        }

        if (old_dsxt) {
            status = old_dsxt->del_record(precord);
            if (status)
                goto restoreScan;
        }
    }

    switch (plink->type) { /* Old link type */
    case DB_LINK:
    case CA_LINK:
    case CONSTANT:
        dbRemoveLink(&locker, plink);   /* link type becomes PV_LINK */
        break;

    case PV_LINK:
    case MACRO_LINK:
        break;  /* should never get here */

    default: /* Hardware address */
        if (!isDevLink) {
            status = S_db_badHWaddr;
            goto restoreScan;
        }
        break;
    }

    if (special) status = dbPutSpecial(paddr, 0);

    if (!status) status = dbSetLink(plink, &link_info, new_devsup);

    if (!status && special) status = dbPutSpecial(paddr, 1);

    if (status) {
        if (isDevLink) {
            precord->dset = NULL;
            precord->pact = TRUE;
        }
        goto postScanEvent;
    }

    if (isDevLink) {
        precord->dpvt = NULL;
        precord->dset = new_dset;
        precord->pact = FALSE;

        status = new_dsxt->add_record(precord);
        if (status) {
            precord->dset = NULL;
            precord->pact = TRUE;
            goto postScanEvent;
        }
    }

    switch (plink->type) { /* New link type */
    case PV_LINK:
    case CONSTANT:
        dbAddLink(&locker, plink, pfldDes->field_type, pdbaddr);
        break;

    case DB_LINK:
    case CA_LINK:
    case MACRO_LINK:
        break;  /* should never get here */

    default: /* Hardware address */
        if (!isDevLink) {
            status = S_db_badHWaddr;
            goto postScanEvent;
        }
        break;
    }
    db_post_events(precord, plink, DBE_VALUE | DBE_LOG);

restoreScan:
    if (isDevLink &&
        scan == menuScanI_O_Intr) { /* undo scanDelete() */
        precord->scan = scan;
        scanAdd(precord);
    }
postScanEvent:
    if (scan != precord->scan)
        db_post_events(precord, &precord->scan, DBE_VALUE | DBE_LOG);
unlock:
    dbScanUnlockMany(&locker);
    dbLockerFinalize(&locker);
cleanup:
    free(link_info.target);
    return status;
}
Esempio n. 22
0
static void check(short dbr_type) {
    dbChannel *pch;
    db_field_log *pfl;
    dbAddr valaddr;
    dbAddr offaddr;
    const char *offname = NULL, *valname = NULL, *typname = NULL;
    epicsInt32 buf[26];
    long off, req;
    int i;

    switch (dbr_type) {
    case DBR_LONG:
        offname = "i32.OFF";
        valname = "i32.VAL";
        typname = "long";
        break;
    case DBR_DOUBLE:
        offname = "f64.OFF";
        valname = "f64.VAL";
        typname = "double";
        break;
    case DBR_STRING:
        offname = "c40.OFF";
        valname = "c40.VAL";
        typname = "string";
        break;
    default:
        testDiag("Invalid data type %d", dbr_type);
    }

    (void) dbNameToAddr(offname, &offaddr);
    (void) dbNameToAddr(valname, &valaddr);

    testHead("Ten %s elements", typname);

    /* Fill the record's array field with data, 10..19 */

    epicsInt32 ar[10] = {10,11,12,13,14,15,16,17,18,19};
    (void) dbPutField(&valaddr, DBR_LONG, ar, 10);

    /* Open a channel to it, make sure no filters present */

    createAndOpen(valname, &pch);
    testOk(pch->final_type == valaddr.field_type,
           "final type unchanged (%d->%d)", valaddr.field_type, pch->final_type);
    testOk(pch->final_no_elements == valaddr.no_elements,
           "final no_elements unchanged (%ld->%ld)", valaddr.no_elements, pch->final_no_elements);

    /* TEST1 sets the record's OFF field, then requests 10 elements from the channel,
     * passing in a transparent db_field_log and converting the data to LONG on the way in.
     * It checks that it got back the expected data and the right number of elements.
     */

#define TEST1(Size, Offset, Text, Expected) \
    testDiag("Reading from offset = %d (%s)", Offset, Text); \
    off = Offset; req = 10; \
    memset(buf, 0, sizeof(buf)); \
    (void) dbPutField(&offaddr, DBR_LONG, &off, 1); \
    pfl = db_create_read_log(pch); \
    testOk(pfl && pfl->type == dbfl_type_rec, "Valid pfl, type = rec"); \
    testOk(!dbChannelGetField(pch, DBR_LONG, buf, NULL, &req, pfl), "Got Field value"); \
    testOk(req == Size, "Got %ld elements (expected %d)", req, Size); \
    if (!testOk(!memcmp(buf, Expected, sizeof(Expected)), "Data correct")) \
        for (i=0; i<Size; i++) \
            testDiag("Element %d expected %d got %d", i, Expected[i], buf[i]); \
    db_delete_field_log(pfl);

    const epicsInt32 res_10_0[] = {10,11,12,13,14,15,16,17,18,19};
    TEST1(10, 0, "no offset", res_10_0);

    const epicsInt32 res_10_4[] = {14,15,16,17,18,19,10,11,12,13};
    TEST1(10, 4, "wrapped", res_10_4);

    /* Partial array */

    testHead("Five %s elements", typname);
    off = 0;    /* Reset offset for writing the next buffer */
    (void) dbPutField(&offaddr, DBR_LONG, &off, 1);
    (void) dbPutField(&valaddr, DBR_LONG, &ar[5], 5);

    createAndOpen(valname, &pch);
    testOk(pch->final_type == valaddr.field_type,
           "final type unchanged (%d->%d)", valaddr.field_type, pch->final_type);
    testOk(pch->final_no_elements == valaddr.no_elements,
           "final no_elements unchanged (%ld->%ld)", valaddr.no_elements, pch->final_no_elements);

    const epicsInt32 res_5_0[] = {15,16,17,18,19};
    TEST1(5, 0, "no offset", res_5_0);

    const epicsInt32 res_5_3[] = {18,19,15,16,17};
    TEST1(5, 3, "wrapped", res_5_3);

    /* TEST2 sets the record's OFF field, then requests 15 elements from the channel
     * but passes in a db_field_log with alternate data, converting that data to LONG.
     * It checks that it got back the expected data and the right number of elements.
     */

#define TEST2(Size, Offset, Text, Expected) \
    testDiag("Reading from offset = %d (%s)", Offset, Text); \
    off = Offset; req = 15; \
    memset(buf, 0, sizeof(buf)); \
    (void) dbPutField(&offaddr, DBR_LONG, &off, 1); \
    pfl = db_create_read_log(pch); \
    pfl->type = dbfl_type_ref; \
    pfl->field_type = DBF_CHAR; \
    pfl->field_size = 1; \
    pfl->no_elements = 26; \
    pfl->u.r.dtor = freeArray; \
    pfl->u.r.field = epicsStrDup("abcdefghijklmnopqrsstuvwxyz"); \
    testOk(!dbChannelGetField(pch, DBR_LONG, buf, NULL, &req, pfl), "Got Field value"); \
    testOk(req == Size, "Got %ld elements (expected %d)", req, Size); \
    if (!testOk(!memcmp(buf, Expected, sizeof(Expected)), "Data correct")) \
        for (i=0; i<Size; i++) \
            testDiag("Element %d expected '%c' got '%c'", i, Expected[i], buf[i]); \
    db_delete_field_log(pfl);

    testHead("Fifteen letters from field-log instead of %s", typname);

    const epicsInt32 res_15[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
        'm', 'n', 'o'};
    TEST2(15, 0, "no offset", res_15);
    TEST2(15, 10, "ignored", res_15);

    dbChannelDelete(pch);
}
Esempio n. 23
0
static long init_record(acalcoutRecord *pcalc, int pass)
{
	DBLINK *plink;
	int i;
	double *pvalue;
	unsigned short *plinkValid;
	short error_number;
    acalcoutDSET *pacalcoutDSET;

	dbAddr       Addr;
	dbAddr       *pAddr = &Addr;
	rpvtStruct   *prpvt;

	if (pass==0) {
		pcalc->vers = VERSION;
		pcalc->rpvt = (void *)calloc(1, sizeof(struct rpvtStruct));
		if ((pcalc->nuse < 0) || (pcalc->nuse > pcalc->nelm)) {
			pcalc->nuse = pcalc->nelm;
			db_post_events(pcalc,&pcalc->nuse,DBE_VALUE|DBE_LOG);
		}
		return(0);
	}

	if (!(pacalcoutDSET = (acalcoutDSET *)pcalc->dset)) {
		recGblRecordError(S_dev_noDSET,(void *)pcalc,"acalcout:init_record");
		return(S_dev_noDSET);
	}
	/* must have write defined */
	if ((pacalcoutDSET->number < 5) || (pacalcoutDSET->write == NULL)) {
		recGblRecordError(S_dev_missingSup,(void *)pcalc,"acalcout:init_record");
		return(S_dev_missingSup);
	}

	prpvt = (rpvtStruct *)pcalc->rpvt;
	plink = &pcalc->inpa;
	pvalue = &pcalc->a;
	plinkValid = &pcalc->inav;
	for (i=0; i<(MAX_FIELDS+ARRAY_MAX_FIELDS+1); i++, plink++, pvalue++, plinkValid++) {
		if (plink->type == CONSTANT) {
			/* Don't InitConstantLink the array links or the output link. */
			if (i < MAX_FIELDS) { 
				recGblInitConstantLink(plink,DBF_DOUBLE,pvalue);
				db_post_events(pcalc,pvalue,DBE_VALUE);
			}
			*plinkValid = acalcoutINAV_CON;
			if (plink == &pcalc->out)
				prpvt->outlink_field_type = DBF_NOACCESS;
		} else if (!dbNameToAddr(plink->value.pv_link.pvname, pAddr)) {
			/* the PV we're linked to resides on this ioc */
			*plinkValid = acalcoutINAV_LOC;
			if (plink == &pcalc->out) {
				prpvt->outlink_field_type = pAddr->field_type;
				if ((pAddr->field_type >= DBF_INLINK) && (pAddr->field_type <= DBF_FWDLINK)) {
					if (!(plink->value.pv_link.pvlMask & pvlOptCA)) {
						printf("aCalcoutRecord(%s):init_record:non-CA link to link field\n",
							plink->value.pv_link.pvname);
					}
				}
				if (pcalc->wait && !(plink->value.pv_link.pvlMask & pvlOptCA)) {
					printf("aCalcoutRecord(%s):init_record: Can't wait with non-CA link attribute\n",
						plink->value.pv_link.pvname);
				}
			}
		} else {
			/* pv is not on this ioc. Callback later for connection stat */
			*plinkValid = acalcoutINAV_EXT_NC;
			prpvt->caLinkStat = CA_LINKS_NOT_OK;
			if (plink == &pcalc->out)
				prpvt->outlink_field_type = DBF_NOACCESS; /* don't know field type */
		}
		db_post_events(pcalc,plinkValid,DBE_VALUE);
	}

	pcalc->clcv = aCalcPostfix(pcalc->calc,pcalc->rpcl,&error_number);
	if (pcalc->clcv) {
		recGblRecordError(S_db_badField,(void *)pcalc,
			"acalcout: init_record: Illegal CALC field");
		if (aCalcoutRecordDebug >= 10)
			printf("acalcPostfix returns: %d\n", error_number);
	}
	db_post_events(pcalc,&pcalc->clcv,DBE_VALUE);

	pcalc->oclv = aCalcPostfix(pcalc->ocal, pcalc->orpc,&error_number);
	if (pcalc->oclv) {
		recGblRecordError(S_db_badField,(void *)pcalc,
			"acalcout: init_record: Illegal OCAL field");
		if (aCalcoutRecordDebug >= 10)
			printf("acalcPostfix returns: %d\n", error_number);
	}
	db_post_events(pcalc,&pcalc->oclv,DBE_VALUE);

	callbackSetCallback(checkLinksCallback, &prpvt->checkLinkCb);
	callbackSetPriority(0, &prpvt->checkLinkCb);
	callbackSetUser(pcalc, &prpvt->checkLinkCb);
	prpvt->wd_id_1_LOCK = 0;

	if (prpvt->caLinkStat == CA_LINKS_NOT_OK) {
		callbackRequestDelayed(&prpvt->checkLinkCb,1.0);
		prpvt->wd_id_1_LOCK = 1;
	}

	if (pacalcoutDSET->init_record ) {
		return (*pacalcoutDSET->init_record)(pcalc);
	}
	return(0);
}
Esempio n. 24
0
static long special(DBADDR *paddr, int after)
{
    calcoutRecord *prec = (calcoutRecord *)paddr->precord;
    rpvtStruct  *prpvt = prec->rpvt;
    DBADDR      dbaddr;
    DBADDR      *pAddr = &dbaddr;
    short       error_number;
    int         fieldIndex = dbGetFieldIndex(paddr);
    int         lnkIndex;
    DBLINK      *plink;
    double      *pvalue;
    epicsEnum16 *plinkValid;

    if (!after) return 0;
    switch(fieldIndex) {
      case(calcoutRecordCALC):
        prec->clcv = postfix(prec->calc, prec->rpcl, &error_number);
        if (prec->clcv){
            recGblRecordError(S_db_badField, (void *)prec,
                      "calcout: special(): Illegal CALC field");
            errlogPrintf("%s.CALC: %s in expression \"%s\"\n",
                         prec->name, calcErrorStr(error_number), prec->calc);
        }
        db_post_events(prec, &prec->clcv, DBE_VALUE);
        return 0;

      case(calcoutRecordOCAL):
        prec->oclv = postfix(prec->ocal, prec->orpc, &error_number);
        if (prec->dopt == calcoutDOPT_Use_OVAL && prec->oclv){
            recGblRecordError(S_db_badField, (void *)prec,
                    "calcout: special(): Illegal OCAL field");
            errlogPrintf("%s.OCAL: %s in expression \"%s\"\n",
                         prec->name, calcErrorStr(error_number), prec->ocal);
        }
        db_post_events(prec, &prec->oclv, DBE_VALUE);
        return 0;
      case(calcoutRecordINPA):
      case(calcoutRecordINPB):
      case(calcoutRecordINPC):
      case(calcoutRecordINPD):
      case(calcoutRecordINPE):
      case(calcoutRecordINPF):
      case(calcoutRecordINPG):
      case(calcoutRecordINPH):
      case(calcoutRecordINPI):
      case(calcoutRecordINPJ):
      case(calcoutRecordINPK):
      case(calcoutRecordINPL):
      case(calcoutRecordOUT):
        lnkIndex = fieldIndex - calcoutRecordINPA;
        plink   = &prec->inpa + lnkIndex;
        pvalue  = &prec->a    + lnkIndex;
        plinkValid = &prec->inav + lnkIndex;
        if (plink->type == CONSTANT) {
            if (fieldIndex != calcoutRecordOUT) {
                recGblInitConstantLink(plink, DBF_DOUBLE, pvalue);
                db_post_events(prec, pvalue, DBE_VALUE);
            }
            *plinkValid = calcoutINAV_CON;
        } else if (!dbNameToAddr(plink->value.pv_link.pvname, pAddr)) {
            /* if the PV resides on this ioc */
            *plinkValid = calcoutINAV_LOC;
        } else {
            /* pv is not on this ioc. Callback later for connection stat */
            *plinkValid = calcoutINAV_EXT_NC;
            /* DO_CALLBACK, if not already scheduled */
            if (!prpvt->cbScheduled) {
                callbackRequestDelayed(&prpvt->checkLinkCb, .5);
                prpvt->cbScheduled = 1;
                prpvt->caLinkStat = CA_LINKS_NOT_OK;
            }
        }
        db_post_events(prec, plinkValid, DBE_VALUE);
        return 0;
      case(calcoutRecordOEVT):
        prec->epvt = eventNameToHandle(prec->oevt);
        return 0;
      default:
        recGblDbaddrError(S_db_badChoice, paddr, "calc: special");
        return(S_db_badChoice);
    }
}
Esempio n. 25
0
static long init_record(calcoutRecord *prec, int pass)
{
    DBLINK *plink;
    int i;
    double *pvalue;
    epicsEnum16 *plinkValid;
    short error_number;
    calcoutDSET *pcalcoutDSET;

    DBADDR     dbaddr;
    DBADDR     *pAddr = &dbaddr;
    rpvtStruct *prpvt;

    if (pass == 0) {
        prec->rpvt = (rpvtStruct *) callocMustSucceed(1, sizeof(rpvtStruct), "calcoutRecord");
        return 0;
    }
    if (!(pcalcoutDSET = (calcoutDSET *)prec->dset)) {
        recGblRecordError(S_dev_noDSET, (void *)prec, "calcout:init_record");
        return S_dev_noDSET;
    }
    /* must have write defined */
    if ((pcalcoutDSET->number < 5) || (pcalcoutDSET->write ==NULL)) {
        recGblRecordError(S_dev_missingSup, (void *)prec, "calcout:init_record");
        return S_dev_missingSup;
    }
    prpvt = prec->rpvt;
    plink = &prec->inpa;
    pvalue = &prec->a;
    plinkValid = &prec->inav;
    for (i = 0; i <= CALCPERFORM_NARGS; i++, plink++, pvalue++, plinkValid++) {
        if (plink->type == CONSTANT) {
            /* Don't InitConstantLink the .OUT link */
            if (i < CALCPERFORM_NARGS) {
                recGblInitConstantLink(plink, DBF_DOUBLE, pvalue);
            }
            *plinkValid = calcoutINAV_CON;
        } else if (!dbNameToAddr(plink->value.pv_link.pvname, pAddr)) {
            /* PV resides on this ioc */
            *plinkValid = calcoutINAV_LOC;
        } else {
            /* pv is not on this ioc. Callback later for connection stat */
            *plinkValid = calcoutINAV_EXT_NC;
             prpvt->caLinkStat = CA_LINKS_NOT_OK;
        }
    }

    prec->clcv = postfix(prec->calc, prec->rpcl, &error_number);
    if (prec->clcv){
        recGblRecordError(S_db_badField, (void *)prec,
                          "calcout: init_record: Illegal CALC field");
        errlogPrintf("%s.CALC: %s in expression \"%s\"\n",
                     prec->name, calcErrorStr(error_number), prec->calc);
    }

    prec->oclv = postfix(prec->ocal, prec->orpc, &error_number);
    if (prec->dopt == calcoutDOPT_Use_OVAL && prec->oclv){
        recGblRecordError(S_db_badField, (void *)prec,
                          "calcout: init_record: Illegal OCAL field");
        errlogPrintf("%s.OCAL: %s in expression \"%s\"\n",
                     prec->name, calcErrorStr(error_number), prec->ocal);
    }

    prpvt = prec->rpvt;
    callbackSetCallback(checkLinksCallback, &prpvt->checkLinkCb);
    callbackSetPriority(0, &prpvt->checkLinkCb);
    callbackSetUser(prec, &prpvt->checkLinkCb);
    prpvt->cbScheduled = 0;

    prec->epvt = eventNameToHandle(prec->oevt);
    
    if (pcalcoutDSET->init_record) pcalcoutDSET->init_record(prec);
    prec->pval = prec->val;
    prec->mlst = prec->val;
    prec->alst = prec->val;
    prec->lalm = prec->val;
    prec->povl = prec->oval;
    return 0;
}
Esempio n. 26
0
/*
 *  Remove breakpoint from a record
 *     1. Convert name to address and check breakpoint mask.
 *     2. Lock database and take stack semaphore.
 *     3. Find structure for record's lockset (in stack).
 *     4. Find and delete record from breakpoint list.
 *     5. Turn off break point field.
 *     6. Give up semaphore to "signal" bkptCont task to quit.
 */
long epicsShareAPI dbd(const char *record_name)
{
  struct dbAddr addr;
  struct LS_LIST *pnode;
  struct BP_LIST *pbl;
  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;

  if (! precord->bkpt & BKPT_ON_MASK) {
      printf("   BKPT> No breakpoint set in this record\n");
      return(S_db_bkptNotSet);
  }

  dbScanLock(precord);

  epicsMutexMustLock(bkpt_stack_sem);

  FIND_LOCKSET(precord, pnode);

  if (pnode == NULL) {
     /* not found, error ! */
     printf("   BKPT> Logic Error in dbd()\n");
     precord->bkpt &= BKPT_OFF_MASK;

     epicsMutexUnlock(bkpt_stack_sem);
     dbScanUnlock(precord);
     return(S_db_bkptLogic);
  }

 /*
  *  Remove record from breakpoint list
  */

 /* find record in list */
  pbl = (struct BP_LIST *) ellFirst(&pnode->bp_list);
  while (pbl != NULL) {
     if (pbl->precord == precord) {
         ellDelete(&pnode->bp_list, (ELLNODE *)pbl);
         free(pbl);
         break;
     }
     pbl = (struct BP_LIST *) ellNext((ELLNODE *)pbl);
  }

  if (pbl == NULL) {
     printf("   BKPT> Logic Error in dbd()\n"); 
     precord->bkpt &= BKPT_OFF_MASK;
     epicsMutexUnlock(bkpt_stack_sem);
     dbScanUnlock(precord);
     return(S_db_bkptLogic);
  }

 /*
  *  Turn off breakpoint field in record
  */
  precord->bkpt &= BKPT_OFF_MASK;

 /*
  *  If there are no more breakpoints, give up semaphore
  *    to cause the bkptCont task to quit.
  */
  if (ellCount(&pnode->bp_list) == 0)
     epicsEventSignal(pnode->ex_sem);

  epicsMutexUnlock(bkpt_stack_sem);

  dbScanUnlock(precord);
  return(0);
}
Esempio n. 27
0
static long dbPutFieldLink(DBADDR *paddr,
    short dbrType, const void *pbuffer, long nRequest)
{
    dbCommon    *precord = paddr->precord;
    dbFldDes    *pfldDes = paddr->pfldDes;
    long        special = paddr->special;
    DBLINK      *plink = (DBLINK *)paddr->pfield;
    const char  *pstring = (const char *)pbuffer;
    DBENTRY     dbEntry;
    DBADDR      dbaddr;
    struct dsxt *old_dsxt = NULL;
    struct dset *new_dset = NULL;
    struct dsxt *new_dsxt = NULL;
    long        status;
    int         isDevLink;
    short       scan;

    switch (dbrType) {
    case DBR_CHAR:
    case DBR_UCHAR:
        if (pstring[nRequest - 1] != '\0')
            return S_db_badDbrtype;
        break;

    case DBR_STRING:
        break;

    default:
        return S_db_badDbrtype;
    }

    dbInitEntry(pdbbase, &dbEntry);
    status = dbFindRecord(&dbEntry, precord->name);
    if (!status) status = dbFindField(&dbEntry, pfldDes->name);
    if (status) goto finish;

    isDevLink = ellCount(&precord->rdes->devList) > 0 &&
                (strcmp(pfldDes->name, "INP") == 0 ||
                 strcmp(pfldDes->name, "OUT") == 0);

    dbLockSetGblLock();
    dbLockSetRecordLock(precord);

    scan = precord->scan;

    if (isDevLink) {
        devSup *pdevSup = dbDTYPtoDevSup(precord->rdes, precord->dtyp);
        if (pdevSup) {
            new_dset = pdevSup->pdset;
            new_dsxt = pdevSup->pdsxt;
        }

        if (precord->dset) {
            pdevSup = dbDSETtoDevSup(precord->rdes, precord->dset);
            if (pdevSup)
                old_dsxt = pdevSup->pdsxt;
        }

        if (new_dsxt == NULL ||
            new_dsxt->add_record == NULL ||
            (precord->dset && old_dsxt == NULL) ||
            (old_dsxt && old_dsxt->del_record == NULL)) {
            status = S_db_noSupport;
            goto unlock;
        }

        if (scan == menuScanI_O_Intr) {
            scanDelete(precord);
            precord->scan = menuScanPassive;
        }

        if (old_dsxt) {
            status = old_dsxt->del_record(precord);
            if (status)
                goto restoreScan;
        }
    }

    switch (plink->type) { /* Old link type */
    case DB_LINK:
        free(plink->value.pv_link.pvt);
        plink->value.pv_link.pvt = 0;
        plink->type = PV_LINK;
        plink->value.pv_link.getCvt = 0;
        plink->value.pv_link.pvlMask = 0;
        plink->value.pv_link.lastGetdbrType = 0;
        dbLockSetSplit(precord);
        break;

    case CA_LINK:
        dbCaRemoveLink(plink);
        plink->type = PV_LINK;
        plink->value.pv_link.getCvt = 0;
        plink->value.pv_link.pvlMask = 0;
        plink->value.pv_link.lastGetdbrType = 0;
        break;

    case CONSTANT:
        break;  /* do nothing */

    case PV_LINK:
    case MACRO_LINK:
        break;  /* should never get here */

    default: /* Hardware address */
        if (!isDevLink) {
            status = S_db_badHWaddr;
            goto restoreScan;
        }
        break;
    }

    if (special) status = dbPutSpecial(paddr, 0);

    if (!status) status = dbPutString(&dbEntry, pstring);

    if (!status && special) status = dbPutSpecial(paddr, 1);

    if (status) {
        if (isDevLink) {
            precord->dset = NULL;
            precord->pact = TRUE;
        }
        goto postScanEvent;
    }

    if (isDevLink) {
        precord->dpvt = NULL;
        precord->dset = new_dset;
        precord->pact = FALSE;

        status = new_dsxt->add_record(precord);
        if (status) {
            precord->dset = NULL;
            precord->pact = TRUE;
            goto postScanEvent;
        }
    }

    switch (plink->type) { /* New link type */
    case PV_LINK:
        if (plink == &precord->tsel)
            recGblTSELwasModified(plink);
        plink->value.pv_link.precord = precord;

        if (!(plink->value.pv_link.pvlMask & (pvlOptCA|pvlOptCP|pvlOptCPP)) &&
            (dbNameToAddr(plink->value.pv_link.pvname, &dbaddr) == 0)) {
            /* It's a DB link */
            DBADDR      *pdbAddr;

            plink->type = DB_LINK;
            pdbAddr = dbMalloc(sizeof(struct dbAddr));
            *pdbAddr = dbaddr; /* NB: structure copy */;
            plink->value.pv_link.pvt = pdbAddr;
            dbLockSetRecordLock(pdbAddr->precord);
            dbLockSetMerge(precord, pdbAddr->precord);
        } else { /* Make it a CA link */
            char        *pperiod;

            plink->type = CA_LINK;
            if (pfldDes->field_type == DBF_INLINK) {
                plink->value.pv_link.pvlMask |= pvlOptInpNative;
            }
            dbCaAddLink(plink);
            if (pfldDes->field_type == DBF_FWDLINK) {
                pperiod = strrchr(plink->value.pv_link.pvname, '.');
                if (pperiod && strstr(pperiod, "PROC"))
                    plink->value.pv_link.pvlMask |= pvlOptFWD;
            }
        }
        break;

    case CONSTANT:
        break;

    case DB_LINK:
    case CA_LINK:
    case MACRO_LINK:
        break;  /* should never get here */

    default: /* Hardware address */
        if (!isDevLink) {
            status = S_db_badHWaddr;
            goto postScanEvent;
        }
        break;
    }
    db_post_events(precord, plink, DBE_VALUE | DBE_LOG);

restoreScan:
    if (isDevLink &&
        scan == menuScanI_O_Intr) { /* undo scanDelete() */
        precord->scan = scan;
        scanAdd(precord);
    }
postScanEvent:
    if (scan != precord->scan)
        db_post_events(precord, &precord->scan, DBE_VALUE|DBE_LOG);
unlock:
    dbLockSetGblUnlock();
finish:
    dbFinishEntry(&dbEntry);
    return status;
}
Esempio n. 28
0
void mdsPlusPut_Task(int param)
{
    unsigned long i;
    int socket;
    int null=0;
    int dtypeFloat = DTYPE_FLOAT;
    int dataDesc,timeDesc;
    int status=1, j;

    float          tdT;
    float          toffT;

    int            tnoRd;
    int            tshotID;
    char            ttagName[20];
    char            ttreeID[20];
    char            tserverID[20];
    float           *timeBase;

    DBADDR          *paddr;
    paddr = (DBADDR *)dbCalloc(1, sizeof(struct dbAddr));

    if(genSubDebug > 0)
        printf("Start MdsPut. ##############.\n");
    status = dbNameToAddr(mpActivePV, paddr);
    enum16Val = 1;
    status = dbPutField(paddr, DBR_ENUM, &enum16Val, 1);
    status = mdsPlusCreatePulse();
    /* loop numNode times */
    for(j = 0;j < numNode; j++) {
        if(genSubDebug > 5)
            printf("genSub: mdsPlusPut_Task() started. Task Position=%d, Flag=%ld\n",j,pmdsPutData[j].putFlag);
        if(pmdsPutData[j].putFlag == 0)
            goto endloop;

        epicsThreadSleep(0.01);

        tnoRd=(int)(pmdsPutData[j].noRd);
        tshotID=(int)(pmdsPutData[j].shotID);
        strcpy(ttagName,pmdsPutData[j].tagName);
        strcpy(ttreeID,pmdsPutData[j].treeID);
        strcpy(tserverID,pmdsPutData[j].serverID);

        tdT=pmdsPutData[j].dT;
        toffT=pmdsPutData[j].offT;

        if(genSubDebug > 3)
            printf("genSub: mdsPlusPut_Task() MdsConnect Ready. ServerID=[%s] TreeID=[%s] tagName=[%s] dt=[%f] off=[%f] noRd=[%d]\n",tserverID, ttreeID, ttagName, tdT, toffT, tnoRd);

        /* Connect server and open tree*/
        socket=MdsConnect(tserverID);
        if(socket == -1) {
            printf("genSub: Error connecting to mdsip server[%s].\n",tserverID);
            break;
        }
        if(genSubDebug > 5)
             printf("genSub: mdsPlusPut_Task() MdsConnected[%s]\n",tserverID);

        status=MdsOpen(ttreeID, &tshotID);
        if( !status_ok(status) ) {
             printf("genSub: Error opening tree [%s] for shot [%d].\n",
                            ttreeID,tshotID );
             break;
        }                
        if(genSubDebug > 5)
             printf("genSub: mdsPlusPut_Task() MdsOpened [%s] shot number [%d].\n",
                       ttreeID,tshotID);

        /* put data */
        timeBase = (float *)malloc(tnoRd*sizeof(float));
        for(i=0;i<tnoRd;i++)
            *(timeBase + i) = ((float)i)*tdT + toffT;

        dataDesc=descr(&dtypeFloat,pmdsPutData[j].dataArray,&tnoRd, &null);
        timeDesc=descr(&dtypeFloat,timeBase, &tnoRd, &null);
        status=MdsPut(ttagName,"BUILD_SIGNAL($1,,$2)",&dataDesc,&timeDesc,&null);
        if( !status_ok(status) ) {
            printf("genSub: Error writing signal.\n");
            break;
        }

        if(genSubDebug > 5)
            printf("genSub: mdsPlusPut_Task() MdsPutted to tag [%s]. shot number [%d], noRd=[%d].\n",
                                ttagName,tshotID,tnoRd);
        if(genSubDebug > 10)
            for(i=0;i<tnoRd;i++) {
                    printf("timeBase=%f,data=%f\n",
                                        *((float *)timeBase+i),*((float *)pmdsPutData[j].dataArray+i));
            }
        free(timeBase);
        status=MdsClose(ttreeID, &tshotID);
        if( !status_ok(status) ) {
            printf("genSub: Error closing tree for shot [%d].\n",tshotID );
            break;
        }
        if(genSubDebug > 5)
            printf("genSub: mdsPlusPut_Task() MdsClosed [%s] shot number [%d]\n",ttreeID,tshotID);

        endloop:
        if(genSubDebug > 5)
            printf("genSub: mdsPlusPut_Task() Data discarded for taskPos[%d].\n",j);
    }
    status = mdsPlusPrepNext();
    /* end of mdsput */
    startMdsPut = 0;
    status = dbNameToAddr(mpActivePV, paddr);
    enum16Val = 0;
    status = dbPutField(paddr, DBR_ENUM, &enum16Val, 1);
    free(paddr);
}
Esempio n. 29
0
static long special(dbAddr	*paddr, int after)
{
	acalcoutRecord	*pcalc = (acalcoutRecord *)(paddr->precord);
	rpvtStruct		*prpvt = (struct rpvtStruct *)pcalc->rpvt;
	dbAddr			Addr;
	dbAddr			*pAddr = &Addr;
	short			error_number;
	int				fieldIndex = dbGetFieldIndex(paddr);
	int				lnkIndex;
	DBLINK			*plink;
	double			*pvalue;
	unsigned short	*plinkValid;

	if (!after) return(0);
	switch (fieldIndex) {
	case acalcoutRecordCALC:
		pcalc->clcv = aCalcPostfix(pcalc->calc, pcalc->rpcl, &error_number);
		if (pcalc->clcv) {
			recGblRecordError(S_db_badField,(void *)pcalc,
				"acalcout: special(): Illegal CALC field");
			if (aCalcoutRecordDebug >= 10)
				printf("acalcPostfix returns: %d\n", error_number);
		}
		db_post_events(pcalc,&pcalc->clcv,DBE_VALUE);
		return(0);
		break;

	case acalcoutRecordOCAL:
		pcalc->oclv = aCalcPostfix(pcalc->ocal, pcalc->orpc, &error_number);
		if (pcalc->oclv) {
			recGblRecordError(S_db_badField,(void *)pcalc,
				"acalcout: special(): Illegal OCAL field");
			if (aCalcoutRecordDebug >= 10)
				printf("acalcPostfix returns: %d\n", error_number);
		}
		db_post_events(pcalc,&pcalc->oclv,DBE_VALUE);
		return(0);
		break;

	case acalcoutRecordNUSE:
		if ((pcalc->nuse < 0) || (pcalc->nuse > pcalc->nelm)) {
			pcalc->nuse = pcalc->nelm;
			db_post_events(pcalc,&pcalc->nuse,DBE_VALUE);
			return(-1);
		}
		return(0);
		break;

	case(acalcoutRecordINPA):
	case(acalcoutRecordINPB):
	case(acalcoutRecordINPC):
	case(acalcoutRecordINPD):
	case(acalcoutRecordINPE):
	case(acalcoutRecordINPF):
	case(acalcoutRecordINPG):
	case(acalcoutRecordINPH):
	case(acalcoutRecordINPI):
	case(acalcoutRecordINPJ):
	case(acalcoutRecordINPK):
	case(acalcoutRecordINPL):
	case(acalcoutRecordINAA):
	case(acalcoutRecordINBB):
	case(acalcoutRecordINCC):
	case(acalcoutRecordINDD):
	case(acalcoutRecordINEE):
	case(acalcoutRecordINFF):
	case(acalcoutRecordINGG):
	case(acalcoutRecordINHH):
	case(acalcoutRecordINII):
	case(acalcoutRecordINJJ):
	case(acalcoutRecordINKK):
	case(acalcoutRecordINLL):
	case(acalcoutRecordOUT):
		lnkIndex = fieldIndex - acalcoutRecordINPA;
		plink   = &pcalc->inpa + lnkIndex;
		pvalue  = &pcalc->a    + lnkIndex;
		plinkValid = &pcalc->inav + lnkIndex;

		if (plink->type == CONSTANT) {
			if (fieldIndex <= acalcoutRecordINPL) {
				recGblInitConstantLink(plink,DBF_DOUBLE,pvalue);
				db_post_events(pcalc,pvalue,DBE_VALUE);
			}
			*plinkValid = acalcoutINAV_CON;
			if (fieldIndex == acalcoutRecordOUT)
				prpvt->outlink_field_type = DBF_NOACCESS;
		} else if (!dbNameToAddr(plink->value.pv_link.pvname, pAddr)) {
			/* PV resides on this ioc */
			*plinkValid = acalcoutINAV_LOC;
			if (fieldIndex == acalcoutRecordOUT) {
				prpvt->outlink_field_type = pAddr->field_type;
				if ((pAddr->field_type >= DBF_INLINK) && (pAddr->field_type <= DBF_FWDLINK)) {
					if (!(plink->value.pv_link.pvlMask & pvlOptCA)) {
						printf("aCalcoutRecord(%s):special:non-CA link to link field\n",
							plink->value.pv_link.pvname);
					}
				}
				if (pcalc->wait && !(plink->value.pv_link.pvlMask & pvlOptCA)) {
					printf("aCalcoutRecord(%s):special: Can't wait with non-CA link attribute\n",
						plink->value.pv_link.pvname);
				}
			}
		} else {
			/* pv is not on this ioc. Callback later for connection stat */
			*plinkValid = acalcoutINAV_EXT_NC;
			/* DO_CALLBACK, if not already scheduled */
			if (!prpvt->wd_id_1_LOCK) {
				callbackRequestDelayed(&prpvt->checkLinkCb,.5);
				prpvt->wd_id_1_LOCK = 1;
				prpvt->caLinkStat = CA_LINKS_NOT_OK;
			}
			if (fieldIndex == acalcoutRecordOUT)
				prpvt->outlink_field_type = DBF_NOACCESS; /* don't know */
		}
        db_post_events(pcalc,plinkValid,DBE_VALUE);
		return(0);
		break;

	default:
		recGblDbaddrError(S_db_badChoice,paddr,"calc: special");
		return(S_db_badChoice);
	}
	return(0);
}
Esempio n. 30
0
/*
 *  Add breakpoint to a lock set
 *     1. Convert name to address and check breakpoint mask.
 *     2. Lock database.
 *     3. If empty, initialize lock set stack and its semaphore.
 *     4. Take that semaphore.
 *     5. Find lockset in the list.  If it doesn't exist, create it.
 *     6. Turn on breakpoint field in record.
 *     7. Add breakpoint to list of breakpoints in structure.
 *     8. Spawn continuation task if it isn't already running.
 */
long epicsShareAPI dbb(const char *record_name)
{
  struct dbAddr addr;
  struct LS_LIST *pnode;
  struct BP_LIST *pbl;
  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;

  if (precord->bkpt & BKPT_ON_MASK) {
     printf("   BKPT> Breakpoint already set in this record\n"); 
     return(S_db_bkptSet);
  }

  dbScanLock(precord);

 /*
  *  Add lock set to the stack of lock sets that
  *    contain breakpoints and/or stopped records.
  */

  epicsMutexMustLock(bkpt_stack_sem);

  FIND_LOCKSET(precord, pnode);

  if (pnode == NULL) {
    /* lockset not found, create node, add to end of list */
     pnode = (struct LS_LIST *) malloc(sizeof(struct LS_LIST));
     if (pnode == NULL) {
        printf("   BKPT> Out of memory\n");
        dbScanUnlock(precord);
        epicsMutexUnlock(bkpt_stack_sem);
        return(1);
     }
     pnode->precord = NULL;

    /* initialize breakpoint list */
     ellInit(&pnode->bp_list);

    /* initialize entry point queue */
     ellInit(&pnode->ep_queue);

    /* create execution semaphore */
     pnode->ex_sem = epicsEventCreate(epicsEventEmpty);
     if (pnode->ex_sem == NULL) {
        printf("   BKPT> Out of memory\n");
        dbScanUnlock(precord);
        epicsMutexUnlock(bkpt_stack_sem);
        return(1);
     }

     pnode->taskid   = 0;
     pnode->step     = 0;
     pnode->l_num    = dbLockGetLockId(precord);

     ellAdd(&lset_stack, (ELLNODE *)pnode);
     ++lset_stack_count;
  }

 /*
  *  Add record to breakpoint list
  */
  pbl = (struct BP_LIST *) malloc(sizeof(struct BP_LIST));
  if (pbl == NULL) {
     printf("  BKPT> Out of memory\n");
     dbScanUnlock(precord);
     epicsMutexUnlock(bkpt_stack_sem);
     return(1);
  }
  pbl->precord = precord; 
  ellAdd(&pnode->bp_list, (ELLNODE *)pbl);

 /*
  *  Turn on breakpoint field in record
  */
  precord->bkpt |= BKPT_ON_MASK; 

  if (! pnode->taskid) {

#ifdef BKPT_DIAG
     printf("   BKPT> Spawning task: %s\n", precord->name);
#endif
    /*
     *  Spawn continuation task
     */
     pnode->taskid = epicsThreadCreate("bkptCont",epicsThreadPriorityScanLow-1,
         epicsThreadGetStackSize(epicsThreadStackBig),
         (EPICSTHREADFUNC)dbBkptCont,precord);
     if (pnode->taskid == 0) {
        printf("   BKPT> Cannot spawn task to process record\n");
        pnode->taskid = 0;
        dbScanUnlock(precord);
        epicsMutexUnlock(bkpt_stack_sem);
        return(1);
     }
  }

  epicsMutexUnlock(bkpt_stack_sem);
  dbScanUnlock(precord);
  return(0);
}