exampleLink implements a PVRecord that that links to another channel.
This example shows how a PVRecord can have support that accesses another channel. It creates records named exampleMonitorLink, exampleGetLink, and examplePutLink. Each has a link to another channel. The process method of the records use pvaChannelMonitor, pvaChannelGet, and pvaChannelPut to connect to the other channel.
exampleLink can be started either as a main program of as part of an EPICS V3 IOC.
mrk> pwd /home/epicsv4/master/exampleCPP/exampleLink mrk> bin/$EPICS_HOST_ARCH/exampleLinkMain
mrk> pwd /home/epicsv4/master/exampleCPP/exampleLink/iocBoot/exampleLink mrk> ../../bin/$EPICS_HOST_ARCH/exampleLink st.cmd
A pvaClient test is available to test exampleLink. Start the example and then:
mrk> pwd /home/epicsv4/master/exampleCPP/exampleLink mrk> bin/$EPICS_HOST_ARCH/exampleLinkClient
The process routine of a PVRecord can access other PVRecords in two ways:
If pvAccess (provider pva or ca) is used then it handles data synchronization. This is done by making a copy of the data that is transferred between the two pvRecords. This is true if either remote or local pvAccess is used. Each get, put, etc request results in data being copied between the two records.
If the linked channel is a local pvRecord then, for scalar and structure arrays, raw data is NOT copied for gets. This is because pvData uses shared_vector to hold the raw data. Instead of copying the raw data the reference count is incremented.
For puts the linked array will force a new allocation of the raw data in the linked record, i. e. copy on write semantics are enforced. This is done automatically by pvData and not by pvDatabase.
As mentioned before a pvDatabase server can be either a separate process, i. e. a main program, or can be part of a V3IOC.
A main pvDatabase server issues the following calls:
... PVDatabasePtr master = PVDatabase::getMaster(); ChannelProviderLocalPtr channelProvider = getChannelProviderLocal(); PvaClientPtr pva= PvaClient::create("providerList"); ServerContext::shared_pointer ctx = startPVAServer("local",0,true,true); ... master->addRecord(... ... cout << "exampleLink\n"; string str; while(true) { cout << "Type exit to stop: \n"; getline(cin,str); if(str.compare("exit")==0) break; } ...
PvaClientPtr pva= PvaClient::create(providerList) is only necessary if some of the pvRecords have pva or ca links. This must be called before any code that uses links is initialized.
A pvDatabase that is part of a V3IOC has the following in the st.cmd file.
... iocInit() startPVAServer local ## commands to create pvRecords
The options supported by exampleLinkMain are shown by:
mrk> pwd /home/epicsv4/master/exampleCPP/exampleLink mrk> bin/linux-x86_64/exampleLinkMain -help provider exampleLinkRecordName . generateLinkedRecord default pva exampleLink doubleArray true mrk>
Thus to run it with default options:
bin/linux-x86_64/exampleLinkMain
exampleLinkMain creates an instance of ExampleLinkRecord. The record name is exampleLinkRecordName. The ExampleLinkRecord monitors linkedRecordName using the specified provider.
After exampleLinkMain is started then in another window:
pvget -m -r "field()" exampleMonitorLink
This can be kept running while exampleLinkMain is stopped and then restarted with other options as long as exampleLinkRecordName is doubleArray.
This makes changes to the record that exampleLink monitors. It has the options:
mrk> pwd /home/epicsv4/master/exampleCPP/exampleLink mrk> bin/linux-x86_64/exampleLinkClient -help provider default pva
NOTE: If exampleLinkMain is stated with provider ca then exampleLinkClient must also be run with provider ca
exampleLinkClient only works if linkedRecordName is doubleArray.
This can be tested via:
bin/linux-x86_64/exampleLinkMain local
This can be done via the default options:
bin/linux-x86_64/exampleLinkMain
It can also be run with pva accessing a record in another IOC:
bin/linux-x86_64/exampleLinkMain pva exampleLink doubleArray false
But this only starts running when the following is also started:
mrk> pwd /home/epicsv4/master/exampleCPP/exampleLink mrk> bin/linux-x86_64/doubleArrayMain
NOTE do not leave this running for other exampleLinkMain options.
This can be tested as follows:
bin/linux-x86_64/exampleLinkMain ca exampleLink doubleArray false
But a softIoc for record doubleArray must also be started:
mrk> pwd /home/epicsv4/master/exampleCPP/exampleLink/v3IOC mrk> softIoc st.cmd
exampleLink configure ExampleRELEASE.local ... src pv exampleLinkRecord.h exampleLinkRecord.cpp exampleLinkInclude.dbd exampleLinkRegister.cpp exampleLinkClient.cpp exampleLinkMain.cpp doubleArrayMain.cpp ioc Db src exampleLinkInclude.dbd exampleLinkMain.cpp iocBoot exampleLink st.local st.remote v3IOC db doubleArray.db st.cmd README ...