The diagnostic people here at SNS (where I'll be for the next couple of years,
right down the hall from David Thompson) have been asking for even more- They want
time stamps to be able to propagate over forward links and, I assume for more
generality, dbPutLinks. I start with the assumption of the code Marty gave(in my
working code I've been calling it "SPECIAL_TIME_EVENT" and making it -2) and then
have had several routines in dbAccess.c and recGbl.c propagate the time if its
set. I've been working on a copy of 3.14.beta0.
From recGbl.c I have:
void epicsShareAPI recGblFwdLink(void *precord)
{
struct dbCommon *pdbc = precord;
static short fwdLinkValue = 1;
if(pdbc->flnk.type==DB_LINK ) {
struct dbAddr *paddr = pdbc->flnk.value.pv_link.pvt;
if (paddr->precord->tse == SPECIAL_TIME_EVENT)
paddr->precord->time = pdbc->time;
dbScanPassive(precord,paddr->precord);
} else
if((pdbc->flnk.type==CA_LINK)
....
From dbAccess.c I have:
void epicsShareAPI dbScanFwdLink(struct link *plink)
{
dbCommon *precord;
struct pv_link *pvlink;
short fwdLinkValue;
if(plink->type!=DB_LINK && plink->type!=CA_LINK) return;
pvlink = &plink->value.pv_link;
precord = pvlink->precord;
if(plink->type==DB_LINK) {
DBADDR *paddr = (DBADDR *)plink->value.pv_link.pvt;
if (paddr->precord->tse == SPECIAL_TIME_EVENT)
paddr->precord->time = precord->time;
dbScanPassive(precord,paddr->precord);
return;
}
if(!(pvlink->pvlMask & pvlOptFWD)) return;
fwdLinkValue = 1;
dbCaPutLink(plink,DBR_SHORT,&fwdLinkValue,1);
return;
}
and:
long epicsShareAPI dbPutLinkValue(struct link *plink,
short dbrType,const void *pbuffer,long nRequest)
{
long status=0;
if(plink->type==DB_LINK) {
struct dbCommon *psource = plink->value.pv_link.precord;
struct pv_link *ppv_link= &(plink->value.pv_link);
DBADDR *paddr = (DBADDR*)(ppv_link->pvt);
dbCommon *pdest = paddr->precord;
if (pdest->tse == SPECIAL_TIME_EVENT)
pdest->time = psource->time;
status=dbPut(paddr,dbrType,pbuffer,nRequest);
if(ppv_link->pvlMask&pvlOptMS)
recGblSetSevr(pdest,LINK_ALARM,psource->nsev);
.....
Note that I am not thinking to support channel access links or input links (hence I
don't put it in dbScanPassive). There may be situations in which the target record
would not process at all or would be processing asynchronously and would just sit
there with the wrong time stamp -- this would be an unintended behavior that is not
excluded but could happen. At least it would only happen if the target record had
this time event set. Old databases would be unaffected.
So records with this event type set might get their time either from links that
caused them to process or from device support. In general, the diagnostics team
wants to see chains of records, the first one of which would get the time stamp
from device support and subsequent ones would process it, keeping the same time
stamp.
Carl
Marty Kraimer wrote:
Someone else asked for this feature. I think the first person to ask was Timo
Korhonen (SLS) who is also the person who is redoing drvTS, which is the support
for hardware generated time stamps.
The next version of base (both 3.13 and 3.14) will provide this feature. The
exact method is still undecided. Corrently in my working area I have the
following change to recGbl.c
For 3.13
void recGblGetTimeStamp(void* prec)
{
struct dbCommon* pr = (struct dbCommon*)prec;
if(pr->tsel.type!=CONSTANT)
dbGetLink(&(pr->tsel), DBR_SHORT,&(pr->tse),0,0);
if(pr->tse!=-1)
TSgetTimeStamp((int)pr->tse,(struct timespec*)&pr->time);
}
For 3.14 I have
void epicsShareAPI recGblGetTimeStamp(void* prec)
{
struct dbCommon* pr = (struct dbCommon*)prec;
int status = 0;
if(pr->tsel.type!=CONSTANT)
dbGetLink(&(pr->tsel), DBR_SHORT,&(pr->tse),0,0);
if (pr->tse!=-1)
status = epicsTimeGetEvent(&pr->time,(unsigned)pr->tse);
if(status) errlogPrintf("%s recGblGetTimeStamp failed\n",pr->name);
}
The above change says that if TSE=-1 then dont do anyting to the time stamp.
This is NOT the final answer however. David Thompson (SNS) pointed out that the
existing drvTS already treats TSE=-1 as a special case. It means that drvTS
should get the most accurate current time stamp. For example with the APS
hardware time stamp support, we keep a 1 millisecond hardware generated clock.
If TSE=-1 then the time stamp will be taken from this clock rather than the
vxWorks 60 HZ clock.
Thus the above change to recGblGetTimeStamp is not correct. David suggested that
we define.
#define epicsTimeEventBestTime -1
#define epicsTimeEventDeviceTime -10000
epicsTimeEventBestTime would be used by drvTS and it's successor.
epicsTimeEventDeviceTime says that device support is supplying the time stamp so
recGblGetTimeStamp should not do anything.
Questions to be resolved
1) Where do we define these? For 3.14 the obvious place is epicsTime.h. For 3.13
it is probably tsDefs.h
2) What value should we use for epicsTimeEventDeviceTime?
3) Whoever set the value for TSE must know about these values. How do we make
these values known? Just document them in the Application Developer's Guide?
Noboru Yamamoto wrote:
Hi,
[Question]
Is there any good way to set a timestamp of a record while a
process() function of a device support routine is called?
[Why I'm asking this question]
We need to import live data from the facility control
system, which uses a proprietary control system. This system
update the information on the memory periodically with
theire own timestamp. We would like to use
this timestamp as a timestamp of EPICS records rather than
the timestamp when the record is updated.
Looking at aiRecord.c, for example, recGblGetTimeStamp is
called AFTER a call to read() function in a device support
is finished.
Any idea?
Noboru