LOCAL int queueRecord (const char *precName) { DBENTRY dbentry; DBENTRY *pdbentry=&dbentry; dbCommon *pdbc; msg_t msg; dbInitEntry (pdbbase, pdbentry); if (dbFindRecord (pdbentry, precName) != 0) { dbFinishEntry (pdbentry); return ERROR; } pdbc = dbentry.precnode->precord; dbFinishEntry (pdbentry); DEBUG2(4,"queueRecord: Name: %s ptr: 0x%x\n",precName,(unsigned)pdbc) msg.pdbc = pdbc; msg.osevr = pdbc->sevr; msg.ostat = pdbc->stat; msg.nsevr = pdbc->sevr; msg.nstat = pdbc->stat; tsLocalTime (&msg.stamp); msg.msgType = mt_Status; ringInsert (&msg); return OK; }
long epicsShareAPI dbla(const char *pmask) { DBENTRY dbentry; DBENTRY *pdbentry = &dbentry; long status; if (!pdbbase) { printf("No database loaded\n"); return 0; } dbInitEntry(pdbbase, pdbentry); status = dbFirstRecordType(pdbentry); while (!status) { for (status = dbFirstRecord(pdbentry); !status; status = dbNextRecord(pdbentry)) { char *palias; if (!dbIsAlias(pdbentry)) continue; palias = dbGetRecordName(pdbentry); if (pmask && *pmask && !epicsStrGlobMatch(palias, pmask)) continue; dbFindField(pdbentry, "NAME"); printf("%s -> %s\n", palias, dbGetString(pdbentry)); } status = dbNextRecordType(pdbentry); } dbFinishEntry(pdbentry); return 0; }
long epicsShareAPI dbgrep(const char *pmask) { DBENTRY dbentry; DBENTRY *pdbentry = &dbentry; long status; if (!pmask || !*pmask) { printf("Usage: dbgrep \"pattern\"\n"); return 1; } if (!pdbbase) { printf("No database loaded\n"); return 0; } dbInitEntry(pdbbase, pdbentry); status = dbFirstRecordType(pdbentry); while (!status) { status = dbFirstRecord(pdbentry); while (!status) { char *pname = dbGetRecordName(pdbentry); if (epicsStrGlobMatch(pname, pmask)) puts(pname); status = dbNextRecord(pdbentry); } status = dbNextRecordType(pdbentry); } dbFinishEntry(pdbentry); return 0; }
ChannelFind::shared_pointer DbPvProvider::channelList( ChannelListRequester::shared_pointer const & channelListRequester) { PVStringArray::svector channelNames; DBENTRY dbentry; DBENTRY *pdbentry=&dbentry; if (pdbbase) { dbInitEntry(pdbbase, pdbentry); long status = dbFirstRecordType(pdbentry); if (!status) { while (!status) { status = dbFirstRecord(pdbentry); while (!status) { channelNames.push_back(dbGetRecordName(pdbentry)); status = dbNextRecord(pdbentry); } status = dbNextRecordType(pdbentry); } } dbFinishEntry(pdbentry); } ChannelFind::shared_pointer nullChannelFind; channelListRequester->channelListResult(Status::Ok, nullChannelFind, freeze(channelNames), false); return nullChannelFind; }
static long asDbAddRecords(void) { DBENTRY dbentry; DBENTRY *pdbentry=&dbentry; long status; dbCommon *precord; dbInitEntry(pdbbase,pdbentry); status = dbFirstRecordType(pdbentry); while(!status) { status = dbFirstRecord(pdbentry); while(!status) { precord = pdbentry->precnode->precord; if(!precord->asp) { status = asAddMember(&precord->asp, precord->asg); if(status) errMessage(status,"asDbAddRecords:asAddMember"); asPutMemberPvt(precord->asp,precord); } status = dbNextRecord(pdbentry); } status = dbNextRecordType(pdbentry); } dbFinishEntry(pdbentry); return(0); }
LOCAL void queueAllRecords () { DBENTRY dbentry; DBENTRY *pdbentry=&dbentry; dbCommon *pdbc; long status; dbInitEntry(pdbbase,pdbentry); status = dbFirstRecordType(pdbentry); while(!status) { status = dbFirstRecord(pdbentry); while(!status) { msg_t msg; pdbc = pdbentry->precnode->precord; DEBUG2(4,"queueAllRecords:Name: %s ptr: 0x%x\n", dbGetRecordName(pdbentry),(unsigned)pdbc) msg.pdbc = pdbc; msg.osevr = pdbc->sevr; msg.ostat = pdbc->stat; msg.nsevr = pdbc->sevr; msg.nstat = pdbc->stat; tsLocalTime (&msg.stamp); msg.msgType = mt_Status; ringInsert (&msg); status = dbNextRecord(pdbentry); } status = dbNextRecordType(pdbentry); } dbFinishEntry(pdbentry); }
long epicsShareAPI dbGetField(DBADDR *paddr,short dbrType, void *pbuffer, long *options, long *nRequest, void *pflin) { short dbfType = paddr->field_type; dbCommon *precord = paddr->precord; long status = 0; dbScanLock(precord); if (dbfType >= DBF_INLINK && dbfType <= DBF_FWDLINK) { DBENTRY dbEntry; dbFldDes *pfldDes = paddr->pfldDes; char *rtnString; char *pbuf = (char *)pbuffer; int maxlen; if (options && (*options)) getOptions(paddr, &pbuf, options, pflin); if (nRequest && *nRequest == 0) goto done; switch (dbrType) { case DBR_STRING: maxlen = MAX_STRING_SIZE - 1; if (nRequest && *nRequest > 1) *nRequest = 1; break; case DBR_CHAR: case DBR_UCHAR: if (nRequest && *nRequest > 0) { maxlen = *nRequest - 1; break; } /* else fall through ... */ default: status = S_db_badDbrtype; goto done; } dbInitEntry(pdbbase, &dbEntry); status = dbFindRecord(&dbEntry, precord->name); if (!status) status = dbFindField(&dbEntry, pfldDes->name); if (!status) { rtnString = dbGetString(&dbEntry); strncpy(pbuf, rtnString, maxlen); pbuf[maxlen] = 0; } dbFinishEntry(&dbEntry); } else { status = dbGet(paddr, dbrType, pbuffer, options, nRequest, pflin); } done: dbScanUnlock(precord); return status; }
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); }
long dbChannelTest(const char *name) { DBENTRY dbEntry; long status; if (!name || !*name || !pdbbase) return S_db_notFound; status = pvNameLookup(&dbEntry, &name); dbFinishEntry(&dbEntry); return status; }
/*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); }
long dbPutAttribute( const char *recordTypename,const char *name,const char*value) { DBENTRY dbEntry; DBENTRY *pdbEntry = &dbEntry; long status=0; if(!pdbbase) return(S_db_notFound); dbInitEntry(pdbbase,pdbEntry); status = dbFindRecordType(pdbEntry,recordTypename); if(!status) status = dbPutRecordAttribute(pdbEntry,name,value); dbFinishEntry(pdbEntry); if(status) errMessage(status,"dbPutAttribute failure"); return(status); }
static int countCvtRecords(void) { DBENTRY dbentry; extern DBBASE *pdbbase; int result = 0; long status; dbInitEntry(pdbbase, &dbentry); status = dbFindRecordType(&dbentry,"cvt"); if (!status) { result = dbGetNRecords(&dbentry); } dbFinishEntry(&dbentry); return result; }
static long ai_init(int pass) { long i; if (pass) return 0; /* Create timers */ for (i = 0; i < TOTAL_TYPES; i++) { scanIoInit(&scan[i].ioscan); scan[i].wd = wdogCreate(scan_time, i); scan[i].total = 0; scan[i].on = 0; scan[i].rate_sec = parmTypes[i].scan_rate; } /* Init OSD stuff */ scan_mutex = epicsMutexMustCreate(); devIocStatsInitCpuUsage(); devIocStatsInitCpuUtilization(&loadinfo); devIocStatsInitFDUsage(); devIocStatsInitMemUsage(); devIocStatsInitWorkspaceUsage(); devIocStatsInitSuspTasks(); devIocStatsInitIFErrors(); /* Get initial values of a few things that don't change much */ devIocStatsGetClusterInfo(SYS_POOL, &clustinfo[SYS_POOL]); devIocStatsGetClusterInfo(DATA_POOL, &clustinfo[DATA_POOL]); devIocStatsGetClusterUsage(SYS_POOL, &mbufnumber[SYS_POOL]); devIocStatsGetClusterUsage(DATA_POOL, &mbufnumber[DATA_POOL]); devIocStatsGetCpuUtilization(&loadinfo); devIocStatsGetIFErrors(&iferrors); devIocStatsGetFDUsage(&fdusage); /* Count EPICS records */ if (pdbbase) { DBENTRY dbentry; long status; dbInitEntry(pdbbase,&dbentry); status = dbFirstRecordType(&dbentry); while (!status) { recordnumber += dbGetNRecords(&dbentry); status = dbNextRecordType(&dbentry); } dbFinishEntry(&dbentry); } return 0; }
static void dbAlias(char *name, char *alias) { DBENTRY dbEntry; DBENTRY *pdbEntry = &dbEntry; dbInitEntry(pdbbase, pdbEntry); if (dbFindRecord(pdbEntry, name)) { epicsPrintf("Alias \"%s\" refers to unknown record \"%s\"\n", alias, name); yyerror(NULL); } else if (dbCreateAlias(pdbEntry, alias)) { epicsPrintf("Can't create alias \"%s\" referring to \"%s\"\n", alias, name); yyerror(NULL); } dbFinishEntry(pdbEntry); }
void dbcaStats(int *pchans, int *pdiscon) { DBENTRY dbentry; DBENTRY *pdbentry = &dbentry; long status; DBLINK *plink; long ncalinks = 0; long nconnected = 0; dbInitEntry(pdbbase,pdbentry); status = dbFirstRecordType(pdbentry); while (!status) { dbRecordType *pdbRecordType = pdbentry->precordType; status = dbFirstRecord(pdbentry); while (!status) { dbCommon *precord = (dbCommon *)pdbentry->precnode->precord; int j; if (!dbIsAlias(pdbentry)) { for (j=0; j<pdbRecordType->no_links; j++) { int i = pdbRecordType->link_ind[j]; dbFldDes *pdbFldDes = pdbRecordType->papFldDes[i]; plink = (DBLINK *)((char *)precord + pdbFldDes->offset); if (plink->type == CA_LINK) { caLink *pca = (caLink *)plink->value.pv_link.pvt; ncalinks++; if (pca && ca_state(pca->chid) == cs_conn) { nconnected++; } } } } status = dbNextRecord(pdbentry); } status = dbNextRecordType(pdbentry); } dbFinishEntry(pdbentry); if (pchans) *pchans = ncalinks; if (pdiscon) *pdiscon = ncalinks - nconnected; }
static long getLinkValue(DBADDR *paddr, short dbrType, char *pbuf, long *nRequest) { dbCommon *precord = paddr->precord; dbFldDes *pfldDes = paddr->pfldDes; int maxlen; DBENTRY dbEntry; long status; switch (dbrType) { case DBR_STRING: maxlen = MAX_STRING_SIZE - 1; if (nRequest && *nRequest > 1) *nRequest = 1; break; case DBR_DOUBLE: /* Needed for dbCa links */ if (nRequest && *nRequest) *nRequest = 1; *(double *)pbuf = epicsNAN; return 0; case DBR_CHAR: case DBR_UCHAR: if (nRequest && *nRequest > 0) { maxlen = *nRequest - 1; break; } /* else fall through ... */ default: return S_db_badDbrtype; } dbInitEntry(pdbbase, &dbEntry); status = dbFindRecord(&dbEntry, precord->name); if (!status) status = dbFindField(&dbEntry, pfldDes->name); if (!status) { char *rtnString = dbGetString(&dbEntry); strncpy(pbuf, rtnString, --maxlen); pbuf[maxlen] = 0; } dbFinishEntry(&dbEntry); return status; }
static long ai_init(int pass) { long i; if (pass) return 0; /* Create timers */ for (i = 0; i < TOTAL_TYPES; i++) { scanIoInit(&scan[i].ioscan); scan[i].wd = wdogCreate(scan_time, i); scan[i].total = 0; scan[i].on = 0; scan[i].rate_sec = scan_rate_sec[i]; scan[i].last_read_sec = 1000000; } /* Init OSD stuff */ devIocStatsInitCpuUsage(); devIocStatsInitCpuUtilization(&loadinfo); devIocStatsInitFDUsage(); devIocStatsInitMemUsage(); devIocStatsInitWorkspaceUsage(); devIocStatsInitSuspTasks(); devIocStatsInitIFErrors(); /* Count EPICS records */ if (pdbbase) { DBENTRY dbentry; long status; dbInitEntry(pdbbase,&dbentry); status = dbFirstRecordType(&dbentry); while (!status) { recordnumber += dbGetNRecords(&dbentry); status = dbNextRecordType(&dbentry); } dbFinishEntry(&dbentry); } return 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); }
long epicsShareAPI dbnr(int verbose) { DBENTRY dbentry; DBENTRY *pdbentry=&dbentry; long status; int nrecords; int naliases; int trecords = 0; int taliases = 0; if (!pdbbase) { printf("No database loaded\n"); return 0; } dbInitEntry(pdbbase, pdbentry); status = dbFirstRecordType(pdbentry); if (status) { printf("No record types loaded\n"); return 0; } printf("Records Aliases Record Type\n"); while (!status) { naliases = dbGetNAliases(pdbentry); taliases += naliases; nrecords = dbGetNRecords(pdbentry) - naliases; trecords += nrecords; if (verbose || nrecords) printf(" %5d %5d %s\n", nrecords, naliases, dbGetRecordTypeName(pdbentry)); status = dbNextRecordType(pdbentry); } dbFinishEntry(pdbentry); printf("Total %d records, %d aliases\n", trecords, taliases); return 0; }
int epicsShareAPI logAlarmsInit ( ) { DBENTRY dbentry; DBENTRY *pdbentry=&dbentry; long status; int numRecords=0; int tid[MSG_TASK_NUM], btid, ctid, rtid; int normalRangeSize, overRangeSize; struct sockaddr_in *psin; int node; char string[32]; char *pstring, *serverList, *ptok, *pheader; int i; if (initialized) { errlogPrintf ("logAlarmsInit: already initialized\n"); return ERROR; } clkRate = sysClkRateGet(); tickInitWait = (unsigned long)(clkRate * INIT_DELAY_SEC + 0.5); tickMaxSilent = (unsigned long)(clkRate * BEACON_IDLE_SEC + 0.5); tickBeaconPeriod = (unsigned long)(clkRate * BEACON_PERIOD_SEC + 0.5); tickBeaconReplyTmo = (unsigned long)(clkRate * BEACON_REPLY_TMO_SEC + 0.5); tickMessageReplyTmo = (unsigned long)(clkRate * MESSAGE_REPLY_TMO_SEC + 0.5); /* wait time between retrying to send messages (>= 1 tick) */ tickMsgRetryWait = (unsigned long)(clkRate * MESSAGE_RETRY_WAIT_SEC + 0.5); if (tickMsgRetryWait == 0UL) tickMsgRetryWait = 1UL; if(!pdbbase) { errlogPrintf ("logAlarmsInit: No database has been loaded\n"); return ERROR; } serverList = getenv ("EPICS_ALARM_SERVER_INET"); if (!serverList) { errlogPrintf ("logAlarmsInit: EPICS_ALARM_SERVER_INET env not defined\n"); return ERROR; } pstring = getenv ("EPICS_ALARM_MESSAGE_PORT"); if (!pstring) msg_port = DEFAULT_MSG_PORT; else { msg_port = (unsigned short) atoi (pstring); if (msg_port < 1024) { msg_port = DEFAULT_MSG_PORT; errlogPrintf ("Port number EPICS_ALARM_MESSAGE_PORT is wrong\n"); } } pstring = getenv ("EPICS_ALARM_COMMAND_PORT"); if (!pstring) cmd_port = DEFAULT_CMD_PORT; else { cmd_port = (unsigned short) atoi (pstring); if (cmd_port < 1024) { cmd_port = DEFAULT_CMD_PORT; errlogPrintf ("Port number EPICS_ALARM_COMMAND_PORT is wrong\n"); } } /* if allAcceptOption is set, commands are accepted from all servers */ pstring = getenv ("EPICS_ALARM_COMMAND_ACCEPT_ALL"); if (strcmp (pstring, "YES") == 0) allAcceptOption = TRUE; psin = &msgServerAddr[0]; node = 0; ptok = strtok_r (serverList, " ", &pstring); while (ptok && node < SERVERS_MAX && aToIPAddr (ptok, msg_port, psin) == 0) { node++; psin++; ptok = strtok_r (NULL, " ", &pstring); } numServersConfigured = node; if (numServersConfigured == 0) { errlogPrintf ( "logAlarmsInit: No server correctly defined in EPICS_ALARM_SERVER_INET\n"); } wakeupSem = semBCreate (SEM_Q_FIFO, SEM_EMPTY); if (!wakeupSem) { errlogPrintf ("logAlarmsInit: Reader wakeup semaphore could not be created\n"); return ERROR; } bucketSem = semMCreate (SEM_Q_PRIORITY | SEM_DELETE_SAFE | SEM_INVERSION_SAFE); if (!bucketSem) { errlogPrintf ("logAlarmsInit: Hash facility mutex could not be created\n"); cleanup (1); return ERROR; } ringSem = semMCreate (SEM_Q_PRIORITY | SEM_DELETE_SAFE | SEM_INVERSION_SAFE); if (!ringSem) { errlogPrintf ("logAlarmsInit: Ring r/w mutex could not be created\n"); cleanup (2); return ERROR; } ringWriteSem = semMCreate (SEM_Q_PRIORITY | SEM_DELETE_SAFE | SEM_INVERSION_SAFE); if (!ringWriteSem) { errlogPrintf ("logAlarmsInit: Ring (write) mutex could not be created\n"); cleanup (3); return ERROR; } msgSockSem = semMCreate (SEM_Q_PRIORITY | SEM_DELETE_SAFE | SEM_INVERSION_SAFE); if (!msgSockSem) { errlogPrintf ("logAlarmsInit: MsgSocket mutex could not be created\n"); cleanup (4); return ERROR; } dbInitEntry(pdbbase,pdbentry); status = dbFirstRecordType(pdbentry); while(!status) { int numRecordsType; numRecordsType = dbGetNRecords(pdbentry); DEBUG2(4,"There are %d records of type %s\n", numRecordsType, dbGetRecordTypeName(pdbentry)) numRecords += numRecordsType; status = dbNextRecordType(pdbentry); } dbFinishEntry(pdbentry); normalRangeSize = (int)(numRecords * RING_NORMAL_MULTI) + 1; overRangeSize = numRecords + numRecords / RING_OVER_DIVI + 1; ringSize = normalRangeSize + overRangeSize; pRingBottom = (msgBuffer_t *)calloc (ringSize, sizeof(msgBuffer_t)); if (!pRingBottom) { errlogPrintf ("logAlarmsInit: Ring buffer could not be created\n"); cleanup (5); return ERROR; } pRingTop = pRingBottom + ringSize; DEBUG2(2,"pRingBottom:%lu pRingTop:%lu\n", (unsigned long)pRingBottom, (unsigned long)pRingTop) ringHighWater = normalRangeSize; DEBUG2(2,"Ring buffer size:%d highwater:%d\n",ringSize,ringHighWater) pRingRead = pRingBottom; pRingWrite = pRingBottom; msgLost = 0; pbuck = bucketCreate (numRecords); if (!pbuck) { errlogPrintf ("logAlarmsInit: Hash table could not be initalized\n"); cleanup (6); return ERROR; } serverSelected = -1; serverSelectedLast = -1; queueAllRecords(); /* spawn alarm beacon task */ btid = taskSpawn ("Al'Beacon", BEACON_TASK_PRIO, BEACON_TASK_OPTIONS, BEACON_TASK_STACK, (FUNCPTR)alarmBeaconTask,0,0,0,0,0,0,0,0,0,0); if (!btid) { errlogPrintf ("logAlarmsInit: Beacon task could not be spawned\n"); cleanup (7); return ERROR; } DEBUG1(1,"alarmBeaconTask started. Task-ID = 0x%x\n", btid); msg_soc = socket (AF_INET, SOCK_DGRAM, 0); if (msg_soc < 0) { errlogPrintf ("Message socket create failed\n"); cleanup (7); return ERROR; } bzero ((char *) &msgReplyInAddr, sockAddrSize); msgReplyInAddr.sin_port = htons(msg_port); msgReplyInAddr.sin_family = AF_INET; msgReplyInAddr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind (msg_soc, (struct sockaddr*)&msgReplyInAddr, sockAddrSize) < 0 ) { errlogPrintf ("Message socket bind failed\n"); cleanup (8); return ERROR; } cmd_soc = socket (AF_INET, SOCK_DGRAM, 0); if (cmd_soc < 0) { errlogPrintf ("Command socket create failed\n"); cleanup (8); return ERROR; } bzero ((char *) &cmdServerAddr, sockAddrSize); cmdServerAddr.sin_port = htons(cmd_port); cmdServerAddr.sin_family = AF_INET; cmdServerAddr.sin_addr.s_addr = htonl(INADDR_ANY); if (bind (cmd_soc, (struct sockaddr*)&cmdServerAddr, sockAddrSize) < 0 ) { errlogPrintf ("Command socket bind failed\n"); cleanup (9); return ERROR; } /* spawn alarm message tasks */ for (i=0; i<MSG_TASK_NUM; i++) { sprintf (string, "Al'Msg%d", i+1); tid[i] = taskSpawn (string, CLIENT_TASK_PRIO, CLIENT_TASK_OPTIONS, CLIENT_TASK_STACK, (FUNCPTR)alarmMessageTask,i+1,0,0,0,0,0,0,0,0,0); if (!tid[i]) { errlogPrintf ( "logAlarmsInit: Message task %d could not be spawned\n"); cleanup (9); while (i > 0) taskDelete (tid[--i]); taskDelete (btid); return ERROR; } } /* spawn alarm log control (command receiver) server task */ ctid = taskSpawn ("Al'Command", CONTROL_TASK_PRIO, CONTROL_TASK_OPTIONS, CONTROL_TASK_STACK, (FUNCPTR)alarmCommandTask,0,0,0,0,0,0,0,0,0,0); if (!ctid) { errlogPrintf ("logAlarmsInit: Control task could not be spawned\n"); cleanup (9); taskDelete (btid); for (i=0; i<MSG_TASK_NUM; i++) taskDelete (tid[i]); return ERROR; } /* spawn message reply receiver task */ rtid = taskSpawn ("Al'ReplyRx", REPLY_TASK_PRIO, REPLY_TASK_OPTIONS, REPLY_TASK_STACK, (FUNCPTR)replyReceiveTask,0,0,0,0,0,0,0,0,0,0); if (!rtid) { errlogPrintf ("logAlarmsInit: Reply receiver task could not be spawned\n"); cleanup (9); taskDelete (btid); taskDelete (ctid); for (i=0; i<MSG_TASK_NUM; i++) taskDelete (tid[i]); return ERROR; } pheader = messageHeader; pstring = getenv ("EPICS_IOC_NAME"); if (pstring) /* given IOC name */ pheader = messageHeader + sprintf (messageHeader, "HOST=%s;", pstring); pheader += sprintf (pheader, "HOST-PHYS=%s;APPLICATION=logAlarms;", gethostname (string, sizeof(string)) ? "TOO_LONG" : string); pstring = getenv ("EPICS_FACILITY"); if (pstring) /* name of application facility */ pheader += sprintf (pheader, "FACILITY=%s;", pstring); /* calculate the remaining space in the message string */ textMsgSize = MAX_MESSAGE_LENGTH - (pheader-messageHeader); epicsPrintf("logAlarms started\n"); recGblAlarmHook = (RECGBL_ALARM_HOOK_ROUTINE)logEvent; DEBUG1(3,"recGblAlarmHook = 0x%lx\n",(unsigned long)recGblAlarmHook) initialized = TRUE; return OK; }
long dbcar(char *precordname, int level) { DBENTRY dbentry; DBENTRY *pdbentry=&dbentry; long status; dbCommon *precord; dbRecordType *pdbRecordType; dbFldDes *pdbFldDes; DBLINK *plink; int ncalinks=0; int nconnected=0; int noReadAccess=0; int noWriteAccess=0; unsigned long nDisconnect=0; unsigned long nNoWrite=0; caLink *pca; int j; if (!precordname || precordname[0] == '\0' || !strcmp(precordname, "*")) { precordname = NULL; printf("CA links in all records\n\n"); } else { printf("CA links in record named '%s'\n\n", precordname); } dbInitEntry(pdbbase,pdbentry); status = dbFirstRecordType(pdbentry); while (!status) { status = dbFirstRecord(pdbentry); while (!status) { if (precordname ? !strcmp(precordname, dbGetRecordName(pdbentry)) : !dbIsAlias(pdbentry)) { pdbRecordType = pdbentry->precordType; precord = (dbCommon *)pdbentry->precnode->precord; for (j=0; j<pdbRecordType->no_links; j++) { pdbFldDes = pdbRecordType->papFldDes[pdbRecordType->link_ind[j]]; plink = (DBLINK *)((char *)precord + pdbFldDes->offset); dbLockSetGblLock(); if (plink->type == CA_LINK) { ncalinks++; pca = (caLink *)plink->value.pv_link.pvt; if (pca && pca->chid && (ca_field_type(pca->chid) != TYPENOTCONN)) { nconnected++; nDisconnect += pca->nDisconnect; nNoWrite += pca->nNoWrite; if (!ca_read_access(pca->chid)) noReadAccess++; if (!ca_write_access(pca->chid)) noWriteAccess++; if (level>1) { int rw = ca_read_access(pca->chid) | ca_write_access(pca->chid) << 1; static const char *rights[4] = { "No Access", "Read Only", "Write Only", "Read/Write" }; int mask = plink->value.pv_link.pvlMask; printf("%28s.%-4s ==> %-28s (%lu, %lu)\n", precord->name, pdbFldDes->name, plink->value.pv_link.pvname, pca->nDisconnect, pca->nNoWrite); printf("%21s [%s%s%s%s] host %s, %s\n", "", mask & pvlOptInpNative ? "IN" : " ", mask & pvlOptInpString ? "IS" : " ", mask & pvlOptOutNative ? "ON" : " ", mask & pvlOptOutString ? "OS" : " ", ca_host_name(pca->chid), rights[rw]); } } else { if (level>0) { printf("%28s.%-4s --> %-28s (%lu, %lu)\n", precord->name, pdbFldDes->name, plink->value.pv_link.pvname, pca->nDisconnect, pca->nNoWrite); } } } dbLockSetGblUnlock(); } if (precordname) goto done; } status = dbNextRecord(pdbentry); } status = dbNextRecordType(pdbentry); } done: if ((level > 1 && nconnected > 0) || (level > 0 && ncalinks != nconnected)) printf("\n"); printf("Total %d CA link%s; ", ncalinks, (ncalinks != 1) ? "s" : ""); printf("%d connected, %d not connected.\n", nconnected, (ncalinks - nconnected)); printf(" %d can't read, %d can't write.", noReadAccess, noWriteAccess); printf(" (%lu disconnects, %lu writes prohibited)\n\n", nDisconnect, nNoWrite); dbFinishEntry(pdbentry); if ( level > 2 && dbCaClientContext != 0 ) { ca_context_status ( dbCaClientContext, level - 2 ); } return(0); }
static void hookPass0(initHookState state) { DBENTRY entry; if(state!=initHookAfterInitDevSup) return; testDiag("initHookAfterInitDevSup"); dbInitEntry(pdbbase, &entry); testDiag("restore integer pass0"); /* rec0.VAL is initially 1, set it to 2 */ if(dbFindRecord(&entry, "rec0.VAL")==0) { aoRecord *prec = entry.precnode->precord; testOk(prec->val==1, "VAL %d==1 (initial value from .db)", (int)prec->val); checkGetString(&entry, "1"); testOk1(dbPutString(&entry, "2")==0); testOk(prec->val==2, "VAL %d==2", (int)prec->val); checkGetString(&entry, "2"); } else { testFail("Missing rec0"); testSkip(4, "missing record"); } testDiag("restore string pass0"); if(dbFindRecord(&entry, "rec0.DESC")==0) { aoRecord *prec = entry.precnode->precord; testOk1(strcmp(prec->desc, "foobar")==0); checkGetString(&entry, "foobar"); testOk1(dbPutString(&entry, "hello")==0); testOk1(strcmp(prec->desc, "hello")==0); checkGetString(&entry, "hello"); } else { testFail("Missing rec0"); testSkip(4, "missing record"); } if(dbFindRecord(&entry, "rec1.DESC")==0) { aoRecord *prec = entry.precnode->precord; testOk1(strcmp(prec->desc, "")==0); checkGetString(&entry, ""); testOk1(dbPutString(&entry, "world")==0); testOk1(strcmp(prec->desc, "world")==0); checkGetString(&entry, "world"); } else { testFail("Missing rec1"); testSkip(4, "missing record"); } testDiag("restore link pass0"); /* rec0.OUT is initially "rec0.DISV", set it to "rec0.SEVR" */ if(dbFindRecord(&entry, "rec0.OUT")==0) { aoRecord *prec = entry.precnode->precord; if(prec->out.type==CONSTANT) testOk(strcmp(prec->out.text,"rec0.DISV")==0, "%s==rec0.DISV (initial value from .db)", prec->out.text); else testFail("Wrong link type: %d", (int)prec->out.type); /* note that dbGetString() reads an empty string before links are initialized * should probably be considered a bug, but has been the case for so long * we call it a 'feature'. */ checkGetString(&entry, ""); testOk1(dbPutString(&entry, "rec0.SEVR")==0); } else{ testFail("Missing rec0"); testSkip(1, "missing record"); } /* rec0.SDIS is initially NULL, set it to "rec0.STAT" */ if(dbFindRecord(&entry, "rec0.SDIS")==0) { aoRecord *prec = entry.precnode->precord; if(prec->sdis.type==CONSTANT) testOk1(prec->sdis.value.constantStr==NULL); else testFail("Wrong link type: %d", (int)prec->sdis.type); testOk1(dbPutString(&entry, "rec0.STAT")==0); } else{ testFail("Missing rec0"); testSkip(1, "missing record"); } /* can't restore array field in pass0 */ dbFinishEntry(&entry); }
/* Performs the work of the public db_get_field API, but also returns the number * of elements actually copied to the buffer. The caller is responsible for * zeroing the remaining part of the buffer. */ int dbChannel_get_count( struct dbChannel *chan, int buffer_type, void *pbuffer, long *nRequest, void *pfl) { long status; long options; long i; long zero = 0; /* The order of the DBR* elements in the "newSt" structures below is * very important and must correspond to the order of processing * in the dbAccess.c dbGet() and getOptions() routines. */ dbScanLock(dbChannelRecord(chan)); switch(buffer_type) { case(oldDBR_STRING): status = dbChannelGet(chan, DBR_STRING, pbuffer, &zero, nRequest, pfl); break; /* case(oldDBR_INT): */ case(oldDBR_SHORT): status = dbChannelGet(chan, DBR_SHORT, pbuffer, &zero, nRequest, pfl); break; case(oldDBR_FLOAT): status = dbChannelGet(chan, DBR_FLOAT, pbuffer, &zero, nRequest, pfl); break; case(oldDBR_ENUM): status = dbChannelGet(chan, DBR_ENUM, pbuffer, &zero, nRequest, pfl); break; case(oldDBR_CHAR): status = dbChannelGet(chan, DBR_CHAR, pbuffer, &zero, nRequest, pfl); break; case(oldDBR_LONG): status = dbChannelGet(chan, DBR_LONG, pbuffer, &zero, nRequest, pfl); break; case(oldDBR_DOUBLE): status = dbChannelGet(chan, DBR_DOUBLE, pbuffer, &zero, nRequest, pfl); break; case(oldDBR_STS_STRING): case(oldDBR_GR_STRING): case(oldDBR_CTRL_STRING): { struct dbr_sts_string *pold = (struct dbr_sts_string *)pbuffer; struct { DBRstatus } newSt; options = DBR_STATUS; status = dbChannelGet(chan, DBR_STRING, &newSt, &options, &zero, pfl); pold->status = newSt.status; pold->severity = newSt.severity; status = dbChannelGet(chan, DBR_STRING, pold->value, &zero, nRequest, pfl); } break; /* case(oldDBR_STS_INT): */ case(oldDBR_STS_SHORT): { struct dbr_sts_int *pold = (struct dbr_sts_int *)pbuffer; struct { DBRstatus } newSt; options = DBR_STATUS; status = dbChannelGet(chan, DBR_SHORT, &newSt, &options, &zero, pfl); pold->status = newSt.status; pold->severity = newSt.severity; status = dbChannelGet(chan, DBR_SHORT, &pold->value, &zero, nRequest, pfl); } break; case(oldDBR_STS_FLOAT): { struct dbr_sts_float *pold = (struct dbr_sts_float *)pbuffer; struct { DBRstatus } newSt; options = DBR_STATUS; status = dbChannelGet(chan, DBR_FLOAT, &newSt, &options, &zero, pfl); pold->status = newSt.status; pold->severity = newSt.severity; status = dbChannelGet(chan, DBR_FLOAT, &pold->value, &zero, nRequest, pfl); } break; case(oldDBR_STS_ENUM): { struct dbr_sts_enum *pold = (struct dbr_sts_enum *)pbuffer; struct { DBRstatus } newSt; options = DBR_STATUS; status = dbChannelGet(chan, DBR_ENUM, &newSt, &options, &zero, pfl); pold->status = newSt.status; pold->severity = newSt.severity; status = dbChannelGet(chan, DBR_ENUM, &pold->value, &zero, nRequest, pfl); } break; case(oldDBR_STS_CHAR): { struct dbr_sts_char *pold = (struct dbr_sts_char *)pbuffer; struct { DBRstatus } newSt; options = DBR_STATUS; status = dbChannelGet(chan, DBR_UCHAR, &newSt, &options, &zero, pfl); pold->status = newSt.status; pold->severity = newSt.severity; status = dbChannelGet(chan, DBR_UCHAR, &pold->value, &zero, nRequest, pfl); } break; case(oldDBR_STS_LONG): { struct dbr_sts_long *pold = (struct dbr_sts_long *)pbuffer; struct { DBRstatus } newSt; options = DBR_STATUS; status = dbChannelGet(chan, DBR_LONG, &newSt, &options, &zero, pfl); pold->status = newSt.status; pold->severity = newSt.severity; status = dbChannelGet(chan, DBR_LONG, &pold->value, &zero, nRequest, pfl); } break; case(oldDBR_STS_DOUBLE): { struct dbr_sts_double *pold = (struct dbr_sts_double *)pbuffer; struct { DBRstatus } newSt; options = DBR_STATUS; status = dbChannelGet(chan, DBR_DOUBLE, &newSt, &options, &zero, pfl); pold->status = newSt.status; pold->severity = newSt.severity; options = 0; status = dbChannelGet(chan, DBR_DOUBLE, &pold->value, &options, nRequest, pfl); } break; case(oldDBR_TIME_STRING): { struct dbr_time_string *pold = (struct dbr_time_string *)pbuffer; struct { DBRstatus DBRtime } newSt; options = DBR_STATUS | DBR_TIME; status = dbChannelGet(chan, DBR_STRING, &newSt, &options, &zero, pfl); pold->status = newSt.status; pold->severity = newSt.severity; pold->stamp = newSt.time; /* structure copy */ options = 0; status = dbChannelGet(chan, DBR_STRING, pold->value, &options, nRequest, pfl); } break; /* case(oldDBR_TIME_INT): */ case(oldDBR_TIME_SHORT): { struct dbr_time_short *pold = (struct dbr_time_short *)pbuffer; struct { DBRstatus DBRtime } newSt; options = DBR_STATUS | DBR_TIME; status = dbChannelGet(chan, DBR_SHORT, &newSt, &options, &zero, pfl); pold->status = newSt.status; pold->severity = newSt.severity; pold->stamp = newSt.time; /* structure copy */ options = 0; status = dbChannelGet(chan, DBR_SHORT, &pold->value, &options, nRequest, pfl); } break; case(oldDBR_TIME_FLOAT): { struct dbr_time_float *pold = (struct dbr_time_float *)pbuffer; struct { DBRstatus DBRtime } newSt; options = DBR_STATUS | DBR_TIME; status = dbChannelGet(chan, DBR_FLOAT, &newSt, &options, &zero, pfl); pold->status = newSt.status; pold->severity = newSt.severity; pold->stamp = newSt.time; /* structure copy */ options = 0; status = dbChannelGet(chan, DBR_FLOAT, &pold->value, &options, nRequest, pfl); } break; case(oldDBR_TIME_ENUM): { struct dbr_time_enum *pold = (struct dbr_time_enum *)pbuffer; struct { DBRstatus DBRtime } newSt; options = DBR_STATUS | DBR_TIME; status = dbChannelGet(chan, DBR_ENUM, &newSt, &options, &zero, pfl); pold->status = newSt.status; pold->severity = newSt.severity; pold->stamp = newSt.time; /* structure copy */ options = 0; status = dbChannelGet(chan, DBR_ENUM, &pold->value, &options, nRequest, pfl); } break; case(oldDBR_TIME_CHAR): { struct dbr_time_char *pold = (struct dbr_time_char *)pbuffer; struct { DBRstatus DBRtime } newSt; options = DBR_STATUS | DBR_TIME; status = dbChannelGet(chan, DBR_CHAR, &newSt, &options, &zero, pfl); pold->status = newSt.status; pold->severity = newSt.severity; pold->stamp = newSt.time; /* structure copy */ options = 0; status = dbChannelGet(chan, DBR_CHAR, &pold->value, &options, nRequest, pfl); } break; case(oldDBR_TIME_LONG): { struct dbr_time_long *pold = (struct dbr_time_long *)pbuffer; struct { DBRstatus DBRtime } newSt; options = DBR_STATUS | DBR_TIME; status = dbChannelGet(chan, DBR_LONG, &newSt, &options, &zero, pfl); pold->status = newSt.status; pold->severity = newSt.severity; pold->stamp = newSt.time; /* structure copy */ options = 0; status = dbChannelGet(chan, DBR_LONG, &pold->value, &options, nRequest, pfl); } break; case(oldDBR_TIME_DOUBLE): { struct dbr_time_double *pold = (struct dbr_time_double *)pbuffer; struct { DBRstatus DBRtime } newSt; options = DBR_STATUS | DBR_TIME; status = dbChannelGet(chan, DBR_DOUBLE, &newSt, &options, &zero, pfl); pold->status = newSt.status; pold->severity = newSt.severity; pold->stamp = newSt.time; /* structure copy */ options = 0; status = dbChannelGet(chan, DBR_DOUBLE, &pold->value, &options, nRequest, pfl); } break; /* case(oldDBR_GR_STRING): NOT IMPLEMENTED - use DBR_STS_STRING */ /* case(oldDBR_GR_INT): */ case(oldDBR_GR_SHORT): { struct dbr_gr_int *pold = (struct dbr_gr_int *)pbuffer; struct { DBRstatus DBRunits DBRgrLong DBRalLong } newSt; options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_AL_LONG; status = dbChannelGet(chan, DBR_SHORT, &newSt, &options, &zero, pfl); pold->status = newSt.status; pold->severity = newSt.severity; strncpy(pold->units, newSt.units, MAX_UNITS_SIZE); pold->units[MAX_UNITS_SIZE-1] = '\0'; pold->upper_disp_limit = newSt.upper_disp_limit; pold->lower_disp_limit = newSt.lower_disp_limit; pold->upper_alarm_limit = newSt.upper_alarm_limit; pold->upper_warning_limit = newSt.upper_warning_limit; pold->lower_warning_limit = newSt.lower_warning_limit; pold->lower_alarm_limit = newSt.lower_alarm_limit; options = 0; status = dbChannelGet(chan, DBR_SHORT, &pold->value, &options, nRequest, pfl); } break; case(oldDBR_GR_FLOAT): { struct dbr_gr_float *pold = (struct dbr_gr_float *)pbuffer; struct { DBRstatus DBRunits DBRprecision DBRgrDouble DBRalDouble } newSt; options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE | DBR_AL_DOUBLE; status = dbChannelGet(chan, DBR_FLOAT, &newSt, &options, &zero, pfl); pold->status = newSt.status; pold->severity = newSt.severity; pold->precision = (dbr_short_t) newSt.precision.dp; strncpy(pold->units, newSt.units, MAX_UNITS_SIZE); pold->units[MAX_UNITS_SIZE-1] = '\0'; pold->upper_disp_limit = epicsConvertDoubleToFloat(newSt.upper_disp_limit); pold->lower_disp_limit = epicsConvertDoubleToFloat(newSt.lower_disp_limit); pold->upper_alarm_limit = epicsConvertDoubleToFloat(newSt.upper_alarm_limit); pold->lower_alarm_limit = epicsConvertDoubleToFloat(newSt.lower_alarm_limit); pold->upper_warning_limit = epicsConvertDoubleToFloat(newSt.upper_warning_limit); pold->lower_warning_limit = epicsConvertDoubleToFloat(newSt.lower_warning_limit); options = 0; status = dbChannelGet(chan, DBR_FLOAT, &pold->value, &options, nRequest, pfl); } break; /* case(oldDBR_GR_ENUM): see oldDBR_CTRL_ENUM */ case(oldDBR_GR_CHAR): { struct dbr_gr_char *pold = (struct dbr_gr_char *)pbuffer; struct { DBRstatus DBRunits DBRgrLong DBRalLong } newSt; options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_AL_LONG; status = dbChannelGet(chan, DBR_UCHAR, &newSt, &options, &zero, pfl); pold->status = newSt.status; pold->severity = newSt.severity; strncpy(pold->units, newSt.units, MAX_UNITS_SIZE); pold->units[MAX_UNITS_SIZE-1] = '\0'; pold->upper_disp_limit = newSt.upper_disp_limit; pold->lower_disp_limit = newSt.lower_disp_limit; pold->upper_alarm_limit = newSt.upper_alarm_limit; pold->upper_warning_limit = newSt.upper_warning_limit; pold->lower_warning_limit = newSt.lower_warning_limit; pold->lower_alarm_limit = newSt.lower_alarm_limit; options = 0; status = dbChannelGet(chan, DBR_UCHAR, &pold->value, &options, nRequest, pfl); } break; case(oldDBR_GR_LONG): { struct dbr_gr_long *pold = (struct dbr_gr_long *)pbuffer; struct { DBRstatus DBRunits DBRgrLong DBRalLong } newSt; options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_AL_LONG; status = dbChannelGet(chan, DBR_LONG, &newSt, &options, &zero, pfl); pold->status = newSt.status; pold->severity = newSt.severity; strncpy(pold->units, newSt.units, MAX_UNITS_SIZE); pold->units[MAX_UNITS_SIZE-1] = '\0'; pold->upper_disp_limit = newSt.upper_disp_limit; pold->lower_disp_limit = newSt.lower_disp_limit; pold->upper_alarm_limit = newSt.upper_alarm_limit; pold->upper_warning_limit = newSt.upper_warning_limit; pold->lower_warning_limit = newSt.lower_warning_limit; pold->lower_alarm_limit = newSt.lower_alarm_limit; options = 0; status = dbChannelGet(chan, DBR_LONG, &pold->value, &options, nRequest, pfl); } break; case(oldDBR_GR_DOUBLE): { struct dbr_gr_double *pold = (struct dbr_gr_double *)pbuffer; struct { DBRstatus DBRunits DBRprecision DBRgrDouble DBRalDouble } newSt; options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE | DBR_AL_DOUBLE; status = dbChannelGet(chan, DBR_DOUBLE, &newSt, &options, &zero, pfl); pold->status = newSt.status; pold->severity = newSt.severity; pold->precision = (dbr_short_t) newSt.precision.dp; strncpy(pold->units, newSt.units, MAX_UNITS_SIZE); pold->units[MAX_UNITS_SIZE-1] = '\0'; pold->upper_disp_limit = newSt.upper_disp_limit; pold->lower_disp_limit = newSt.lower_disp_limit; pold->upper_alarm_limit = newSt.upper_alarm_limit; pold->upper_warning_limit = newSt.upper_warning_limit; pold->lower_warning_limit = newSt.lower_warning_limit; pold->lower_alarm_limit = newSt.lower_alarm_limit; options = 0; status = dbChannelGet(chan, DBR_DOUBLE, &pold->value, &options, nRequest, pfl); } break; /* case(oldDBR_CTRL_INT): */ case(oldDBR_CTRL_SHORT): { struct dbr_ctrl_int *pold = (struct dbr_ctrl_int *)pbuffer; struct { DBRstatus DBRunits DBRgrLong DBRctrlLong DBRalLong } newSt; options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_CTRL_LONG | DBR_AL_LONG; status = dbChannelGet(chan, DBR_SHORT, &newSt, &options, &zero, pfl); pold->status = newSt.status; pold->severity = newSt.severity; strncpy(pold->units, newSt.units, MAX_UNITS_SIZE); pold->units[MAX_UNITS_SIZE-1] = '\0'; pold->upper_disp_limit = newSt.upper_disp_limit; pold->lower_disp_limit = newSt.lower_disp_limit; pold->upper_alarm_limit = newSt.upper_alarm_limit; pold->upper_warning_limit = newSt.upper_warning_limit; pold->lower_warning_limit = newSt.lower_warning_limit; pold->lower_alarm_limit = newSt.lower_alarm_limit; pold->upper_ctrl_limit = newSt.upper_ctrl_limit; pold->lower_ctrl_limit = newSt.lower_ctrl_limit; options = 0; status = dbChannelGet(chan, DBR_SHORT, &pold->value, &options, nRequest, pfl); } break; case(oldDBR_CTRL_FLOAT): { struct dbr_ctrl_float *pold = (struct dbr_ctrl_float *)pbuffer; struct { DBRstatus DBRunits DBRprecision DBRgrDouble DBRctrlDouble DBRalDouble } newSt; options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE | DBR_CTRL_DOUBLE | DBR_AL_DOUBLE; status = dbChannelGet(chan, DBR_FLOAT, &newSt, &options, &zero, pfl); pold->status = newSt.status; pold->severity = newSt.severity; pold->precision = (dbr_short_t) newSt.precision.dp; strncpy(pold->units, newSt.units, MAX_UNITS_SIZE); pold->units[MAX_UNITS_SIZE-1] = '\0'; pold->upper_disp_limit = epicsConvertDoubleToFloat(newSt.upper_disp_limit); pold->lower_disp_limit = epicsConvertDoubleToFloat(newSt.lower_disp_limit); pold->upper_alarm_limit = epicsConvertDoubleToFloat(newSt.upper_alarm_limit); pold->lower_alarm_limit = epicsConvertDoubleToFloat(newSt.lower_alarm_limit); pold->upper_warning_limit = epicsConvertDoubleToFloat(newSt.upper_warning_limit); pold->lower_warning_limit = epicsConvertDoubleToFloat(newSt.lower_warning_limit); pold->upper_ctrl_limit = epicsConvertDoubleToFloat(newSt.upper_ctrl_limit); pold->lower_ctrl_limit = epicsConvertDoubleToFloat(newSt.lower_ctrl_limit); options = 0; status = dbChannelGet(chan, DBR_FLOAT, &pold->value, &options, nRequest, pfl); } break; case(oldDBR_GR_ENUM): case(oldDBR_CTRL_ENUM): { struct dbr_ctrl_enum *pold = (struct dbr_ctrl_enum *)pbuffer; struct { DBRstatus DBRenumStrs } newSt; short no_str; memset(pold, '\0', sizeof(struct dbr_ctrl_enum)); /* first get status and severity */ options = DBR_STATUS | DBR_ENUM_STRS; status = dbChannelGet(chan, DBR_ENUM, &newSt, &options, &zero, pfl); pold->status = newSt.status; pold->severity = newSt.severity; no_str = newSt.no_str; if (no_str>16) no_str=16; pold->no_str = no_str; for (i = 0; i < no_str; i++) strncpy(pold->strs[i], newSt.strs[i], sizeof(pold->strs[i])); /*now get values*/ options = 0; status = dbChannelGet(chan, DBR_ENUM, &pold->value, &options, nRequest, pfl); } break; case(oldDBR_CTRL_CHAR): { struct dbr_ctrl_char *pold = (struct dbr_ctrl_char *)pbuffer; struct { DBRstatus DBRunits DBRgrLong DBRctrlLong DBRalLong } newSt; options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_CTRL_LONG | DBR_AL_LONG; status = dbChannelGet(chan, DBR_UCHAR, &newSt, &options, &zero, pfl); pold->status = newSt.status; pold->severity = newSt.severity; strncpy(pold->units, newSt.units, MAX_UNITS_SIZE); pold->units[MAX_UNITS_SIZE-1] = '\0'; pold->upper_disp_limit = newSt.upper_disp_limit; pold->lower_disp_limit = newSt.lower_disp_limit; pold->upper_alarm_limit = newSt.upper_alarm_limit; pold->upper_warning_limit = newSt.upper_warning_limit; pold->lower_warning_limit = newSt.lower_warning_limit; pold->lower_alarm_limit = newSt.lower_alarm_limit; pold->upper_ctrl_limit = newSt.upper_ctrl_limit; pold->lower_ctrl_limit = newSt.lower_ctrl_limit; options = 0; status = dbChannelGet(chan, DBR_UCHAR, &pold->value, &options, nRequest, pfl); } break; case(oldDBR_CTRL_LONG): { struct dbr_ctrl_long *pold = (struct dbr_ctrl_long *)pbuffer; struct { DBRstatus DBRunits DBRgrLong DBRctrlLong DBRalLong } newSt; options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_CTRL_LONG | DBR_AL_LONG; status = dbChannelGet(chan, DBR_LONG, &newSt, &options, &zero, pfl); pold->status = newSt.status; pold->severity = newSt.severity; strncpy(pold->units, newSt.units, MAX_UNITS_SIZE); pold->units[MAX_UNITS_SIZE-1] = '\0'; pold->upper_disp_limit = newSt.upper_disp_limit; pold->lower_disp_limit = newSt.lower_disp_limit; pold->upper_alarm_limit = newSt.upper_alarm_limit; pold->upper_warning_limit = newSt.upper_warning_limit; pold->lower_warning_limit = newSt.lower_warning_limit; pold->lower_alarm_limit = newSt.lower_alarm_limit; pold->upper_ctrl_limit = newSt.upper_ctrl_limit; pold->lower_ctrl_limit = newSt.lower_ctrl_limit; options = 0; status = dbChannelGet(chan, DBR_LONG, &pold->value, &options, nRequest, pfl); } break; case(oldDBR_CTRL_DOUBLE): { struct dbr_ctrl_double *pold = (struct dbr_ctrl_double *)pbuffer; struct { DBRstatus DBRunits DBRprecision DBRgrDouble DBRctrlDouble DBRalDouble } newSt; options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE | DBR_CTRL_DOUBLE | DBR_AL_DOUBLE; status = dbChannelGet(chan, DBR_DOUBLE, &newSt, &options, &zero, pfl); pold->status = newSt.status; pold->severity = newSt.severity; pold->precision = (dbr_short_t) newSt.precision.dp; strncpy(pold->units, newSt.units, MAX_UNITS_SIZE); pold->units[MAX_UNITS_SIZE-1] = '\0'; pold->upper_disp_limit = newSt.upper_disp_limit; pold->lower_disp_limit = newSt.lower_disp_limit; pold->upper_alarm_limit = newSt.upper_alarm_limit; pold->upper_warning_limit = newSt.upper_warning_limit; pold->lower_warning_limit = newSt.lower_warning_limit; pold->lower_alarm_limit = newSt.lower_alarm_limit; pold->upper_ctrl_limit = newSt.upper_ctrl_limit; pold->lower_ctrl_limit = newSt.lower_ctrl_limit; options = 0; status = dbChannelGet(chan, DBR_DOUBLE, &pold->value, &options, nRequest, pfl); } break; case(oldDBR_STSACK_STRING): { struct dbr_stsack_string *pold = (struct dbr_stsack_string *)pbuffer; struct { DBRstatus } newSt; options = DBR_STATUS; status = dbChannelGet(chan, DBR_STRING, &newSt, &options, &zero, pfl); pold->status = newSt.status; pold->severity = newSt.severity; pold->ackt = newSt.ackt; pold->acks = newSt.acks; options = 0; status = dbChannelGet(chan, DBR_STRING, pold->value, &options, nRequest, pfl); } break; case(oldDBR_CLASS_NAME): { DBENTRY dbEntry; char *name = 0; char *pto = (char *)pbuffer; if (!pdbbase) { status = S_db_notFound; break; } dbInitEntry(pdbbase, &dbEntry); status = dbFindRecord(&dbEntry, dbChannelRecord(chan)->name); if (!status) name = dbGetRecordTypeName(&dbEntry); dbFinishEntry(&dbEntry); if (status) break; if (!name) { status = S_dbLib_recordTypeNotFound; break; } pto[MAX_STRING_SIZE-1] = 0; strncpy(pto, name, MAX_STRING_SIZE-1); } break; default: status = -1; break; } dbScanUnlock(dbChannelRecord(chan)); if (status) return -1; return 0; }
static long dbReadCOM(DBBASE **ppdbbase,const char *filename, FILE *fp, const char *path,const char *substitutions) { long status; inputFile *pinputFile = NULL; char *penv; char **macPairs; if(*ppdbbase == 0) *ppdbbase = dbAllocBase(); pdbbase = *ppdbbase; if(path && strlen(path)>0) { dbPath(pdbbase,path); } else { penv = getenv("EPICS_DB_INCLUDE_PATH"); if(penv) { dbPath(pdbbase,penv); } else { dbPath(pdbbase,"."); } } my_buffer = dbCalloc(MY_BUFFER_SIZE,sizeof(char)); freeListInitPvt(&freeListPvt,sizeof(tempListNode),100); if(substitutions) { if(macCreateHandle(&macHandle,NULL)) { epicsPrintf("macCreateHandle error\n"); status = -1; goto cleanup; } macParseDefns(macHandle,(char *)substitutions,&macPairs); if(macPairs ==NULL) { macDeleteHandle(macHandle); macHandle = NULL; } else { macInstallMacros(macHandle,macPairs); free((void *)macPairs); mac_input_buffer = dbCalloc(MY_BUFFER_SIZE,sizeof(char)); } } pinputFile = dbCalloc(1,sizeof(inputFile)); if(filename) { pinputFile->filename = macEnvExpand(filename); } if(!fp) { FILE *fp1; if(pinputFile->filename) pinputFile->path = dbOpenFile(pdbbase,pinputFile->filename,&fp1); if(!pinputFile->filename || !fp1) { errPrintf(0,__FILE__, __LINE__, "dbRead opening file %s",pinputFile->filename); free((void *)pinputFile->filename); free((void *)pinputFile); status = -1; goto cleanup; } pinputFile->fp = fp1; } else { pinputFile->fp = fp; } pinputFile->line_num = 0; pinputFileNow = pinputFile; my_buffer[0] = '\0'; my_buffer_ptr = my_buffer; ellAdd(&inputFileList,&pinputFile->node); status = pvt_yy_parse(); dbFreePath(pdbbase); if(!status) { /*add RTYP and VERS as an attribute */ DBENTRY dbEntry; DBENTRY *pdbEntry = &dbEntry; long localStatus; dbInitEntry(pdbbase,pdbEntry); localStatus = dbFirstRecordType(pdbEntry); while(!localStatus) { localStatus = dbPutRecordAttribute(pdbEntry,"RTYP", dbGetRecordTypeName(pdbEntry)); if(!localStatus) { localStatus = dbPutRecordAttribute(pdbEntry,"VERS", "none specified"); } if(localStatus) { fprintf(stderr,"dbPutRecordAttribute status %ld\n",status); } else { localStatus = dbNextRecordType(pdbEntry); } } dbFinishEntry(pdbEntry); } cleanup: if(macHandle) macDeleteHandle(macHandle); macHandle = NULL; if(mac_input_buffer) free((void *)mac_input_buffer); mac_input_buffer = NULL; if(freeListPvt) freeListCleanup(freeListPvt); freeListPvt = NULL; if(my_buffer) free((void *)my_buffer); my_buffer = NULL; freeInputFileList(); return(status); }
dbChannel * dbChannelCreate(const char *name) { const char *pname = name; DBENTRY dbEntry; dbChannel *chan = NULL; char *cname; dbAddr *paddr; dbFldDes *pflddes; long status; short dbfType; if (!name || !*name || !pdbbase) return NULL; status = pvNameLookup(&dbEntry, &pname); if (status) goto finish; chan = freeListCalloc(dbChannelFreeList); if (!chan) goto finish; cname = malloc(strlen(name) + 1); if (!cname) goto finish; strcpy(cname, name); chan->name = cname; ellInit(&chan->filters); ellInit(&chan->pre_chain); ellInit(&chan->post_chain); paddr = &chan->addr; pflddes = dbEntry.pflddes; dbfType = pflddes->field_type; paddr->precord = dbEntry.precnode->precord; paddr->pfield = dbEntry.pfield; paddr->pfldDes = pflddes; paddr->no_elements = 1; paddr->field_type = dbfType; paddr->field_size = pflddes->size; paddr->special = pflddes->special; paddr->dbr_field_type = mapDBFToDBR[dbfType]; if (paddr->special == SPC_DBADDR) { struct rset *prset = dbGetRset(paddr); /* Let record type modify paddr */ if (prset && prset->cvt_dbaddr) { status = prset->cvt_dbaddr(paddr); if (status) goto finish; dbfType = paddr->field_type; } } /* Handle field modifiers */ if (*pname) { if (*pname == '$') { /* Some field types can be accessed as char arrays */ if (dbfType == DBF_STRING) { paddr->no_elements = paddr->field_size; paddr->field_type = DBF_CHAR; paddr->field_size = 1; paddr->dbr_field_type = DBR_CHAR; } else if (dbfType >= DBF_INLINK && dbfType <= DBF_FWDLINK) { /* Clients see a char array, but keep original dbfType */ paddr->no_elements = PVNAME_STRINGSZ + 12; paddr->field_size = 1; paddr->dbr_field_type = DBR_CHAR; } else { status = S_dbLib_fieldNotFound; goto finish; } pname++; } if (*pname == '[') { status = parseArrayRange(chan, pname, &pname); if (status) goto finish; } /* JSON may follow */ if (*pname == '{') { status = chf_parse(chan, &pname); if (status) goto finish; } /* Make sure there's nothing else */ if (*pname) { status = S_dbLib_fieldNotFound; goto finish; } } finish: if (status && chan) { dbChannelDelete(chan); chan = NULL; } dbFinishEntry(&dbEntry); return chan; }
/* * Fill out a database structure (*paddr) for * a record given by the name "pname." * * Returns error codes from StaticLib module, not * from dbAccess. */ long epicsShareAPI dbNameToAddr(const char *pname, DBADDR *paddr) { DBENTRY dbEntry; dbFldDes *pflddes; struct rset *prset; long status = 0; long no_elements = 1; short dbfType, dbrType, field_size; if (!pname || !*pname || !pdbbase) return S_db_notFound; dbInitEntry(pdbbase, &dbEntry); status = dbFindRecordPart(&dbEntry, &pname); if (status) goto finish; if (*pname == '.') ++pname; status = dbFindFieldPart(&dbEntry, &pname); if (status == S_dbLib_fieldNotFound) status = dbGetAttributePart(&dbEntry, &pname); if (status) goto finish; paddr->precord = dbEntry.precnode->precord; paddr->pfield = dbEntry.pfield; pflddes = dbEntry.pflddes; dbfType = pflddes->field_type; dbrType = mapDBFToDBR[dbfType]; field_size = pflddes->size; if (*pname++ == '$') { /* Some field types can be accessed as char arrays */ if (dbfType == DBF_STRING) { dbfType = DBF_CHAR; dbrType = DBR_CHAR; no_elements = field_size; field_size = 1; } else if (dbfType >= DBF_INLINK && dbfType <= DBF_FWDLINK) { /* Clients see a char array, but keep original dbfType */ dbrType = DBR_CHAR; no_elements = PVNAME_STRINGSZ + 12; field_size = 1; } else { status = S_dbLib_fieldNotFound; goto finish; } } paddr->pfldDes = pflddes; paddr->field_type = dbfType; paddr->dbr_field_type = dbrType; paddr->field_size = field_size; paddr->special = pflddes->special; paddr->no_elements = no_elements; if ((paddr->special == SPC_DBADDR) && (prset = dbGetRset(paddr)) && prset->cvt_dbaddr) /* cvt_dbaddr routine may change any of these elements of paddr: * pfield, no_elements, element_offset, field_type, * dbr_field_type, field_size, and/or special. */ status = prset->cvt_dbaddr(paddr); finish: dbFinishEntry(&dbEntry); return status; }
/* * Fill out a database structure (*paddr) for * a record given by the name "pname." * * Returns error codes from StaticLib module, not * from dbAccess. */ long dbNameToAddr(const char *pname, DBADDR *paddr) { DBENTRY dbEntry; dbFldDes *pflddes; long status = 0; short dbfType; if (!pname || !*pname || !pdbbase) return S_db_notFound; dbInitEntry(pdbbase, &dbEntry); status = dbFindRecordPart(&dbEntry, &pname); if (status) goto finish; if (*pname == '.') ++pname; status = dbFindFieldPart(&dbEntry, &pname); if (status == S_dbLib_fieldNotFound) status = dbGetAttributePart(&dbEntry, &pname); if (status) goto finish; pflddes = dbEntry.pflddes; dbfType = pflddes->field_type; paddr->precord = dbEntry.precnode->precord; paddr->pfield = dbEntry.pfield; paddr->pfldDes = pflddes; paddr->no_elements = 1; paddr->field_type = dbfType; paddr->field_size = pflddes->size; paddr->special = pflddes->special; paddr->dbr_field_type = mapDBFToDBR[dbfType]; if (paddr->special == SPC_DBADDR) { struct rset *prset = dbGetRset(paddr); /* Let record type modify paddr */ if (prset && prset->cvt_dbaddr) { status = prset->cvt_dbaddr(paddr); if (status) goto finish; dbfType = paddr->field_type; } } /* Handle field modifiers */ if (*pname++ == '$') { /* Some field types can be accessed as char arrays */ if (dbfType == DBF_STRING) { paddr->no_elements = paddr->field_size; paddr->field_type = DBF_CHAR; paddr->field_size = 1; paddr->dbr_field_type = DBR_CHAR; } else if (dbfType >= DBF_INLINK && dbfType <= DBF_FWDLINK) { /* Clients see a char array, but keep original dbfType */ paddr->no_elements = PVNAME_STRINGSZ + 12; paddr->field_size = 1; paddr->dbr_field_type = DBR_CHAR; } else { status = S_dbLib_fieldNotFound; goto finish; } } finish: dbFinishEntry(&dbEntry); return status; }
long epicsShareAPI dbl(const char *precordTypename, const char *fields) { DBENTRY dbentry; DBENTRY *pdbentry=&dbentry; long status; int nfields = 0; int ifield; char *fieldnames = 0; char **papfields = 0; if (!pdbbase) { printf("No database loaded\n"); return 0; } if (precordTypename && ((*precordTypename == '\0') || !strcmp(precordTypename,"*"))) precordTypename = NULL; if (fields && (*fields == '\0')) fields = NULL; if (fields) { char *pnext; fieldnames = epicsStrDup(fields); nfields = 1; pnext = fieldnames; while (*pnext && (pnext = strchr(pnext,' '))) { nfields++; while (*pnext == ' ') pnext++; } papfields = dbCalloc(nfields,sizeof(char *)); pnext = fieldnames; for (ifield = 0; ifield < nfields; ifield++) { papfields[ifield] = pnext; if (ifield < nfields - 1) { pnext = strchr(pnext, ' '); *pnext++ = 0; while (*pnext == ' ') pnext++; } } } dbInitEntry(pdbbase, pdbentry); if (!precordTypename) status = dbFirstRecordType(pdbentry); else status = dbFindRecordType(pdbentry,precordTypename); if (status) { printf("No record type\n"); } while (!status) { status = dbFirstRecord(pdbentry); while (!status) { printf("%s", dbGetRecordName(pdbentry)); for (ifield = 0; ifield < nfields; ifield++) { char *pvalue; status = dbFindField(pdbentry, papfields[ifield]); if (status) { if (!strcmp(papfields[ifield], "recordType")) { pvalue = dbGetRecordTypeName(pdbentry); } else { printf(", "); continue; } } else { pvalue = dbGetString(pdbentry); } printf(", \"%s\"", pvalue ? pvalue : ""); } printf("\n"); status = dbNextRecord(pdbentry); } if (precordTypename) break; status = dbNextRecordType(pdbentry); } if (nfields > 0) { free((void *)papfields); free((void *)fieldnames); } dbFinishEntry(pdbentry); return 0; }
static int dbpr_report( const char *pname, DBADDR *paddr, int interest_level, TAB_BUFFER *pMsgBuff, int tab_size) { char *pmsg; dbFldDes *pdbFldDes = paddr->pfldDes; dbRecordType *pdbRecordType = pdbFldDes->pdbRecordType; short n2; void *pfield; char *pfield_name; char *pfield_value; DBENTRY dbentry; DBENTRY *pdbentry = &dbentry; long status; dbInitEntry(pdbbase,pdbentry); status = dbFindRecord(pdbentry,pname); if (status) { errMessage(status,pname); return -1; } pmsg = pMsgBuff->message; for (n2 = 0; n2 <= pdbRecordType->no_fields - 1; n2++) { pdbFldDes = pdbRecordType->papFldDes[pdbRecordType->sortFldInd[n2]]; pfield_name = pdbFldDes->name; pfield = ((char *)paddr->precord) + pdbFldDes->offset; if (pdbFldDes->interest > interest_level ) continue; switch (pdbFldDes->field_type) { case DBF_STRING: case DBF_USHORT: case DBF_ENUM: case DBF_FLOAT: case DBF_CHAR: case DBF_UCHAR: case DBF_SHORT: case DBF_LONG: case DBF_ULONG: case DBF_DOUBLE: case DBF_MENU: case DBF_DEVICE: status = dbFindField(pdbentry,pfield_name); pfield_value = dbGetString(pdbentry); sprintf(pmsg, "%s: %s", pfield_name, (pfield_value ? pfield_value : "<nil>")); dbpr_msgOut(pMsgBuff, tab_size); break; case DBF_INLINK: case DBF_OUTLINK: case DBF_FWDLINK: { DBLINK *plink = (DBLINK *)pfield; int ind; status = dbFindField(pdbentry,pfield_name); for (ind=0; ind<LINK_NTYPES; ind++) { if (pamaplinkType[ind].value == plink->type) break; } if (ind>=LINK_NTYPES) { sprintf(pmsg,"%s: Illegal Link Type", pfield_name); } else { sprintf(pmsg,"%s:%s %s", pfield_name, pamaplinkType[ind].strvalue,dbGetString(pdbentry)); } dbpr_msgOut(pMsgBuff, tab_size); } break; case DBF_NOACCESS: if (pfield == (void *)&paddr->precord->time) { /* Special for the TIME field, make it human-readable */ char time_buf[40]; epicsTimeToStrftime(time_buf, 40, "%Y-%m-%d %H:%M:%S.%09f", &paddr->precord->time); sprintf(pmsg, "%s: %s", pfield_name, time_buf); dbpr_msgOut(pMsgBuff, tab_size); } else if (pdbFldDes->size == sizeof(void *) && strchr(pdbFldDes->extra, '*')) { /* Special for pointers, needed on little-endian CPUs */ sprintf(pmsg, "%s: %p", pfield_name, *(void **)pfield); dbpr_msgOut(pMsgBuff, tab_size); } else { /* just print field as hex bytes */ unsigned char *pchar = (unsigned char *)pfield; char temp_buf[61]; char *ptemp_buf = &temp_buf[0]; short n = pdbFldDes->size; short i; unsigned int value; if (n > sizeof(temp_buf)/3) n = sizeof(temp_buf)/3; for (i=0; i<n; i++, ptemp_buf += 3, pchar++) { value = (unsigned int)*pchar; sprintf(ptemp_buf, "%02x ", value); } sprintf(pmsg, "%s: %s", pfield_name,temp_buf); dbpr_msgOut(pMsgBuff, tab_size); } break; default: sprintf(pmsg, "%s: dbpr: Unknown field_type", pfield_name); dbpr_msgOut(pMsgBuff, tab_size); break; } } pmsg[0] = '\0'; dbpr_msgOut(pMsgBuff, tab_size); dbFinishEntry(pdbentry); return (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; }