make compatible with pvDataCPP-md; channelArray implemented; can be part of v3IOC.

This commit is contained in:
Marty Kraimer
2013-07-25 10:27:17 -04:00
parent 255f58aeb8
commit e40fe7b0ac
57 changed files with 2595 additions and 318 deletions

View File

@ -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

View File

@ -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&lt;&lt;.
</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&gt; pwd
/home/hg/pvDatabaseCPP
mrk&gt; bin/linux-x86_64/testExampleServer
mrk&gt; bin/linux-x86_64/exampleCounterMain
</pre></p>
<p>The Java programs
<p>To start exampleCounter as part of a V3IOC:
<pre>
mrk&gt; pwd
/home/hg/pvDatabaseCPP/iocBoot/exampleCounter
mrk&gt; ../../../bin/linux-x86_64/exampleCounter st.cmd
</pre></p>
<p>You can then issue the commands dbl and pvdbl:
<pre>
epics&gt; dbl
double01
epics&gt; pvdbl
exampleCounter
epics&gt;
</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&gt; pwd
mrk&gt; 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-&gt;addRecord(pvRecord);
cout &lt;&lt; "result of addRecord " &lt;&lt; recordName &lt;&lt; " " &lt;&lt; result &lt;&lt; endl;
pvRecord.reset();
cout &lt;&lt; "exampleServer\n";
startPVAServer(PVACCESS_ALL_PROVIDERS,0,true,true);
cout &lt;&lt; "exampleCounter\n";
string str;
while(true) {
cout &lt;&lt; "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>

File diff suppressed because it is too large Load Diff

View File

@ -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

View 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

View File

@ -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";

View 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

View 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;
}

View File

@ -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
View 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

View File

@ -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;
}

View 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
View File

@ -0,0 +1,6 @@
TOP = ../..
include $(TOP)/configure/CONFIG
DIRS += exampleCounter
DIRS += exampleServer
include $(TOP)/configure/RULES_DIRS

View 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

View 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")
}

View 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

View 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

View 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);

View File

@ -0,0 +1,3 @@
include "base.dbd"
include "PVAServerRegister.dbd"
registrar("exampleCounterRegister")

View 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);
}

View 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

View 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")
}

View 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")
}

View 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")
}

View 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")
}

View 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")
}

View File

@ -0,0 +1,3 @@
record(stringout, "$(name)")
{
}

View File

@ -0,0 +1,5 @@
record(waveform, "${name}")
{
field(NELM,"5")
field(FTVL,"STRING")
}

View 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

View 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

View 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);

View File

@ -0,0 +1,3 @@
include "base.dbd"
include "PVAServerRegister.dbd"
registrar("exampleServerRegister")

View 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
View 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

View File

@ -0,0 +1,5 @@
TOP = ../..
include $(TOP)/configure/CONFIG
ARCH = $(EPICS_HOST_ARCH)
TARGETS = envPaths
include $(TOP)/configure/RULES.ioc

View 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

View File

@ -0,0 +1,5 @@
TOP = ../..
include $(TOP)/configure/CONFIG
ARCH = $(EPICS_HOST_ARCH)
TARGETS = envPaths
include $(TOP)/configure/RULES.ioc

View 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

View File

@ -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

View File

@ -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;
}

View File

@ -6,7 +6,7 @@
*/
/**
* @author mrk
* @data 2012.11.21
* @date 2012.11.21
*/
#include <pv/pvDatabase.h>

View File

@ -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;

View File

@ -6,7 +6,7 @@
*/
/**
* @author Marty Kraimer
* @data 2013.04
* @date 2013.04
*/
#ifndef CHANNELPROVIDERLOCAL_H
#define CHANNELPROVIDERLOCAL_H

View File

@ -6,7 +6,7 @@
*/
/**
* @author Marty Kraimer
* @data 2013.04
* @date 2013.04
*/
#ifndef MONITORALGORITHM_H
#define MONITORALGORITHM_H

View File

@ -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 &copyPVField,
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);
}
}
}

View File

@ -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 &copyPVField,
PVRecordFieldPtr const &recordPVField);
void makeShared(
epics::pvData::PVFieldPtr const &copyPVField,
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 */

View 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);
}
}
}}

View 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 */

View File

@ -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 ";

View 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);

View File

@ -0,0 +1,3 @@
registrar("startPVAServerRegister")
registrar("stopPVAServerRegister")
registrar("pvdblRegister")

View File

@ -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