make compatible with pvDataCPP-md; channelArray implemented; can be part of v3IOC.
This commit is contained in:
4
Makefile
4
Makefile
@ -6,9 +6,11 @@ DIRS += configure
|
||||
DIRS += src
|
||||
src_DEPEND_DIRS = configure
|
||||
|
||||
DIRS += test
|
||||
DIRS += example
|
||||
test_DEPEND_DIRS = src
|
||||
|
||||
DIRS += iocBoot
|
||||
|
||||
include $(TOP)/configure/RULES_TOP
|
||||
|
||||
|
||||
|
@ -38,7 +38,7 @@
|
||||
<h1>pvDatabaseCPP</h1>
|
||||
<!-- Maturity: Working Draft or Request for Comments, or Recommendation, and date. -->
|
||||
|
||||
<h2 class="nocount">EPICS v4 Working Group, Working Draft, 27-Jun-2013</h2>
|
||||
<h2 class="nocount">EPICS v4 Working Group, Working Draft, 25-Jul-2013</h2>
|
||||
<dl>
|
||||
<dt>Latest version:</dt>
|
||||
<dd><a
|
||||
@ -46,11 +46,14 @@
|
||||
</dd>
|
||||
<dt>This version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDatabaseCPP/raw-file/tip/documentation/pvDatabaseCPP_20130627.html">pvDatabaseCPP20130627.html</a>
|
||||
href=
|
||||
"http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDatabaseCPP/raw-file/tip/documentation/pvDatabaseCPP_20130725.html">
|
||||
pvDatabaseCPP20130725.html</a>
|
||||
</dd>
|
||||
<dt>Previous version:</dt>
|
||||
<dd><a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDatabaseCPP/raw-file/tip/documentation/pvDatabaseCPP_20130523.html">pvDatabaseCPP20130523.html</a>
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/pvDatabaseCPP/raw-file/tip/documentation/pvDatabaseCPP_20130627.html">
|
||||
pvDatabaseCPP20130627.html</a>
|
||||
</dd>
|
||||
<dt>Editors:</dt>
|
||||
<dd>Marty Kraimer, BNL</dd>
|
||||
@ -74,29 +77,36 @@ The minimum that an extenson must provide is a top level PVStructure and a proce
|
||||
|
||||
<h2 class="nocount">Status of this Document</h2>
|
||||
|
||||
<p>This is the 27-Jun-2013 version of the definition of pvDatabaseCPP.
|
||||
<p>This is the 25-Jul-2013 version of the definition of pvDatabaseCPP.
|
||||
<p><b>NOTE:</b>
|
||||
This is built against pvDataCPP-md NOT against pvDataCPP.
|
||||
To build you must also
|
||||
checkout pvAccessCPP and build it against pvDataCPP-md.
|
||||
</p>
|
||||
<p>The following Channel methods are implemented and working: getField,
|
||||
channelProcess, channelGet, channelPut, channelPutGet,channelArray and Monitor.
|
||||
But work remains:</p>
|
||||
</p>
|
||||
<p>All channel methods except channelRPCi, which is implemented
|
||||
by pvAccess, have been implemented.
|
||||
This project is ready for alpha users.
|
||||
</p>
|
||||
<p>Future enhancements in priority order:</p>
|
||||
<dl>
|
||||
<dt>Other Channel Methods</dt>
|
||||
<dd>channlRPC will not be implemented because pvAccess itself
|
||||
provides what is required to easily implement channelRPC requests.
|
||||
</dd>
|
||||
<dt>pvAccess directly to local channelProvider</dt>
|
||||
<dd>Create an example record that communicates with another
|
||||
record via pvAccess but directly connects to channelProviderLocal.
|
||||
Thus channelGet and monitor of arrays will be done without
|
||||
copying raw array data.</dd>
|
||||
<dt>Array performance</dt>
|
||||
<dd>Create an example record that continuously creates array data.
|
||||
The idea is to compare performance allocating memory from the
|
||||
heap vs using a free list.</dd>
|
||||
<dt>Separate example that also has pvaSrv</dt>
|
||||
<dd>Create a separate example that combines a V3IOC,
|
||||
a pvDatabase, and pvaSrv.</dd>
|
||||
<dt>Monitor Algorithms</dt>
|
||||
<dd>Monitor algorithms have not been implemented.
|
||||
Thus all monitors are onPut.</dd>
|
||||
<dt>Memory leaks</dt>
|
||||
<dd>I think all memory leaks have been fixed.</dd>
|
||||
<dt>Scalar Arrays</dt>
|
||||
<dd>Share has not been implemented.
|
||||
This will wait for a new implementation of ScalarArray.</dd>
|
||||
<dt>Structure Arrays</dt>
|
||||
<dd>Has not been implemented</dd>
|
||||
<dt>toString</dt>
|
||||
<dd>The toString methods should be replaced by stream operator<<.
|
||||
</dd>
|
||||
<dt>Testing</dt>
|
||||
<dd>Needs more testing</dd>
|
||||
</dl>
|
||||
@ -137,8 +147,19 @@ A record is smart because code can be attached to a record, which is accessed vi
|
||||
as defined by pvAccess.
|
||||
It is used by the server side of pvAccess to attach to pvRecords.
|
||||
This component also includes the monitor and pvCopy components from pvIOCJava</dd>
|
||||
<dt>Main and V3IOC</dt>
|
||||
<dd>The pvDatabase can be provided via a Main program or can be part
|
||||
of a V3IOC. In tha later case the IOC has both a database of V3 Records
|
||||
and a pvDatabase.</dd>
|
||||
<dt>exampleCounter</dt>
|
||||
<dd>This is a simple example showing how to create a PVRecord and
|
||||
how to deploy it either as a standalone process or as part of a V3IOC.</dd>
|
||||
<dt>exampleServer</dt>
|
||||
<dd>This example has a set of PVRecords.
|
||||
Again the records can be deployed either as a standalone process or
|
||||
as part of a V3IOC.
|
||||
</dl>
|
||||
<p>database provides base classes that make it easy to create record instances.
|
||||
<p><b>database</b> provides base classes that make it easy to create record instances.
|
||||
The code attached to each record must create the top
|
||||
level PVStructure and the following three methods:</p>
|
||||
<dl>
|
||||
@ -153,42 +174,68 @@ level PVStructure and the following three methods:</p>
|
||||
<dd>This releases and resorurces used by the impplementation.</dd>
|
||||
</dl>
|
||||
<h3>Getting started</h3>
|
||||
<p>Included with this project are two main programs that are useful for
|
||||
<p>Included with this project are two examples that are useful for
|
||||
seeing how pvDatabase can be used by clients.
|
||||
The programs are:
|
||||
Each can be deployed either as a standalone process or as part of a V3IOC.
|
||||
The examples are:
|
||||
<dl>
|
||||
<dt>exampleCounterMain</dt>
|
||||
<dd>This has a database consisting of two records:
|
||||
The exampleCounter discussed in a following section and a record
|
||||
that allows a pvAccess client to set the trace level of the
|
||||
exampleCounter. This is also discussed below.
|
||||
</dd>
|
||||
<dt>testExamplServerMain</dt>
|
||||
<dd>This has a database consisting of a single record named exampleCounter:
|
||||
The exampleCounter is discussed in a following section.</dd>
|
||||
<dt>exampleCounter</dt>
|
||||
<dd>This is exampleCounter as part of a V3IOC.</dd>
|
||||
<dt>exampleServerMain</dt>
|
||||
<dd>This has a database with several records.</dd>
|
||||
<dt>exampleServer</dt>
|
||||
<dd>This is exampleServer as part of a V3IOC</dd>
|
||||
</dt>
|
||||
</p>
|
||||
<p>To start one of the programs on linux, do the following:
|
||||
<h3>exampleCounter</h3>
|
||||
<p>To start exampleCounterMain:
|
||||
<pre>
|
||||
mrk> pwd
|
||||
/home/hg/pvDatabaseCPP
|
||||
mrk> bin/linux-x86_64/testExampleServer
|
||||
mrk> bin/linux-x86_64/exampleCounterMain
|
||||
</pre></p>
|
||||
<p>The Java programs
|
||||
<p>To start exampleCounter as part of a V3IOC:
|
||||
<pre>
|
||||
mrk> pwd
|
||||
/home/hg/pvDatabaseCPP/iocBoot/exampleCounter
|
||||
mrk> ../../../bin/linux-x86_64/exampleCounter st.cmd
|
||||
</pre></p>
|
||||
<p>You can then issue the commands dbl and pvdbl:
|
||||
<pre>
|
||||
epics> dbl
|
||||
double01
|
||||
epics> pvdbl
|
||||
exampleCounter
|
||||
epics>
|
||||
</pre>
|
||||
double01 is a v3Record.
|
||||
exampleCounter is a pvRecord.
|
||||
</p>
|
||||
<p>Starting exampleServer is similar.
|
||||
After successfully running exampleCounterMain and exampleCounter then
|
||||
try starting exampleServerMain and exampleServer.
|
||||
</p>
|
||||
<h3>swtshell</h3>
|
||||
<p>The Java program
|
||||
<a
|
||||
href="http://epics-pvdata.hg.sourceforge.net/hgweb/epics-pvdata/swtshellJava/raw-file/tip/documentation/swtshellJava.html">
|
||||
swtshellJava.html</a>
|
||||
can be used to access the database.</p>
|
||||
swtshell</a>
|
||||
can be used to access pvDatabase.</p>
|
||||
<p>In particular read the sections "Getting Started" and "Simple Example".
|
||||
They will work on the testExampleServer with the following differences:
|
||||
They will work on the exampleServer with the following differences:
|
||||
<dl>
|
||||
<dt>startExample.zip</dt>
|
||||
<dd>Do NOT use this. Instead run testExampleServer</dd>
|
||||
<dd>Do NOT use this. Instead run exampleServer</dd>
|
||||
<dt>channelList result</dt>
|
||||
<dd>The result of channelList will show the list of records that
|
||||
testExampleServer has rather than the records from startExample.zip</dd>
|
||||
exampleServer has rather than the records from startExample.zip</dd>
|
||||
</dl>
|
||||
</p>
|
||||
<p>The database has the following records:
|
||||
<h3>exampleServer</h3>
|
||||
<p>The exampleServer pvDatabase includes the following records:
|
||||
<dl>
|
||||
<dt>exampleCounter</dt>
|
||||
<dd>A record that is an instance of exampleCounter described below.
|
||||
@ -209,6 +256,7 @@ They will work on the testExampleServer with the following differences:
|
||||
<dt>traceRecordPGRPC</dt>
|
||||
<dd>This can be used via channelPutGet to set the trace level of another record.</dd>
|
||||
</dl>
|
||||
<p>It also has a number of other scalar and array records.</p>
|
||||
|
||||
<h3>Relationship with pvIOCJava.</h3>
|
||||
<p>This document descibes a C++ implementation of some of the components in pvIOCJava,
|
||||
@ -240,13 +288,23 @@ mrk> pwd
|
||||
mrk> bin/linux-x86_64/exampleCounter
|
||||
|
||||
</pre>
|
||||
<p>The example consists of two components:</p>
|
||||
<p>The example consists of four components:</p>
|
||||
<dl>
|
||||
<dt>ExampleCounter.h</dt>
|
||||
<dd>The source code for the counter.</dd>
|
||||
<dd>The source code for the counter.
|
||||
It is located in directory pvDatabaseCPP/example/src/exampleCounter.
|
||||
</dd>
|
||||
<dt>exampleCounterMain.cpp</dt>
|
||||
<dd>A main program that runs the example so that it can be accessed
|
||||
by a pvAccess client.</dd>
|
||||
by a pvAccess client.
|
||||
It is located in directory pvDatabaseCPP/example/exampleCounter.
|
||||
</dd>
|
||||
<dt>v3IOC/exampleCounter</dt>
|
||||
<dd>This is a directory that packages exampleCounter to make it
|
||||
part of a v3IOC.</dd>
|
||||
<dt>iocBoot/exampleCounter</dt>
|
||||
<dd>A place to start exampleCounter as part of a v3IOC.
|
||||
It follows the normal iocCore conventions.</dd>
|
||||
</dl>
|
||||
<h4>ExampleCounter.h</h4>
|
||||
<p>The example resides in src/database.
|
||||
@ -383,11 +441,10 @@ void ExampleCounter::process()
|
||||
It adds 1.0 to the current value.
|
||||
It then sets the timeStamp to the current time.
|
||||
<h4>exampleCounterMain.cpp</h4>
|
||||
<p>This is in test/server.</p>
|
||||
<p><b>NOTE:</b>
|
||||
This is a shorter version of the actual code.
|
||||
It shows the essential code.
|
||||
The actual example shows how the create additional records.
|
||||
The actual example shows how create an additional record.
|
||||
</p>
|
||||
<p>The main program is:</p>
|
||||
<pre>
|
||||
@ -400,7 +457,8 @@ int main(int argc,char *argv[])
|
||||
bool result = master->addRecord(pvRecord);
|
||||
cout << "result of addRecord " << recordName << " " << result << endl;
|
||||
pvRecord.reset();
|
||||
cout << "exampleServer\n";
|
||||
startPVAServer(PVACCESS_ALL_PROVIDERS,0,true,true);
|
||||
cout << "exampleCounter\n";
|
||||
string str;
|
||||
while(true) {
|
||||
cout << "Type exit to stop: \n";
|
||||
@ -420,6 +478,40 @@ This:
|
||||
<li>Prints exampleCounter on standard out.</li>
|
||||
<li>Runs forever until the user types exit on standard in.</li>
|
||||
</ul>
|
||||
<h4>v3IOC exampleCounter</h4>
|
||||
<p>This has two subdirectories:
|
||||
<dl>
|
||||
<dt>Db</dt>
|
||||
<dd>This has a template for a single v3Record.</dd>
|
||||
<dt>src</dt>
|
||||
<dd>This has code to allow exampleCounter to reside in a v3IOC.</dd>
|
||||
</dl>
|
||||
</p>
|
||||
<p>The src directory has the following components:</p>
|
||||
<dl>
|
||||
<dt>exampleCounterMain.cpp</dt>
|
||||
<dd>This is just a standard Main for a v3IOC.</dd>
|
||||
<dt>exampleCounterInclude.dbd</dt>
|
||||
<dd>This is:
|
||||
<pre>
|
||||
include "base.dbd"
|
||||
include "PVAServerRegister.dbd"
|
||||
registrar("exampleCounterRegister")
|
||||
</pre>
|
||||
This includes the dbd components required from base,
|
||||
the dbd file for starting pvAccess and the local channelProvider,
|
||||
and the dbd file for the example. The later is for the code from the
|
||||
next file.
|
||||
</dd>
|
||||
<dt>exampleCounter.cpp</dt>
|
||||
<dd>This is the code that registers a command the can be issued
|
||||
via the iocsh, which is the console for a v3IOC.
|
||||
The example supports a single command:
|
||||
<pre>
|
||||
exampleCounterCreateRecord recordName
|
||||
</pre>
|
||||
</dd>
|
||||
</dl>
|
||||
<h3>Phased Development</h3>
|
||||
<p>This documentation describes the first phase of a phased implementation of pvDatabaseCPP:</pp>
|
||||
<dl>
|
||||
|
1242
documentation/pvDatabaseCPP_20130725.html
Normal file
1242
documentation/pvDatabaseCPP_20130725.html
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,10 @@
|
||||
TOP = ..
|
||||
include $(TOP)/configure/CONFIG
|
||||
DIRS += src
|
||||
DIRS += record
|
||||
DIRS += pvCopy
|
||||
DIRS += server
|
||||
DIRS += exampleCounter
|
||||
DIRS += exampleServer
|
||||
DIRS += v3IOC
|
||||
include $(TOP)/configure/RULES_DIRS
|
||||
|
13
example/exampleCounter/Makefile
Normal file
13
example/exampleCounter/Makefile
Normal file
@ -0,0 +1,13 @@
|
||||
TOP=../..
|
||||
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
PROD_HOST += exampleCounterMain
|
||||
exampleCounterMain_SRCS += exampleCounterMain.cpp
|
||||
exampleCounterMain_LIBS += pvDatabase pvAccess pvData Com
|
||||
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
#----------------------------------------
|
||||
# ADD RULES AFTER THIS LINE
|
||||
|
@ -48,7 +48,7 @@ int main(int argc,char *argv[])
|
||||
if(!result) cout<< "record " << recordName << " not added" << endl;
|
||||
pvRecord.reset();
|
||||
startPVAServer(PVACCESS_ALL_PROVIDERS,0,true,true);
|
||||
cout << "exampleServer\n";
|
||||
cout << "exampleCounter\n";
|
||||
string str;
|
||||
while(true) {
|
||||
cout << "Type exit to stop: \n";
|
12
example/exampleServer/Makefile
Normal file
12
example/exampleServer/Makefile
Normal file
@ -0,0 +1,12 @@
|
||||
TOP=../..
|
||||
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
PROD_HOST += exampleServerMain
|
||||
exampleServerMain_SRCS += exampleServerMain.cpp
|
||||
exampleServerMain_LIBS += pvDatabase pvDatabaseExample pvAccess pvData Com
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
#----------------------------------------
|
||||
# ADD RULES AFTER THIS LINE
|
||||
|
57
example/exampleServer/exampleServerMain.cpp
Normal file
57
example/exampleServer/exampleServerMain.cpp
Normal file
@ -0,0 +1,57 @@
|
||||
/*exampleServerMain.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
*/
|
||||
|
||||
/* Author: Marty Kraimer */
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
#include <pv/channelProviderLocal.h>
|
||||
#include <pv/exampleServerCreateRecords.h>
|
||||
#include <pv/serverContext.h>
|
||||
|
||||
using namespace std;
|
||||
using std::tr1::static_pointer_cast;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::pvDatabase;
|
||||
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
PVDatabasePtr master = PVDatabase::getMaster();
|
||||
ChannelProviderLocalPtr channelProvider = getChannelProviderLocal();
|
||||
ExampleServerCreateRecords::create();
|
||||
ServerContext::shared_pointer ctx =
|
||||
startPVAServer(PVACCESS_ALL_PROVIDERS,0,true,true);
|
||||
cout << "exampleServer\n";
|
||||
PVStringArrayPtr pvNames = master->getRecordNames();
|
||||
String buffer;
|
||||
pvNames->toString(&buffer);
|
||||
cout << "recordNames" << endl << buffer << endl;
|
||||
string str;
|
||||
while(true) {
|
||||
cout << "Type exit to stop: \n";
|
||||
getline(cin,str);
|
||||
if(str.compare("exit")==0) break;
|
||||
|
||||
}
|
||||
ctx->destroy();
|
||||
epicsThreadSleep(1.0);
|
||||
channelProvider->destroy();
|
||||
return 0;
|
||||
}
|
||||
|
@ -194,16 +194,15 @@ static void testPVScalarArray(
|
||||
size_t offset;
|
||||
ConvertPtr convert = getConvert();
|
||||
size_t n = 5;
|
||||
DoubleArray values(n);
|
||||
// shared_vector<double> values(n);
|
||||
//DoubleArray values(n);
|
||||
shared_vector<double> values(n);
|
||||
|
||||
pvRecord->lock_guard();
|
||||
cout << endl;
|
||||
pvStructureRecord = pvRecord->getPVRecordStructure()->getPVStructure();
|
||||
pvValueRecord = pvStructureRecord->getScalarArrayField(valueNameRecord,scalarType);
|
||||
for(size_t i=0; i<n; i++) values[i] = i;
|
||||
convert->fromDoubleArray(pvValueRecord,0,n,get(values),0);
|
||||
// pvValueRecord->PVScalarArray::putFrom<pvDouble>(values);
|
||||
pvValueRecord->PVScalarArray::putFrom<pvDouble>(values);
|
||||
StructureConstPtr structure = pvCopy->getStructure();
|
||||
builder.clear(); structure->toString(&builder);
|
||||
cout << "structure from copy" << endl << builder << endl;
|
||||
@ -215,8 +214,7 @@ convert->fromDoubleArray(pvValueRecord,0,n,get(values),0);
|
||||
cout << "after initCopy pvValueCopy " << builder << endl;
|
||||
cout << endl;
|
||||
for(size_t i=0; i<n; i++) values[i] = i + .06;
|
||||
convert->fromDoubleArray(pvValueRecord,0,n,get(values),0);
|
||||
// pvValueRecord->PVScalarArray::putFrom<pvDouble>(values);
|
||||
pvValueRecord->PVScalarArray::putFrom<pvDouble>(values);
|
||||
pvCopy->updateCopySetBitSet(pvStructureCopy,bitSet,true);
|
||||
builder.clear(); pvValueCopy->toString(&builder);
|
||||
cout << "after put(i+ .06) pvValueCopy " << builder << endl;
|
||||
@ -235,8 +233,7 @@ convert->fromDoubleArray(pvValueRecord,0,n,get(values),0);
|
||||
cout << endl;
|
||||
bitSet->clear();
|
||||
for(size_t i=0; i<n; i++) values[i] = i + 1.0;
|
||||
convert->fromDoubleArray(pvValueRecord,0,n,get(values),0);
|
||||
// pvValueRecord->PVScalarArray::putFrom<pvDouble>(values);
|
||||
pvValueRecord->PVScalarArray::putFrom<pvDouble>(values);
|
||||
builder.clear();
|
||||
bitSet->toString(&builder);
|
||||
cout << "before updateCopyFromBitSet";
|
||||
@ -260,8 +257,7 @@ convert->fromDoubleArray(pvValueRecord,0,n,get(values),0);
|
||||
cout << " bitSet " << builder;
|
||||
cout << endl;
|
||||
for(size_t i=0; i<n; i++) values[i] = i + 2.0;
|
||||
convert->fromDoubleArray(pvValueRecord,0,n,get(values),0);
|
||||
// pvValueRecord->PVScalarArray::putFrom<pvDouble>(values);
|
||||
pvValueRecord->PVScalarArray::putFrom<pvDouble>(values);
|
||||
bitSet->set(0);
|
||||
cout << "before updateRecord";
|
||||
builder.clear(); pvValueRecord->toString(&builder);
|
19
example/src/Makefile
Normal file
19
example/src/Makefile
Normal file
@ -0,0 +1,19 @@
|
||||
TOP = ../..
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
EXAMPLESRC = $(TOP)/example/src/
|
||||
|
||||
LIBRARY_IOC += pvDatabaseExample
|
||||
pvDatabaseExample_LIBS += $(EPICS_BASE_IOC_LIBS)
|
||||
pvDatabaseExample_LIBS += Com pvData pvAccess pvDatabase
|
||||
|
||||
SRC_DIRS += $(EXAMPLESRC)/exampleCounter
|
||||
INC += exampleCounter.h
|
||||
|
||||
SRC_DIRS += $(EXAMPLESRC)/exampleServer
|
||||
INC+= exampleServerCreateRecords.h
|
||||
LIBSRCS += exampleServerCreateRecords.cpp
|
||||
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*testExampleRecordMain.cpp */
|
||||
/*exampleServerCreateRecords.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
@ -6,6 +6,7 @@
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
* @date 2013.07.24
|
||||
*/
|
||||
|
||||
/* Author: Marty Kraimer */
|
||||
@ -16,6 +17,7 @@
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
#include <pv/standardField.h>
|
||||
@ -25,7 +27,7 @@
|
||||
#include <pv/exampleCounter.h>
|
||||
#include <pv/recordList.h>
|
||||
#include <pv/traceRecord.h>
|
||||
#include <pv/serverContext.h>
|
||||
#include <pv/exampleServerCreateRecords.h>
|
||||
|
||||
using namespace std;
|
||||
using std::tr1::static_pointer_cast;
|
||||
@ -33,12 +35,13 @@ using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::pvDatabase;
|
||||
|
||||
static FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
static StandardFieldPtr standardField = getStandardField();
|
||||
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
static StandardPVFieldPtr standardPVField = getStandardPVField();
|
||||
|
||||
static PVStructurePtr createPowerSupply()
|
||||
{
|
||||
FieldCreatePtr fieldCreate = getFieldCreate();
|
||||
StandardFieldPtr standardField = getStandardField();
|
||||
PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
size_t nfields = 5;
|
||||
StringArray names;
|
||||
names.reserve(nfields);
|
||||
@ -59,11 +62,47 @@ static PVStructurePtr createPowerSupply()
|
||||
fieldCreate->createStructure(names,powerSupply));
|
||||
}
|
||||
|
||||
static void createStructureArrayRecord(
|
||||
PVDatabasePtr const &master,
|
||||
ScalarType scalarType,
|
||||
String const &recordName)
|
||||
{
|
||||
StructureConstPtr structure = standardField->scalar(
|
||||
pvDouble,
|
||||
String("value,alarm,timeStamp"));
|
||||
StringArray names(2);
|
||||
FieldConstPtrArray fields(2);
|
||||
names[0] = "timeStamp";
|
||||
names[1] = "value";
|
||||
fields[0] = standardField->timeStamp();
|
||||
fields[1] = fieldCreate->createStructureArray(structure);
|
||||
StructureConstPtr top = fieldCreate->createStructure(names,fields);
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(top);
|
||||
PVRecordPtr pvRecord = PVRecord::create(recordName,pvStructure);
|
||||
bool result = master->addRecord(pvRecord);
|
||||
if(!result) cout<< "record " << recordName << " not added" << endl;
|
||||
}
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
static void createRecords(
|
||||
PVDatabasePtr const &master,
|
||||
ScalarType scalarType,
|
||||
String const &recordNamePrefix,
|
||||
String const &properties)
|
||||
{
|
||||
String recordName = recordNamePrefix;
|
||||
PVStructurePtr pvStructure = standardPVField->scalar(scalarType,properties);
|
||||
PVRecordPtr pvRecord = PVRecord::create(recordName,pvStructure);
|
||||
bool result = master->addRecord(pvRecord);
|
||||
if(!result) cout<< "record " << recordName << " not added" << endl;
|
||||
recordName += "Array";
|
||||
pvStructure = standardPVField->scalarArray(scalarType,properties);
|
||||
pvRecord = PVRecord::create(recordName,pvStructure);
|
||||
result = master->addRecord(pvRecord);
|
||||
}
|
||||
|
||||
void ExampleServerCreateRecords::create()
|
||||
{
|
||||
PVDatabasePtr master = PVDatabase::getMaster();
|
||||
ChannelProviderLocalPtr channelProvider = getChannelProviderLocal();
|
||||
PVRecordPtr pvRecord;
|
||||
String recordName;
|
||||
bool result(false);
|
||||
@ -71,40 +110,27 @@ int main(int argc,char *argv[])
|
||||
pvRecord = TraceRecord::create(recordName);
|
||||
result = master->addRecord(pvRecord);
|
||||
if(!result) cout<< "record " << recordName << " not added" << endl;
|
||||
StandardPVFieldPtr standardPVField = getStandardPVField();
|
||||
String properties;
|
||||
ScalarType scalarType;
|
||||
recordName = "exampleCounter";
|
||||
pvRecord = ExampleCounter::create(recordName);
|
||||
result = master->addRecord(pvRecord);
|
||||
properties = "alarm,timeStamp";
|
||||
scalarType = pvDouble;
|
||||
recordName = "exampleDouble";
|
||||
PVStructurePtr pvStructure;
|
||||
pvStructure = standardPVField->scalar(scalarType,properties);
|
||||
pvRecord = PVRecord::create(recordName,pvStructure);
|
||||
{
|
||||
pvRecord->lock_guard();
|
||||
pvRecord->process();
|
||||
}
|
||||
result = master->addRecord(pvRecord);
|
||||
if(!result) cout<< "record " << recordName << " not added" << endl;
|
||||
recordName = "exampleDoubleArray";
|
||||
pvStructure = standardPVField->scalarArray(scalarType,properties);
|
||||
pvRecord = PVRecord::create(recordName,pvStructure);
|
||||
{
|
||||
pvRecord->lock_guard();
|
||||
pvRecord->process();
|
||||
}
|
||||
result = master->addRecord(pvRecord);
|
||||
if(!result) cout<< "record " << recordName << " not added" << endl;
|
||||
createRecords(master,pvBoolean,"exampleBoolean",properties);
|
||||
createRecords(master,pvByte,"exampleByte",properties);
|
||||
createRecords(master,pvShort,"exampleShort",properties);
|
||||
createRecords(master,pvInt,"exampleInt",properties);
|
||||
createRecords(master,pvLong,"exampleLong",properties);
|
||||
createRecords(master,pvFloat,"exampleFloat",properties);
|
||||
createRecords(master,pvDouble,"exampleDouble",properties);
|
||||
createRecords(master,pvString,"exampleString",properties);
|
||||
createStructureArrayRecord(master,pvDouble,"exampleStructureArray");
|
||||
recordName = "examplePowerSupply";
|
||||
pvStructure = createPowerSupply();
|
||||
PVStructurePtr pvStructure = createPowerSupply();
|
||||
PowerSupplyRecordTestPtr psr =
|
||||
PowerSupplyRecordTest::create(recordName,pvStructure);
|
||||
if(psr.get()==NULL) {
|
||||
cout << "PowerSupplyRecordTest::create failed" << endl;
|
||||
return 1;
|
||||
return;
|
||||
}
|
||||
result = master->addRecord(psr);
|
||||
if(!result) cout<< "record " << recordName << " not added" << endl;
|
||||
@ -112,23 +138,5 @@ int main(int argc,char *argv[])
|
||||
pvRecord = RecordListRecord::create(recordName);
|
||||
result = master->addRecord(pvRecord);
|
||||
if(!result) cout<< "record " << recordName << " not added" << endl;
|
||||
ServerContext::shared_pointer ctx =
|
||||
startPVAServer(PVACCESS_ALL_PROVIDERS,0,true,true);
|
||||
cout << "exampleServer\n";
|
||||
PVStringArrayPtr pvNames = master->getRecordNames();
|
||||
String buffer;
|
||||
pvNames->toString(&buffer);
|
||||
cout << "recordNames" << endl << buffer << endl;
|
||||
string str;
|
||||
while(true) {
|
||||
cout << "Type exit to stop: \n";
|
||||
getline(cin,str);
|
||||
if(str.compare("exit")==0) break;
|
||||
|
||||
}
|
||||
ctx->destroy();
|
||||
epicsThreadSleep(1.0);
|
||||
channelProvider->destroy();
|
||||
return 0;
|
||||
}
|
||||
|
27
example/src/exampleServer/exampleServerCreateRecords.h
Normal file
27
example/src/exampleServer/exampleServerCreateRecords.h
Normal file
@ -0,0 +1,27 @@
|
||||
/* exampleServerCreateRecords.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
* @date 2013.07.24
|
||||
*/
|
||||
#ifndef EXAMPLESERVERCREATERECORDS_H
|
||||
#define EXAMPLESERVERCREATERECORDS_H
|
||||
|
||||
|
||||
#include <pv/pvDatabase.h>
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
|
||||
class ExampleServerCreateRecords {
|
||||
public:
|
||||
static void create();
|
||||
};
|
||||
|
||||
|
||||
}}
|
||||
|
||||
#endif /* EXAMPLESERVERCREATERECORDS_H */
|
6
example/v3IOC/Makefile
Normal file
6
example/v3IOC/Makefile
Normal file
@ -0,0 +1,6 @@
|
||||
TOP = ../..
|
||||
include $(TOP)/configure/CONFIG
|
||||
DIRS += exampleCounter
|
||||
DIRS += exampleServer
|
||||
include $(TOP)/configure/RULES_DIRS
|
||||
|
21
example/v3IOC/exampleCounter/Db/Makefile
Normal file
21
example/v3IOC/exampleCounter/Db/Makefile
Normal file
@ -0,0 +1,21 @@
|
||||
TOP=../../../..
|
||||
include $(TOP)/configure/CONFIG
|
||||
#----------------------------------------
|
||||
# ADD MACRO DEFINITIONS AFTER THIS LINE
|
||||
|
||||
#----------------------------------------------------
|
||||
# Optimization of db files using dbst (DEFAULT: NO)
|
||||
#DB_OPT = YES
|
||||
|
||||
#----------------------------------------------------
|
||||
# Create and install (or just install)
|
||||
# databases, templates, substitutions like this
|
||||
DB += ai.db
|
||||
#----------------------------------------------------
|
||||
# If <anyname>.db template is not named <anyname>*.template add
|
||||
# <anyname>_TEMPLATE = <templatename>
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
#----------------------------------------
|
||||
# ADD RULES AFTER THIS LINE
|
||||
|
13
example/v3IOC/exampleCounter/Db/ai.db
Normal file
13
example/v3IOC/exampleCounter/Db/ai.db
Normal file
@ -0,0 +1,13 @@
|
||||
record(ai, "$(name)")
|
||||
{
|
||||
field(PREC, "1")
|
||||
field(EGU, "amps")
|
||||
field(HIHI, "8")
|
||||
field(HIGH, "6")
|
||||
field(LOW, "4")
|
||||
field(LOLO, "2")
|
||||
field(HHSV, "MAJOR")
|
||||
field(HSV, "MINOR")
|
||||
field(LSV, "MINOR")
|
||||
field(LLSV, "MAJOR")
|
||||
}
|
8
example/v3IOC/exampleCounter/Makefile
Normal file
8
example/v3IOC/exampleCounter/Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
TOP = ../../..
|
||||
include $(TOP)/configure/CONFIG
|
||||
DIRS := $(DIRS) $(filter-out $(DIRS), $(wildcard *src*))
|
||||
DIRS := $(DIRS) $(filter-out $(DIRS), $(wildcard *Src*))
|
||||
DIRS := $(DIRS) $(filter-out $(DIRS), $(wildcard *db*))
|
||||
DIRS := $(DIRS) $(filter-out $(DIRS), $(wildcard *Db*))
|
||||
include $(TOP)/configure/RULES_DIRS
|
||||
|
48
example/v3IOC/exampleCounter/src/Makefile
Normal file
48
example/v3IOC/exampleCounter/src/Makefile
Normal file
@ -0,0 +1,48 @@
|
||||
TOP=../../../..
|
||||
|
||||
include $(TOP)/configure/CONFIG
|
||||
#----------------------------------------
|
||||
# ADD MACRO DEFINITIONS AFTER THIS LINE
|
||||
#=============================
|
||||
|
||||
#==================================================
|
||||
# Build an IOC support library
|
||||
#
|
||||
|
||||
DBD += exampleCounter.dbd
|
||||
|
||||
LIBRARY_IOC += exampleCounterSupport
|
||||
exampleCounterSupport_SRCS += exampleCounter.cpp
|
||||
exampleCounterSupport_LIBS += pvData
|
||||
exampleCounterSupport_LIBS += pvAccess
|
||||
exampleCounterSupport_LIBS += pvDatabase
|
||||
exampleCounterSupport_LIBS += pvDatabaseExample
|
||||
exampleCounterSupport_LIBS += $(EPICS_BASE_IOC_LIBS)
|
||||
|
||||
#=============================
|
||||
# build an ioc application
|
||||
|
||||
PROD_IOC += exampleCounter
|
||||
|
||||
|
||||
# <name>_registerRecordDeviceDriver.cpp will be created from <name>.dbd
|
||||
exampleCounter_SRCS += exampleCounter_registerRecordDeviceDriver.cpp
|
||||
exampleCounter_SRCS_DEFAULT += exampleCounterMain.cpp
|
||||
exampleCounter_SRCS_vxWorks += -nil-
|
||||
|
||||
|
||||
# The following adds support from base/src/vxWorks
|
||||
exampleCounter_OBJS_vxWorks += $(EPICS_BASE_BIN)/vxComLibrary
|
||||
|
||||
exampleCounter_LIBS += pvData pvAccess
|
||||
exampleCounter_LIBS += pvDatabase
|
||||
exampleCounter_LIBS += pvDatabaseExample
|
||||
exampleCounter_LIBS += exampleCounterSupport
|
||||
exampleCounter_LIBS += $(EPICS_BASE_IOC_LIBS)
|
||||
|
||||
#===========================
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
#----------------------------------------
|
||||
# ADD RULES AFTER THIS LINE
|
||||
|
66
example/v3IOC/exampleCounter/src/exampleCounter.cpp
Normal file
66
example/v3IOC/exampleCounter/src/exampleCounter.cpp
Normal file
@ -0,0 +1,66 @@
|
||||
/*exampleCounter.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
* @date 2013.07.24
|
||||
*/
|
||||
|
||||
|
||||
/* Author: Marty Kraimer */
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
|
||||
#include <cantProceed.h>
|
||||
#include <epicsStdio.h>
|
||||
#include <epicsMutex.h>
|
||||
#include <epicsEvent.h>
|
||||
#include <epicsThread.h>
|
||||
#include <iocsh.h>
|
||||
|
||||
#include <epicsExport.h>
|
||||
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/pvAccess.h>
|
||||
#include <pv/pvDatabase.h>
|
||||
#include <pv/exampleCounter.h>
|
||||
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::pvDatabase;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
static const iocshArg testArg0 = { "recordName", iocshArgString };
|
||||
static const iocshArg *testArgs[] = {
|
||||
&testArg0};
|
||||
|
||||
static const iocshFuncDef exampleCounterFuncDef = {
|
||||
"exampleCounterCreateRecord", 1, testArgs};
|
||||
static void exampleCounterCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
char *recordName = args[0].sval;
|
||||
ExampleCounterPtr record = ExampleCounter::create(recordName);
|
||||
bool result = PVDatabase::getMaster()->addRecord(record);
|
||||
if(!result) cout << "recordname" << " not added" << endl;
|
||||
}
|
||||
|
||||
static void exampleCounterRegister(void)
|
||||
{
|
||||
static int firstTime = 1;
|
||||
if (firstTime) {
|
||||
firstTime = 0;
|
||||
iocshRegister(&exampleCounterFuncDef, exampleCounterCallFunc);
|
||||
}
|
||||
}
|
||||
epicsExportRegistrar(exampleCounterRegister);
|
@ -0,0 +1,3 @@
|
||||
include "base.dbd"
|
||||
include "PVAServerRegister.dbd"
|
||||
registrar("exampleCounterRegister")
|
31
example/v3IOC/exampleCounter/src/exampleCounterMain.cpp
Normal file
31
example/v3IOC/exampleCounter/src/exampleCounterMain.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
/* exampleCounterMain.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
* @date 2013.07.24
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "epicsExit.h"
|
||||
#include "epicsThread.h"
|
||||
#include "iocsh.h"
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
if(argc>=2) {
|
||||
iocsh(argv[1]);
|
||||
epicsThreadSleep(.2);
|
||||
}
|
||||
iocsh(NULL);
|
||||
epicsExit(0);
|
||||
return(0);
|
||||
}
|
28
example/v3IOC/exampleServer/Db/Makefile
Normal file
28
example/v3IOC/exampleServer/Db/Makefile
Normal file
@ -0,0 +1,28 @@
|
||||
TOP=../../../..
|
||||
include $(TOP)/configure/CONFIG
|
||||
#----------------------------------------
|
||||
# ADD MACRO DEFINITIONS AFTER THIS LINE
|
||||
|
||||
#----------------------------------------------------
|
||||
# Optimization of db files using dbst (DEFAULT: NO)
|
||||
#DB_OPT = YES
|
||||
|
||||
#----------------------------------------------------
|
||||
# Create and install (or just install)
|
||||
# databases, templates, substitutions like this
|
||||
DB += dbScalar.db
|
||||
DB += dbInteger.db
|
||||
DB += dbArray.db
|
||||
DB += dbString.db
|
||||
DB += dbStringArray.db
|
||||
DB += dbEnum.db
|
||||
DB += dbCounter.db
|
||||
|
||||
#----------------------------------------------------
|
||||
# If <anyname>.db template is not named <anyname>*.template add
|
||||
# <anyname>_TEMPLATE = <templatename>
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
#----------------------------------------
|
||||
# ADD RULES AFTER THIS LINE
|
||||
|
9
example/v3IOC/exampleServer/Db/dbArray.db
Normal file
9
example/v3IOC/exampleServer/Db/dbArray.db
Normal file
@ -0,0 +1,9 @@
|
||||
record(waveform, "$(name)")
|
||||
{
|
||||
field(NELM,"5")
|
||||
field(NORD,"5")
|
||||
field(FTVL,"$(type)")
|
||||
field(EGU, "Counts")
|
||||
field(HOPR, "10")
|
||||
field(LOPR, "0")
|
||||
}
|
20
example/v3IOC/exampleServer/Db/dbCounter.db
Normal file
20
example/v3IOC/exampleServer/Db/dbCounter.db
Normal file
@ -0,0 +1,20 @@
|
||||
record(calc, "${name}")
|
||||
{
|
||||
field(DESC, "Counter")
|
||||
field(SCAN,"1 second")
|
||||
field(CALC, "(A<B)?(A+C):D")
|
||||
field(INPA, "${name} NPP NMS")
|
||||
field(INPB, "9")
|
||||
field(INPC, "1")
|
||||
field(INPD, "0")
|
||||
field(EGU, "Counts")
|
||||
field(HOPR, "10")
|
||||
field(HIHI, "8")
|
||||
field(HIGH, "6")
|
||||
field(LOW, "4")
|
||||
field(LOLO, "2")
|
||||
field(HHSV, "MAJOR")
|
||||
field(HSV, "MINOR")
|
||||
field(LSV, "MINOR")
|
||||
field(LLSV, "MAJOR")
|
||||
}
|
14
example/v3IOC/exampleServer/Db/dbEnum.db
Normal file
14
example/v3IOC/exampleServer/Db/dbEnum.db
Normal file
@ -0,0 +1,14 @@
|
||||
record(mbbo, "$(name)")
|
||||
{
|
||||
field(NOBT,"2")
|
||||
field(ZRVL,"0")
|
||||
field(ONVL,"1")
|
||||
field(TWVL,"2")
|
||||
field(THVL,"3")
|
||||
field(ZRST,"zero")
|
||||
field(ONST,"one")
|
||||
field(TWST,"two")
|
||||
field(THST,"three")
|
||||
field(TWSV,"MINOR")
|
||||
field(THSV,"MAJOR")
|
||||
}
|
16
example/v3IOC/exampleServer/Db/dbInteger.db
Normal file
16
example/v3IOC/exampleServer/Db/dbInteger.db
Normal file
@ -0,0 +1,16 @@
|
||||
record($(type), "$(name)")
|
||||
{
|
||||
field(EGU, "Counts")
|
||||
field(HOPR, "10")
|
||||
field(LOPR, "0")
|
||||
field(DRVH, "9")
|
||||
field(DRVL, "0")
|
||||
field(HIHI, "8")
|
||||
field(HIGH, "6")
|
||||
field(LOW, "4")
|
||||
field(LOLO, "2")
|
||||
field(HHSV, "MAJOR")
|
||||
field(HSV, "MINOR")
|
||||
field(LSV, "MINOR")
|
||||
field(LLSV, "MAJOR")
|
||||
}
|
17
example/v3IOC/exampleServer/Db/dbScalar.db
Normal file
17
example/v3IOC/exampleServer/Db/dbScalar.db
Normal file
@ -0,0 +1,17 @@
|
||||
record($(type), "$(name)")
|
||||
{
|
||||
field(PREC, "1")
|
||||
field(EGU, "Counts")
|
||||
field(HOPR, "10")
|
||||
field(LOPR, "0")
|
||||
field(DRVH, "9.9")
|
||||
field(DRVL, "-0.1")
|
||||
field(HIHI, "8")
|
||||
field(HIGH, "6")
|
||||
field(LOW, "4")
|
||||
field(LOLO, "2")
|
||||
field(HHSV, "MAJOR")
|
||||
field(HSV, "MINOR")
|
||||
field(LSV, "MINOR")
|
||||
field(LLSV, "MAJOR")
|
||||
}
|
3
example/v3IOC/exampleServer/Db/dbString.db
Normal file
3
example/v3IOC/exampleServer/Db/dbString.db
Normal file
@ -0,0 +1,3 @@
|
||||
record(stringout, "$(name)")
|
||||
{
|
||||
}
|
5
example/v3IOC/exampleServer/Db/dbStringArray.db
Normal file
5
example/v3IOC/exampleServer/Db/dbStringArray.db
Normal file
@ -0,0 +1,5 @@
|
||||
record(waveform, "${name}")
|
||||
{
|
||||
field(NELM,"5")
|
||||
field(FTVL,"STRING")
|
||||
}
|
8
example/v3IOC/exampleServer/Makefile
Normal file
8
example/v3IOC/exampleServer/Makefile
Normal file
@ -0,0 +1,8 @@
|
||||
TOP = ../../..
|
||||
include $(TOP)/configure/CONFIG
|
||||
DIRS := $(DIRS) $(filter-out $(DIRS), $(wildcard *src*))
|
||||
DIRS := $(DIRS) $(filter-out $(DIRS), $(wildcard *Src*))
|
||||
DIRS := $(DIRS) $(filter-out $(DIRS), $(wildcard *db*))
|
||||
DIRS := $(DIRS) $(filter-out $(DIRS), $(wildcard *Db*))
|
||||
include $(TOP)/configure/RULES_DIRS
|
||||
|
48
example/v3IOC/exampleServer/src/Makefile
Normal file
48
example/v3IOC/exampleServer/src/Makefile
Normal file
@ -0,0 +1,48 @@
|
||||
TOP=../../../..
|
||||
|
||||
include $(TOP)/configure/CONFIG
|
||||
#----------------------------------------
|
||||
# ADD MACRO DEFINITIONS AFTER THIS LINE
|
||||
#=============================
|
||||
|
||||
#==================================================
|
||||
# Build an IOC support library
|
||||
#
|
||||
|
||||
DBD += exampleServer.dbd
|
||||
|
||||
LIBRARY_IOC += exampleServerSupport
|
||||
exampleServerSupport_SRCS += exampleServer.cpp
|
||||
exampleServerSupport_LIBS += pvData
|
||||
exampleServerSupport_LIBS += pvAccess
|
||||
exampleServerSupport_LIBS += pvDatabase
|
||||
exampleServerSupport_LIBS += pvDatabaseExample
|
||||
exampleServerSupport_LIBS += $(EPICS_BASE_IOC_LIBS)
|
||||
|
||||
#=============================
|
||||
# build an ioc application
|
||||
|
||||
PROD_IOC += exampleServer
|
||||
|
||||
|
||||
# <name>_registerRecordDeviceDriver.cpp will be created from <name>.dbd
|
||||
exampleServer_SRCS += exampleServer_registerRecordDeviceDriver.cpp
|
||||
exampleServer_SRCS_DEFAULT += exampleServerMain.cpp
|
||||
exampleServer_SRCS_vxWorks += -nil-
|
||||
|
||||
|
||||
# The following adds support from base/src/vxWorks
|
||||
exampleServer_OBJS_vxWorks += $(EPICS_BASE_BIN)/vxComLibrary
|
||||
|
||||
exampleServer_LIBS += pvData pvAccess
|
||||
exampleServer_LIBS += pvDatabase
|
||||
exampleServer_LIBS += pvDatabaseExample
|
||||
exampleServer_LIBS += exampleServerSupport
|
||||
exampleServer_LIBS += $(EPICS_BASE_IOC_LIBS)
|
||||
|
||||
#===========================
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
#----------------------------------------
|
||||
# ADD RULES AFTER THIS LINE
|
||||
|
61
example/v3IOC/exampleServer/src/exampleServer.cpp
Normal file
61
example/v3IOC/exampleServer/src/exampleServer.cpp
Normal file
@ -0,0 +1,61 @@
|
||||
/*exampleServer.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
* @date 2013.07.24
|
||||
*/
|
||||
|
||||
|
||||
/* Author: Marty Kraimer */
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
|
||||
#include <cantProceed.h>
|
||||
#include <epicsStdio.h>
|
||||
#include <epicsMutex.h>
|
||||
#include <epicsEvent.h>
|
||||
#include <epicsThread.h>
|
||||
#include <iocsh.h>
|
||||
|
||||
#include <epicsExport.h>
|
||||
|
||||
#include <pv/pvIntrospect.h>
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/pvAccess.h>
|
||||
#include <pv/pvDatabase.h>
|
||||
#include <pv/exampleServerCreateRecords.h>
|
||||
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::pvDatabase;
|
||||
|
||||
static const iocshArg testArg0 = { "prefix", iocshArgString };
|
||||
static const iocshArg *testArgs[] = {
|
||||
&testArg0};
|
||||
|
||||
static const iocshFuncDef exampleServerFuncDef = {
|
||||
"exampleServerCreateRecords", 1, testArgs};
|
||||
static void exampleServerCallFunc(const iocshArgBuf *args)
|
||||
{
|
||||
char *prefix = args[0].sval;
|
||||
ExampleServerCreateRecords::create();
|
||||
}
|
||||
|
||||
static void exampleServerRegister(void)
|
||||
{
|
||||
static int firstTime = 1;
|
||||
if (firstTime) {
|
||||
firstTime = 0;
|
||||
iocshRegister(&exampleServerFuncDef, exampleServerCallFunc);
|
||||
}
|
||||
}
|
||||
epicsExportRegistrar(exampleServerRegister);
|
3
example/v3IOC/exampleServer/src/exampleServerInclude.dbd
Normal file
3
example/v3IOC/exampleServer/src/exampleServerInclude.dbd
Normal file
@ -0,0 +1,3 @@
|
||||
include "base.dbd"
|
||||
include "PVAServerRegister.dbd"
|
||||
registrar("exampleServerRegister")
|
31
example/v3IOC/exampleServer/src/exampleServerMain.cpp
Normal file
31
example/v3IOC/exampleServer/src/exampleServerMain.cpp
Normal file
@ -0,0 +1,31 @@
|
||||
/* exampleServerMain.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
* @date 2013.07.24
|
||||
*/
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "epicsExit.h"
|
||||
#include "epicsThread.h"
|
||||
#include "iocsh.h"
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
if(argc>=2) {
|
||||
iocsh(argv[1]);
|
||||
epicsThreadSleep(.2);
|
||||
}
|
||||
iocsh(NULL);
|
||||
epicsExit(0);
|
||||
return(0);
|
||||
}
|
7
iocBoot/Makefile
Normal file
7
iocBoot/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
TOP = ..
|
||||
include $(TOP)/configure/CONFIG
|
||||
DIRS += $(wildcard *ioc*)
|
||||
DIRS += $(wildcard as*)
|
||||
DIRS += $(wildcard example*)
|
||||
include $(EPICS_BASE)/configure/RULES_DIRS
|
||||
|
5
iocBoot/exampleCounter/Makefile
Normal file
5
iocBoot/exampleCounter/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
TOP = ../..
|
||||
include $(TOP)/configure/CONFIG
|
||||
ARCH = $(EPICS_HOST_ARCH)
|
||||
TARGETS = envPaths
|
||||
include $(TOP)/configure/RULES.ioc
|
17
iocBoot/exampleCounter/st.cmd
Normal file
17
iocBoot/exampleCounter/st.cmd
Normal file
@ -0,0 +1,17 @@
|
||||
< envPaths
|
||||
|
||||
cd ${TOP}
|
||||
|
||||
## Register all support components
|
||||
dbLoadDatabase("dbd/exampleCounter.dbd")
|
||||
exampleCounter_registerRecordDeviceDriver(pdbbase)
|
||||
|
||||
## Load record instances
|
||||
dbLoadRecords("db/ai.db","name=double01")
|
||||
|
||||
cd ${TOP}/iocBoot/${IOC}
|
||||
iocInit()
|
||||
epicsThreadSleep(2.0)
|
||||
casr
|
||||
exampleCounterCreateRecord exampleCounter
|
||||
startPVAServer
|
5
iocBoot/exampleServer/Makefile
Normal file
5
iocBoot/exampleServer/Makefile
Normal file
@ -0,0 +1,5 @@
|
||||
TOP = ../..
|
||||
include $(TOP)/configure/CONFIG
|
||||
ARCH = $(EPICS_HOST_ARCH)
|
||||
TARGETS = envPaths
|
||||
include $(TOP)/configure/RULES.ioc
|
20
iocBoot/exampleServer/st.cmd
Normal file
20
iocBoot/exampleServer/st.cmd
Normal file
@ -0,0 +1,20 @@
|
||||
< envPaths
|
||||
|
||||
cd ${TOP}
|
||||
|
||||
## Register all support components
|
||||
dbLoadDatabase("dbd/exampleServer.dbd")
|
||||
exampleServer_registerRecordDeviceDriver(pdbbase)
|
||||
|
||||
## Load record instances
|
||||
dbLoadRecords("db/dbScalar.db","name=double01,type=ao")
|
||||
dbLoadRecords("db/dbStringArray.db","name=stringArray01")
|
||||
dbLoadRecords("db/dbEnum.db","name=enum01")
|
||||
dbLoadRecords("db/dbCounter.db","name=counter01");
|
||||
|
||||
cd ${TOP}/iocBoot/${IOC}
|
||||
iocInit()
|
||||
epicsThreadSleep(2.0)
|
||||
casr
|
||||
exampleServerCreateRecords
|
||||
startPVAServer
|
14
src/Makefile
14
src/Makefile
@ -7,6 +7,10 @@ LIBRARY_IOC += pvDatabase
|
||||
pvDatabase_LIBS += $(EPICS_BASE_IOC_LIBS)
|
||||
pvDatabase_LIBS += Com pvData pvAccess
|
||||
|
||||
SRC_DIRS += $(DATABASE)/pvData
|
||||
INC += pvSubArrayCopy.h
|
||||
LIBSRCS += pvSubArrayCopy.cpp
|
||||
|
||||
SRC_DIRS += $(DATABASE)/database
|
||||
INC += pvDatabase.h
|
||||
LIBSRCS += pvRecord.cpp
|
||||
@ -17,10 +21,14 @@ INC += channelProviderLocal.h
|
||||
INC += pvCopy.h
|
||||
INC += monitorAlgorithm.h
|
||||
LIBSRCS += channelProviderLocal.cpp
|
||||
LIBSRCS += channelLocal.cpp
|
||||
LIBSRCS += pvCopy.cpp
|
||||
LIBSRCS += channelLocal.cpp
|
||||
LIBSRCS += monitorFactory.cpp
|
||||
|
||||
SRC_DIRS += $(DATABASE)/v3IOC
|
||||
DBD += PVAServerRegister.dbd
|
||||
LIBSRCS += PVAServerRegister.cpp
|
||||
|
||||
SRC_DIRS += $(DATABASE)/special
|
||||
INC += recordList.h
|
||||
INC += traceRecord.h
|
||||
@ -28,9 +36,5 @@ INC += powerSupplyRecordTest.h
|
||||
LIBSRCS += recordList.cpp
|
||||
LIBSRCS += traceRecord.cpp
|
||||
|
||||
SRC_DIRS += $(DATABASE)/example
|
||||
INC += exampleCounter.h
|
||||
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
* @data 2012.11.21
|
||||
* @date 2012.11.21
|
||||
*/
|
||||
|
||||
#include <pv/pvDatabase.h>
|
||||
@ -85,13 +85,13 @@ PVStringArrayPtr PVDatabase::getRecordNames()
|
||||
PVStringArrayPtr pvStringArray = static_pointer_cast<PVStringArray>
|
||||
(getPVDataCreate()->createPVScalarArray(pvString));
|
||||
size_t len = recordMap.size();
|
||||
std::vector<String> names(len);
|
||||
shared_vector<String> names(len);
|
||||
PVRecordMap::iterator iter;
|
||||
size_t i = 0;
|
||||
for(iter = recordMap.begin(); iter!=recordMap.end(); ++iter) {
|
||||
names[i++] = (*iter).first;
|
||||
}
|
||||
pvStringArray->put(0,len,names,0);
|
||||
pvStringArray->replace(names);
|
||||
return pvStringArray;
|
||||
}
|
||||
|
||||
|
@ -6,7 +6,7 @@
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
* @data 2012.11.21
|
||||
* @date 2012.11.21
|
||||
*/
|
||||
|
||||
#include <pv/pvDatabase.h>
|
||||
|
@ -15,11 +15,13 @@
|
||||
|
||||
#include <pv/channelProviderLocal.h>
|
||||
#include <pv/convert.h>
|
||||
#include <pv/pvSubArrayCopy.h>
|
||||
|
||||
namespace epics { namespace pvDatabase {
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::tr1::dynamic_pointer_cast;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
@ -759,6 +761,8 @@ void ChannelPutGetLocal::getGet()
|
||||
}
|
||||
}
|
||||
|
||||
typedef std::tr1::shared_ptr<PVArray> PVArrayPtr;
|
||||
|
||||
class ChannelArrayLocal :
|
||||
public ChannelArray,
|
||||
public std::tr1::enable_shared_from_this<ChannelArrayLocal>
|
||||
@ -791,8 +795,8 @@ private:
|
||||
ChannelArrayLocal(
|
||||
ChannelLocalPtr const &channelLocal,
|
||||
ChannelArrayRequester::shared_pointer const & channelArrayRequester,
|
||||
PVScalarArrayPtr const &pvArray,
|
||||
PVScalarArrayPtr const &pvCopy,
|
||||
PVArrayPtr const &pvArray,
|
||||
PVArrayPtr const &pvCopy,
|
||||
PVRecordPtr const &pvRecord)
|
||||
:
|
||||
isDestroyed(false),
|
||||
@ -810,13 +814,14 @@ private:
|
||||
bool callProcess;
|
||||
ChannelLocalPtr channelLocal;
|
||||
ChannelArrayRequester::shared_pointer channelArrayRequester,;
|
||||
PVScalarArrayPtr pvArray;
|
||||
PVScalarArrayPtr pvCopy;
|
||||
PVArrayPtr pvArray;
|
||||
PVArrayPtr pvCopy;
|
||||
PVRecordPtr pvRecord;
|
||||
Mutex mutex;
|
||||
Lock thelock;
|
||||
};
|
||||
|
||||
|
||||
ChannelArrayLocalPtr ChannelArrayLocal::create(
|
||||
ChannelLocalPtr const &channelLocal,
|
||||
ChannelArrayRequester::shared_pointer const & channelArrayRequester,
|
||||
@ -852,18 +857,26 @@ ChannelArrayLocalPtr ChannelArrayLocal::create(
|
||||
channelArrayRequester->channelArrayConnect(status,channelArray,pvArray);
|
||||
return channelArray;
|
||||
}
|
||||
if(pvField->getField()->getType()!=scalarArray)
|
||||
if(pvField->getField()->getType()!=scalarArray && pvField->getField()->getType()!=structureArray)
|
||||
{
|
||||
Status status(
|
||||
Status::Status::STATUSTYPE_ERROR,fieldName +" not scalarArray");
|
||||
Status::Status::STATUSTYPE_ERROR,fieldName +" not array");
|
||||
ChannelArrayLocalPtr channelArray;
|
||||
PVScalarArrayPtr pvArray;
|
||||
PVArrayPtr pvArray;
|
||||
channelArrayRequester->channelArrayConnect(status,channelArray,pvArray);
|
||||
return channelArray;
|
||||
}
|
||||
PVScalarArrayPtr pvArray = static_pointer_cast<PVScalarArray>(pvField);
|
||||
PVScalarArrayPtr pvCopy = getPVDataCreate()->createPVScalarArray(
|
||||
pvArray->getScalarArray()->getElementType());
|
||||
PVArrayPtr pvArray = static_pointer_cast<PVArray>(pvField);
|
||||
PVArrayPtr pvCopy;
|
||||
if(pvField->getField()->getType()==scalarArray) {
|
||||
PVScalarArrayPtr xxx = static_pointer_cast<PVScalarArray>(pvField);
|
||||
pvCopy = getPVDataCreate()->createPVScalarArray(
|
||||
xxx->getScalarArray()->getElementType());
|
||||
} else {
|
||||
PVStructureArrayPtr xxx = static_pointer_cast<PVStructureArray>(pvField);
|
||||
pvCopy = getPVDataCreate()->createPVStructureArray(
|
||||
xxx->getStructureArray());
|
||||
}
|
||||
|
||||
ChannelArrayLocalPtr array(new ChannelArrayLocal(
|
||||
channelLocal,
|
||||
@ -913,8 +926,13 @@ void ChannelArrayLocal::getArray(bool lastRequest,int offset, int count)
|
||||
}
|
||||
pvRecord->lock();
|
||||
try {
|
||||
size_t len = getConvert()->copyScalarArray(pvArray,offset,pvCopy,0,count);
|
||||
if(!pvCopy->isImmutable()) pvCopy->setLength(len);
|
||||
if(count<0) count = pvArray->getLength();
|
||||
size_t capacity = pvArray->getCapacity();
|
||||
if(capacity!=0) {
|
||||
pvCopy->setCapacity(capacity);
|
||||
pvCopy->setLength(count);
|
||||
copy(*pvArray.get(),offset,*pvCopy.get(),0,count);
|
||||
}
|
||||
} catch(...) {
|
||||
pvRecord->unlock();
|
||||
throw;
|
||||
@ -937,10 +955,12 @@ void ChannelArrayLocal::putArray(bool lastRequest,int offset, int count)
|
||||
{
|
||||
cout << "ChannelArrayLocal::putArray" << endl;
|
||||
}
|
||||
if(count<=0) count = pvCopy->getLength();
|
||||
pvRecord->lock();
|
||||
try {
|
||||
getConvert()->copyScalarArray(pvCopy,0,pvArray,offset,count);
|
||||
if(count<=0) count = pvCopy->getLength();
|
||||
if(pvArray->getCapacity()<count) pvArray->setCapacity(count);
|
||||
if(pvArray->getLength()<count) pvArray->setLength(count);
|
||||
copy(*pvCopy.get(),0,*pvArray.get(),offset,count);
|
||||
} catch(...) {
|
||||
pvRecord->unlock();
|
||||
throw;
|
||||
@ -964,21 +984,22 @@ void ChannelArrayLocal::setLength(bool lastRequest,int length, int capacity)
|
||||
{
|
||||
cout << "ChannelArrayLocal::setLength" << endl;
|
||||
}
|
||||
if(capacity>=0 && !pvArray->isCapacityMutable()) {
|
||||
Status status(
|
||||
Status::Status::STATUSTYPE_ERROR,
|
||||
"capacityImnutable");
|
||||
channelArrayRequester->setLengthDone(status);
|
||||
return;
|
||||
}
|
||||
pvRecord->lock();
|
||||
try {
|
||||
if(length>0) {
|
||||
if(pvArray->getLength()!=length) pvArray->setLength(length);
|
||||
if(capacity>=0 && !pvArray->isCapacityMutable()) {
|
||||
Status status(
|
||||
Status::Status::STATUSTYPE_ERROR,
|
||||
"capacityImnutable");
|
||||
channelArrayRequester->setLengthDone(status);
|
||||
pvRecord->unlock();
|
||||
return;
|
||||
}
|
||||
if(capacity>0) {
|
||||
if(pvArray->getCapacity()!=capacity) pvArray->setCapacity(capacity);
|
||||
}
|
||||
if(length>0) {
|
||||
if(pvArray->getLength()!=length) pvArray->setLength(length);
|
||||
}
|
||||
} catch(...) {
|
||||
pvRecord->unlock();
|
||||
throw;
|
||||
|
@ -6,7 +6,7 @@
|
||||
*/
|
||||
/**
|
||||
* @author Marty Kraimer
|
||||
* @data 2013.04
|
||||
* @date 2013.04
|
||||
*/
|
||||
#ifndef CHANNELPROVIDERLOCAL_H
|
||||
#define CHANNELPROVIDERLOCAL_H
|
||||
|
@ -6,7 +6,7 @@
|
||||
*/
|
||||
/**
|
||||
* @author Marty Kraimer
|
||||
* @data 2013.04
|
||||
* @date 2013.04
|
||||
*/
|
||||
#ifndef MONITORALGORITHM_H
|
||||
#define MONITORALGORITHM_H
|
||||
|
@ -20,6 +20,7 @@ namespace epics { namespace pvDatabase {
|
||||
|
||||
using namespace epics::pvData;
|
||||
using std::tr1::static_pointer_cast;
|
||||
using std::tr1::dynamic_pointer_cast;
|
||||
using std::size_t;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
@ -35,13 +36,11 @@ struct CopyNode {
|
||||
CopyNode()
|
||||
: isStructure(false),
|
||||
structureOffset(0),
|
||||
nfields(0),
|
||||
shareData(false)
|
||||
nfields(0)
|
||||
{}
|
||||
bool isStructure;
|
||||
size_t structureOffset; // In the copy
|
||||
size_t nfields;
|
||||
bool shareData;
|
||||
PVStructurePtr options;
|
||||
};
|
||||
|
||||
@ -734,23 +733,7 @@ void PVCopy::referenceImmutable(
|
||||
CopyRecordNodePtr recordNode =
|
||||
static_pointer_cast<CopyRecordNode>(node);
|
||||
PVRecordFieldPtr recordPVField = recordNode->recordPVField;
|
||||
bool shareData = false;
|
||||
if(node->options.get()!=NULL) {
|
||||
PVFieldPtr pv = node->options->getSubField("_options");
|
||||
if(pv.get()!=NULL) {
|
||||
PVStructurePtr xxx = static_pointer_cast<PVStructure>(pv);
|
||||
pv = xxx->getSubField("shareData");
|
||||
if(pv.get()!=NULL) {
|
||||
PVStringPtr yyy = xxx->getStringField("shareData");
|
||||
shareData = (yyy->get().compare("true")==0) ? true : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(shareData) {
|
||||
makeShared(pvField,recordNode->recordPVField);
|
||||
} else {
|
||||
referenceImmutable(pvField,recordPVField);
|
||||
}
|
||||
referenceImmutable(pvField,recordPVField);
|
||||
}
|
||||
}
|
||||
|
||||
@ -780,13 +763,6 @@ void PVCopy::referenceImmutable(
|
||||
}
|
||||
}
|
||||
|
||||
void PVCopy::makeShared(
|
||||
PVFieldPtr const ©PVField,
|
||||
PVRecordFieldPtr const &recordPVField)
|
||||
{
|
||||
throw std::logic_error(String("Not Implemented"));
|
||||
}
|
||||
|
||||
void PVCopy::updateStructureNodeSetBitSet(
|
||||
PVStructurePtr const &pvCopy,
|
||||
CopyStructureNodePtr const &structureNode,
|
||||
@ -803,24 +779,7 @@ void PVCopy::updateStructureNodeSetBitSet(
|
||||
} else {
|
||||
CopyRecordNodePtr recordNode =
|
||||
static_pointer_cast<CopyRecordNode>(node);
|
||||
bool shareData = false;
|
||||
if(node->options.get()!=NULL) {
|
||||
PVFieldPtr pv = node->options->getSubField("_options");
|
||||
if(pv.get()!=NULL) {
|
||||
PVStructurePtr xxx =
|
||||
static_pointer_cast<PVStructure>(pv);
|
||||
pv = xxx->getSubField("shareData");
|
||||
if(pv.get()!=NULL) {
|
||||
PVStringPtr yyy = xxx->getStringField("shareData");
|
||||
shareData = (yyy->get().compare("true")==0) ? true : false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(shareData) {
|
||||
bitSet->set(pvField->getFieldOffset());
|
||||
} else {
|
||||
updateSubFieldSetBitSet(pvField,recordNode->recordPVField,bitSet);
|
||||
}
|
||||
updateSubFieldSetBitSet(pvField,recordNode->recordPVField,bitSet);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,10 +25,6 @@ class PVCopyMonitor;
|
||||
typedef std::tr1::shared_ptr<PVCopyMonitor> PVCopyMonitorPtr;
|
||||
class PVCopyMonitorRequester;
|
||||
typedef std::tr1::shared_ptr<PVCopyMonitorRequester> PVCopyMonitorRequesterPtr;
|
||||
class SharePVScalarArray;
|
||||
typedef std::tr1::shared_ptr<SharePVScalarArray> SharePVScalarArrayPtr;
|
||||
class SharePVStructureArray;
|
||||
typedef std::tr1::shared_ptr<SharePVStructureArray> SharePVStructureArrayPtr;
|
||||
|
||||
struct CopyNode;
|
||||
typedef std::tr1::shared_ptr<CopyNode> CopyNodePtr;
|
||||
@ -125,9 +121,6 @@ private:
|
||||
void referenceImmutable(
|
||||
epics::pvData::PVFieldPtr const ©PVField,
|
||||
PVRecordFieldPtr const &recordPVField);
|
||||
void makeShared(
|
||||
epics::pvData::PVFieldPtr const ©PVField,
|
||||
PVRecordFieldPtr const &recordPVField);
|
||||
void updateStructureNodeSetBitSet(
|
||||
epics::pvData::PVStructurePtr const &pvCopy,
|
||||
CopyStructureNodePtr const &structureNode,
|
||||
@ -217,113 +210,6 @@ public:
|
||||
virtual void unlisten() = 0;
|
||||
};
|
||||
|
||||
|
||||
#ifdef MUSTIMPLEMENT
|
||||
template<typename T>
|
||||
class SharePVScalarArray :
|
||||
public epics::pvData::PVScalarArray
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(SharePVScalarArray)
|
||||
typedef T value_type;
|
||||
typedef T* pointer;
|
||||
typedef const T* const_pointer;
|
||||
typedef epics::pvData::PVArrayData<T> ArrayDataType;
|
||||
|
||||
SharePVScalarArray(
|
||||
PVRecordFieldPtr const &pvRecordField,
|
||||
epics::pvData::PVStructurePtr const &parent,
|
||||
epics::pvData::PVScalarArrayPtr const &pvShare);
|
||||
virtual ~SharePVScalarArray();
|
||||
void lockShare() const;
|
||||
void unlockShare() const;
|
||||
virtual void message(
|
||||
epics::pvData::String const & message,
|
||||
epics::pvData::MessageType messageType);
|
||||
virtual void setImmutable();
|
||||
bool isImmutable();
|
||||
virtual void setCapacity(std::size_t capacity);
|
||||
void setLength(std::size_t length);
|
||||
std::size_t getCapacity() const;
|
||||
std::size_t getLength() const;
|
||||
bool isCapacityMutable();
|
||||
void setCapacityMutable(bool isMutable);
|
||||
virtual std::size_t get(std::size_t offset, std::size_t length, ArrayDataType &data) = 0;
|
||||
virtual std::size_t put(std::size_t offset,std::size_t length, pointer from, std::size_t fromOffset) = 0;
|
||||
virtual void shareData(pointer value,std::size_t capacity,std::size_t length) = 0;
|
||||
virtual bool equals(epics::pvData::PVFieldPtr const &pv);
|
||||
virtual void serialize(
|
||||
epics::pvData::ByteBufferPtr *pbuffer,
|
||||
epics::pvData::SerializableControl *pflusher) const;
|
||||
virtual void deserialize(
|
||||
epics::pvData::ByteBuffer *pbuffer,
|
||||
epics::pvData::DeserializableControl *pflusher);
|
||||
virtual void serialize(
|
||||
epics::pvData::ByteBuffer *pbuffer,
|
||||
epics::pvData::SerializableControl *pflusher, std::size_t offset, std::size_t count) const;
|
||||
private:
|
||||
PVRecordField &pvRecordField;
|
||||
};
|
||||
|
||||
typedef SharePVScalarArray<bool> SharePVBooleanArray;
|
||||
typedef SharePVScalarArray<epics::pvData::int8> SharePVByteArray;
|
||||
typedef SharePVScalarArray<epics::pvData::int16> SharePVShortArray;
|
||||
typedef SharePVScalarArray<epics::pvData::int32> SharePVIntArray;
|
||||
typedef SharePVScalarArray<epics::pvData::int64> SharePVLongArray;
|
||||
typedef SharePVScalarArray<float> SharePVFloatArray;
|
||||
typedef SharePVScalarArray<double> SharePVDoubleArray;
|
||||
typedef SharePVScalarArray<epics::pvData::String> SharePVStringArray;
|
||||
|
||||
|
||||
class SharePVStructureArray :
|
||||
public epics::pvData::PVStructureArray
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(SharePVStructureArray)
|
||||
SharePVStructureArray(
|
||||
PVRecordFieldPtr const &pvRecordField,
|
||||
epics::pvData::PVStructurePtr const &parent,
|
||||
epics::pvData::PVStructureArrayPtr const &pvShare);
|
||||
virtual ~SharePVStructureArray();
|
||||
virtual epics::pvData::StructureArrayConstPtr getStructureArray();
|
||||
void lockShare() const;
|
||||
void unlockShare() const;
|
||||
virtual void message(
|
||||
epics::pvData::String const &message,
|
||||
epics::pvData::MessageType messageType);
|
||||
virtual void setImmutable();
|
||||
bool isImmutable();
|
||||
virtual void setCapacity(std::size_t capacity);
|
||||
void setLength(std::size_t length);
|
||||
std::size_t getCapacity() const;
|
||||
std::size_t getLength() const;
|
||||
bool isCapacityMutable();
|
||||
void setCapacityMutable(bool isMutable);
|
||||
virtual void shareData(
|
||||
epics::pvData::PVStructurePtrArrayPtr const & value,
|
||||
std::size_t capacity,std::size_t length);
|
||||
virtual std::size_t get(std::size_t offset, std::size_t length,
|
||||
epics::pvData::StructureArrayData &data);
|
||||
virtual std::size_t put(std::size_t offset,std::size_t length,
|
||||
epics::pvData::PVStructurePtrArrayPtr const & from,
|
||||
std::size_t fromOffset);
|
||||
virtual bool equals(epics::pvData::PVField & &pv);
|
||||
virtual void serialize(
|
||||
epics::pvData::ByteBuffer *pbuffer,
|
||||
epics::pvData::SerializableControl *pflusher) const;
|
||||
virtual void deserialize(
|
||||
epics::pvData::ByteBuffer *pbuffer,
|
||||
epics::pvData::DeserializableControl *pflusher);
|
||||
virtual void serialize(
|
||||
epics::pvData::ByteBuffer *pbuffer,
|
||||
epics::pvData::SerializableControl *pflusher,
|
||||
std::size_t offset, std::size_t count) const;
|
||||
private:
|
||||
PVRecordField &pvRecordField;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
}}
|
||||
|
||||
#endif /* PVCOPY_H */
|
||||
|
201
src/pvData/pvSubArrayCopy.cpp
Normal file
201
src/pvData/pvSubArrayCopy.cpp
Normal file
@ -0,0 +1,201 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author Marty Kraimer
|
||||
* @date 2013.07
|
||||
*/
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <memory>
|
||||
|
||||
#include <pv/pvSubArrayCopy.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
template<typename T>
|
||||
void copy(
|
||||
PVValueArray<T> & pvFrom,
|
||||
size_t fromOffset,
|
||||
PVValueArray<T> & pvTo,
|
||||
size_t toOffset,
|
||||
size_t len)
|
||||
{
|
||||
if(pvTo.isImmutable()) {
|
||||
throw std::logic_error("pvSubArrayCopy to is immutable");
|
||||
}
|
||||
size_t fromLength = pvFrom.getLength();
|
||||
if(fromOffset+len>fromLength) {
|
||||
throw std::length_error("pvSubArrayCopy from length error");
|
||||
}
|
||||
size_t capacity = pvTo.getCapacity();
|
||||
if(toOffset+len>capacity) pvTo.setCapacity(toOffset+len);
|
||||
typename PVValueArray<T>::const_svector vecFrom = pvFrom.view();
|
||||
typename PVValueArray<T>::const_svector vecTo = pvTo.view();
|
||||
shared_vector<T> temp;
|
||||
pvTo.swap(temp);
|
||||
for(size_t i=0; i<len; ++i) temp[i + toOffset] = vecFrom[i + fromOffset];
|
||||
pvTo.replace(temp);
|
||||
}
|
||||
|
||||
void copy(
|
||||
PVScalarArray & from,
|
||||
size_t fromOffset,
|
||||
PVScalarArray & to,
|
||||
size_t toOffset,
|
||||
size_t len)
|
||||
{
|
||||
ScalarType scalarType = from.getScalarArray()->getElementType();
|
||||
ScalarType otherType = to.getScalarArray()->getElementType();
|
||||
if(scalarType!=otherType) {
|
||||
throw std::invalid_argument("pvSubArrayCopy element types do not match");
|
||||
}
|
||||
switch(scalarType)
|
||||
{
|
||||
case pvBoolean:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<boolean> &>(from),fromOffset,
|
||||
dynamic_cast<PVValueArray<boolean>& >(to),
|
||||
toOffset,len);
|
||||
}
|
||||
break;
|
||||
case pvByte:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<int8> &>(from),fromOffset,
|
||||
dynamic_cast<PVValueArray<int8>& >(to),
|
||||
toOffset,len);
|
||||
}
|
||||
break;
|
||||
case pvShort:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<int16> &>(from),fromOffset,
|
||||
dynamic_cast<PVValueArray<int16>& >(to),
|
||||
toOffset,len);
|
||||
}
|
||||
break;
|
||||
case pvInt:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<int32> &>(from),fromOffset,
|
||||
dynamic_cast<PVValueArray<int32>& >(to),
|
||||
toOffset,len);
|
||||
}
|
||||
break;
|
||||
case pvLong:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<int64> &>(from),fromOffset,
|
||||
dynamic_cast<PVValueArray<int64>& >(to),
|
||||
toOffset,len);
|
||||
}
|
||||
break;
|
||||
case pvUByte:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<uint8> &>(from),fromOffset,
|
||||
dynamic_cast<PVValueArray<uint8>& >(to),
|
||||
toOffset,len);
|
||||
}
|
||||
break;
|
||||
case pvUShort:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<uint16> &>(from),fromOffset,
|
||||
dynamic_cast<PVValueArray<uint16>& >(to),
|
||||
toOffset,len);
|
||||
}
|
||||
break;
|
||||
case pvUInt:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<uint32> &>(from),fromOffset,
|
||||
dynamic_cast<PVValueArray<uint32>& >(to),
|
||||
toOffset,len);
|
||||
}
|
||||
break;
|
||||
case pvULong:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<uint64> &>(from),fromOffset,
|
||||
dynamic_cast<PVValueArray<uint64>& >(to),
|
||||
toOffset,len);
|
||||
}
|
||||
break;
|
||||
case pvFloat:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<float> &>(from),fromOffset,
|
||||
dynamic_cast<PVValueArray<float>& >(to),
|
||||
toOffset,len);
|
||||
}
|
||||
break;
|
||||
case pvDouble:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<double> &>(from),fromOffset,
|
||||
dynamic_cast<PVValueArray<double>& >(to),
|
||||
toOffset,len);
|
||||
}
|
||||
break;
|
||||
case pvString:
|
||||
{
|
||||
copy(dynamic_cast<PVValueArray<String> &>(from),fromOffset,
|
||||
dynamic_cast<PVValueArray<String>& >(to),
|
||||
toOffset,len);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void copy(
|
||||
PVStructureArray & from,
|
||||
size_t fromOffset,
|
||||
PVStructureArray & to,
|
||||
size_t toOffset,
|
||||
size_t len)
|
||||
{
|
||||
if(to.isImmutable()) {
|
||||
throw std::logic_error("pvSubArrayCopy to is immutable");
|
||||
}
|
||||
StructureArrayConstPtr fromStructure = from.getStructureArray();
|
||||
StructureArrayConstPtr toStructure = to.getStructureArray();
|
||||
if(fromStructure!=toStructure) {
|
||||
throw std::invalid_argument(
|
||||
"pvSubArrayCopy structureArray to and from have different structures");
|
||||
}
|
||||
size_t fromLength = from.getLength();
|
||||
if(fromOffset+len>fromLength) {
|
||||
throw std::length_error("pvSubArrayCopy from length error");
|
||||
}
|
||||
size_t capacity = to.getCapacity();
|
||||
if(toOffset+len>capacity) to.setCapacity(toOffset+len);
|
||||
typename PVValueArray<PVStructurePtr>::const_svector vecFrom = from.view();
|
||||
typename PVValueArray<PVStructurePtr>::const_svector vecTo = to.view();
|
||||
shared_vector<PVStructurePtr> temp;
|
||||
to.swap(temp);
|
||||
for(size_t i=0; i<len; ++i) {
|
||||
temp[i + toOffset] = vecFrom[i + fromOffset];
|
||||
}
|
||||
to.replace(temp);
|
||||
}
|
||||
|
||||
void copy(
|
||||
PVArray & from,
|
||||
size_t fromOffset,
|
||||
PVArray & to,
|
||||
size_t toOffset,
|
||||
size_t len)
|
||||
{
|
||||
Type type = from.getField()->getType();
|
||||
Type otherType = to.getField()->getType();
|
||||
if(type!=otherType) {
|
||||
throw std::invalid_argument("pvSubArrayCopy types do not match");
|
||||
}
|
||||
if(type==scalarArray) {
|
||||
copy(dynamic_cast<PVScalarArray &>(from) ,fromOffset,
|
||||
dynamic_cast<PVScalarArray&>(to),
|
||||
toOffset,len);
|
||||
}
|
||||
if(type==structureArray) {
|
||||
copy(dynamic_cast<PVStructureArray &>(from) ,fromOffset,
|
||||
dynamic_cast<PVStructureArray&>(to),
|
||||
toOffset,len);
|
||||
}
|
||||
}
|
||||
|
||||
}}
|
||||
|
83
src/pvData/pvSubArrayCopy.h
Normal file
83
src/pvData/pvSubArrayCopy.h
Normal file
@ -0,0 +1,83 @@
|
||||
/* pvSubArrayCopy.h */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author Marty Kraimer
|
||||
* @date 2013.07
|
||||
*/
|
||||
#ifndef PVSUBARRAYCOPY_H
|
||||
#define PVSUBARRAYCOPY_H
|
||||
#include <pv/pvData.h>
|
||||
|
||||
namespace epics { namespace pvData {
|
||||
|
||||
/** @brief Copy a subarray from one PVValueArray to another.
|
||||
* @warning The two PVValueArrays must both the same type
|
||||
* @param from The source
|
||||
* @param fromOffset The offset in the source
|
||||
* @param to The destination
|
||||
* @param toOffset The offset in the destination
|
||||
* @param len The total number of elements to copy
|
||||
*/
|
||||
template<typename T>
|
||||
void copy(
|
||||
PVValueArray<T> & pvFrom,
|
||||
size_t fromOffset,
|
||||
PVValueArray<T> & pvTo,
|
||||
size_t toOffset,
|
||||
size_t len);
|
||||
|
||||
/** @brief Copy a subarray from one scalar array to another.
|
||||
* @warning The two scalar arrays must both be PVValueArrays of the same type
|
||||
* @param from The source
|
||||
* @param fromOffset The offset in the source
|
||||
* @param to The destination
|
||||
* @param toOffset The offset in the destination
|
||||
* @param len The total number of elements to copy
|
||||
*/
|
||||
void copy(
|
||||
PVScalarArray & from,
|
||||
size_t fromOffset,
|
||||
PVScalarArray & to,
|
||||
size_t toOffset,
|
||||
size_t len);
|
||||
|
||||
/** @brief Copy a subarray from one structure array to another.
|
||||
* @warning The two structure arrays must have the same
|
||||
* structure introspection interface.
|
||||
* @param from The source
|
||||
* @param fromOffset The offset in the source
|
||||
* @param to The destination
|
||||
* @param toOffset The offset in the destination
|
||||
* @param len The total number of elements to copy
|
||||
*/
|
||||
void copy(
|
||||
PVStructureArray & from,
|
||||
size_t fromOffset,
|
||||
PVStructureArray & to,
|
||||
size_t toOffset,
|
||||
size_t len);
|
||||
|
||||
/** @brief Copy a subarray from one array to another.
|
||||
* @warning The two arrays must have the same
|
||||
* introspection interface.
|
||||
* @param from The source
|
||||
* @param fromOffset The offset in the source
|
||||
* @param to The destination
|
||||
* @param toOffset The offset in the destination
|
||||
* @param len The total number of elements to copy
|
||||
*/
|
||||
void copy(
|
||||
PVArray & from,
|
||||
size_t fromOffset,
|
||||
PVArray & to,
|
||||
size_t toOffset,
|
||||
size_t len);
|
||||
|
||||
}}
|
||||
|
||||
|
||||
#endif /* PVSUBARRAYCOPY_H */
|
@ -90,9 +90,7 @@ bool RecordListRecord::init()
|
||||
void RecordListRecord::process()
|
||||
{
|
||||
PVStringArrayPtr pvNames = PVDatabase::getMaster()->getRecordNames();
|
||||
std::vector<String> const & xxx = pvNames->getVector();
|
||||
size_t n = xxx.size();
|
||||
names->put(0,n,xxx,0);
|
||||
names->replace(pvNames->view());
|
||||
String message("");
|
||||
if(database->get().compare("master")!=0) {
|
||||
message += " can only access master ";
|
||||
|
155
src/v3IOC/PVAServerRegister.cpp
Normal file
155
src/v3IOC/PVAServerRegister.cpp
Normal file
@ -0,0 +1,155 @@
|
||||
/*PVAServerRegister.cpp */
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* EPICS pvData is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
/**
|
||||
* @author mrk
|
||||
* @date 2013.07.24
|
||||
*/
|
||||
|
||||
/* Author: Marty Kraimer */
|
||||
|
||||
#include <cstddef>
|
||||
#include <cstdlib>
|
||||
#include <cstddef>
|
||||
#include <string>
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
#include <iostream>
|
||||
|
||||
#include <cantProceed.h>
|
||||
#include <epicsStdio.h>
|
||||
#include <epicsMutex.h>
|
||||
#include <epicsEvent.h>
|
||||
#include <epicsThread.h>
|
||||
#include <iocsh.h>
|
||||
|
||||
#include <epicsExport.h>
|
||||
|
||||
#include <pv/pvAccess.h>
|
||||
#include <pv/serverContext.h>
|
||||
#include <pv/channelProviderLocal.h>
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::pvDatabase;
|
||||
|
||||
class PVAServerCTX;
|
||||
typedef std::tr1::shared_ptr<PVAServerCTX> PVAServerCTXPtr;
|
||||
|
||||
class PVAServerCTX :
|
||||
public std::tr1::enable_shared_from_this<PVAServerCTX>
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(PVAServerCTX);
|
||||
static PVAServerCTXPtr getPVAServerCTX();
|
||||
void start();
|
||||
void stop();
|
||||
virtual ~PVAServerCTX() {}
|
||||
private:
|
||||
PVAServerCTX() {}
|
||||
shared_pointer getPtrSelf()
|
||||
{
|
||||
return shared_from_this();
|
||||
}
|
||||
ServerContext::shared_pointer ctx;
|
||||
};
|
||||
|
||||
void PVAServerCTX::start()
|
||||
{
|
||||
if(ctx!=NULL) {
|
||||
cout<< "PVAServer already started" << endl;
|
||||
return;
|
||||
}
|
||||
ctx = startPVAServer(PVACCESS_ALL_PROVIDERS,0,true,true);
|
||||
}
|
||||
|
||||
void PVAServerCTX::stop()
|
||||
{
|
||||
if(ctx==NULL) {
|
||||
cout<< "PVAServer already stopped" << endl;
|
||||
return;
|
||||
}
|
||||
ChannelProviderLocalPtr channelProvider = getChannelProviderLocal();
|
||||
ctx->destroy();
|
||||
ctx.reset();
|
||||
epicsThreadSleep(1.0);
|
||||
channelProvider->destroy();
|
||||
}
|
||||
|
||||
PVAServerCTXPtr PVAServerCTX::getPVAServerCTX()
|
||||
{
|
||||
static PVAServerCTXPtr pvPVAServerCTX;
|
||||
static Mutex mutex;
|
||||
Lock xx(mutex);
|
||||
|
||||
if(pvPVAServerCTX==NULL) {
|
||||
pvPVAServerCTX = PVAServerCTXPtr(new PVAServerCTX());
|
||||
}
|
||||
return pvPVAServerCTX;
|
||||
}
|
||||
|
||||
|
||||
static const iocshFuncDef startPVAServerFuncDef = {
|
||||
"startPVAServer", 0, 0
|
||||
};
|
||||
extern "C" void startPVAServer(const iocshArgBuf *args)
|
||||
{
|
||||
PVAServerCTX::getPVAServerCTX()->start();
|
||||
}
|
||||
|
||||
static const iocshFuncDef stopPVAServerFuncDef = {
|
||||
"stopPVAServer", 0, 0
|
||||
};
|
||||
extern "C" void stopPVAServer(const iocshArgBuf *args)
|
||||
{
|
||||
PVAServerCTX::getPVAServerCTX()->stop();
|
||||
}
|
||||
|
||||
|
||||
static const iocshFuncDef pvdblFuncDef = {
|
||||
"pvdbl", 0, 0
|
||||
};
|
||||
extern "C" void pvdbl(const iocshArgBuf *args)
|
||||
{
|
||||
PVDatabasePtr master = PVDatabase::getMaster();
|
||||
PVStringArrayPtr pvNames = master->getRecordNames();
|
||||
PVStringArray::const_svector xxx = pvNames->view();
|
||||
for(size_t i=0; i<xxx.size(); ++i) cout<< xxx[i] << endl;
|
||||
}
|
||||
|
||||
static void startPVAServerRegister(void)
|
||||
{
|
||||
static int firstTime = 1;
|
||||
if (firstTime) {
|
||||
firstTime = 0;
|
||||
iocshRegister(&startPVAServerFuncDef, startPVAServer);
|
||||
}
|
||||
}
|
||||
|
||||
static void stopPVAServerRegister(void)
|
||||
{
|
||||
static int firstTime = 1;
|
||||
if (firstTime) {
|
||||
firstTime = 0;
|
||||
iocshRegister(&stopPVAServerFuncDef, stopPVAServer);
|
||||
}
|
||||
}
|
||||
|
||||
static void pvdblRegister(void)
|
||||
{
|
||||
static int firstTime = 1;
|
||||
if (firstTime) {
|
||||
firstTime = 0;
|
||||
iocshRegister(&pvdblFuncDef, pvdbl);
|
||||
getChannelProviderLocal();
|
||||
}
|
||||
}
|
||||
|
||||
epicsExportRegistrar(startPVAServerRegister);
|
||||
epicsExportRegistrar(stopPVAServerRegister);
|
||||
epicsExportRegistrar(pvdblRegister);
|
3
src/v3IOC/PVAServerRegister.dbd
Normal file
3
src/v3IOC/PVAServerRegister.dbd
Normal file
@ -0,0 +1,3 @@
|
||||
registrar("startPVAServerRegister")
|
||||
registrar("stopPVAServerRegister")
|
||||
registrar("pvdblRegister")
|
@ -1,17 +0,0 @@
|
||||
TOP=../..
|
||||
|
||||
include $(TOP)/configure/CONFIG
|
||||
|
||||
PROD_HOST += testExampleServer
|
||||
testExampleServer_SRCS += testExampleServerMain.cpp
|
||||
testExampleServer_LIBS += pvDatabase pvAccess pvData Com
|
||||
|
||||
PROD_HOST += exampleCounter
|
||||
exampleCounter_SRCS += exampleCounterMain.cpp
|
||||
exampleCounter_LIBS += pvDatabase pvAccess pvData Com
|
||||
|
||||
|
||||
include $(TOP)/configure/RULES
|
||||
#----------------------------------------
|
||||
# ADD RULES AFTER THIS LINE
|
||||
|
Reference in New Issue
Block a user