26 Commits
4.5.0 ... 4.5.2

Author SHA1 Message Date
Andrew Johnson
3f5bfd067f Update version numbers for release 2020-05-28 16:14:30 -05:00
mrkraimer
85165e6579 get ready for next epics7 release 2020-05-20 14:03:13 -04:00
Marty Kraimer
476a8f1e32 Merge pull request #56 from dirk-zimoch/CleanupWhitespace
Cleanup whitespace
2020-05-20 08:47:32 -04:00
31e883dbbc removed empty lines at end of file 2020-04-15 18:00:08 +02:00
57cbf66833 removed spaces at end of line 2020-04-15 17:58:14 +02:00
7f31332a80 replaced tabs with spaces 2020-04-15 17:54:47 +02:00
Marty Kraimer
12015309d8 Merge pull request #55 from epics-base/arrayfilterforunion
Arrayfilterforunion
2020-04-13 06:27:41 -04:00
mrkraimer
1e62844a22 testPlugin found bug: added unionArrayTest 2020-04-12 14:01:22 -04:00
mrkraimer
ad479309b0 fix bitset bug 2020-04-08 11:06:59 -04:00
mrkraimer
2f7c82757f pvArrayPlugin now supports union scalarArray 2020-04-07 12:53:01 -04:00
Marty Kraimer
634153a28d Merge pull request #54 from epics-base/issue53
Issue53
2020-02-18 05:39:58 -05:00
Heesterman, Peter J
e664037063 static analysis during the Codathon at Diamond. 2020-02-17 12:06:08 +00:00
mrkraimer
75c16bd423 pvDatabase::removeRecord and pvRecord::remove no longer call eachother directly 2020-02-12 09:13:19 -05:00
mrkraimer
083dffac3c pvDatabase::removeRecord and pvRecord::remove changes;descructors now have at most a print statement 2020-02-10 06:15:59 -05:00
mrkraimer
42ba054e5f add createdestroy example 2020-02-07 10:58:55 -05:00
mrkraimer
3173e9aeae problems with examples 2020-02-07 09:17:08 -05:00
mrkraimer
785d654129 first attempt to fix issue 53; add example 2020-02-07 08:54:18 -05:00
Ralph Lange
22ce4440b7 Fix bug preventing "whole structure" bitset(0) copy
(fixes #52)
(this should have a test added, but I am not familiar enough with the code)
2020-01-28 15:44:27 +01:00
Andrew Johnson
80baccfd9c Incr version and set development flag after release 2019-11-01 12:52:23 -05:00
Andrew Johnson
0c92f07749 Clear development flag for 4.5.1 release 2019-11-01 12:50:11 -05:00
Andrew Johnson
73a9f1f84f Release notes for 4.5.1 2019-11-01 12:48:58 -05:00
Marty Kraimer
3c3f0ab7f1 Merge pull request #51 from mrkraimer/master
addRecord is new
2019-09-13 10:00:22 -04:00
Marty Kraimer
803098922a Update .travis.yml 2019-09-13 09:04:54 -04:00
mrkraimer
c028af8b6d addRecord is new 2019-09-11 10:17:09 -04:00
Ralph Lange
d33d03189e rtd-ci: add read-the-docs integration 2019-09-06 14:19:00 +02:00
Andrew Johnson
d7bd5628d4 Update version number to 4.5.1 DEVELOPMENT 2019-08-13 11:04:36 -05:00
56 changed files with 950 additions and 303 deletions

17
.readthedocs.yml Normal file
View File

@@ -0,0 +1,17 @@
# .readthedocs.yml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Build documentation in the documentation/ directory with Sphinx
sphinx:
configuration: documentation/conf.py
# Build documentation with MkDocs
#mkdocs:
# configuration: mkdocs.yml
# Optionally build your docs in additional formats such as PDF and ePub
formats: all

View File

@@ -28,4 +28,4 @@ env:
- BRBASE=7.0 RTEMS=4.9 TEST=NO - BRBASE=7.0 RTEMS=4.9 TEST=NO
- BRBASE=3.16 - BRBASE=3.16
- BRBASE=3.15 - BRBASE=3.15
- BRBASE=3.14

View File

@@ -38,7 +38,7 @@ PROJECT_NAME = pvDatabaseCPP
# could be handy for archiving the generated documentation or if some version # could be handy for archiving the generated documentation or if some version
# control system is used. # control system is used.
PROJECT_NUMBER = PROJECT_NUMBER = 4.5.2
# Using the PROJECT_BRIEF tag one can provide an optional one line description # Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a # for a project that appears at the top of each page and should give viewer a
@@ -765,7 +765,7 @@ WARN_LOGFILE =
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched. # Note: If this tag is empty the current directory is searched.
INPUT = include INPUT = src
# This tag can be used to specify the character encoding of the source files # This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
@@ -1035,7 +1035,7 @@ GENERATE_HTML = YES
# The default directory is: html. # The default directory is: html.
# This tag requires that the tag GENERATE_HTML is set to YES. # This tag requires that the tag GENERATE_HTML is set to YES.
HTML_OUTPUT = documentation/html HTML_OUTPUT = html/doxygen
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each # The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
# generated HTML page (for example: .htm, .php, .asp). # generated HTML page (for example: .htm, .php, .asp).

View File

@@ -1,3 +1,12 @@
# Version number for the PV Database API and shared library
EPICS_PVDATABASE_MAJOR_VERSION = 4 EPICS_PVDATABASE_MAJOR_VERSION = 4
EPICS_PVDATABASE_MINOR_VERSION = 5 EPICS_PVDATABASE_MINOR_VERSION = 5
EPICS_PVDATABASE_MAINTENANCE_VERSION = 0 EPICS_PVDATABASE_MAINTENANCE_VERSION = 2
# Development flag, set to zero for release versions
EPICS_PVDATABASE_DEVELOPMENT_FLAG = 0
# Immediately after a release the MAINTENANCE_VERSION
# will be incremented and the DEVELOPMENT_FLAG set to 1

View File

@@ -2,10 +2,21 @@
This document summarizes the changes to the module between releases. This document summarizes the changes to the module between releases.
## Release 4.5.2 (EPICS 7.0.3.2 May 2020)
* plugin support is new
* fixed issues #53 and #52
## Release 4.5.1 (EPICS 7.0.3.1, Nov 2019)
* addRecord is new.
* Doxygen updates and read-the-docs integration.
## Release 4.5.0 (EPICS 7.0.3, Jul 2019) ## Release 4.5.0 (EPICS 7.0.3, Jul 2019)
1) support is a new feature. * support is a new feature.
2) processRecord is new * processRecord is new.
## Release 4.4.2 (EPICS 7.0.2.2, Apr 2019) ## Release 4.4.2 (EPICS 7.0.2.2, Apr 2019)

View File

@@ -0,0 +1,7 @@
.wy-side-nav-search {
background-color: #18334B;
}
.wy-side-nav-search input[type="text"] {
border-color: #18334b;
}

80
documentation/conf.py Normal file
View File

@@ -0,0 +1,80 @@
# Configuration file for the Sphinx documentation builder.
#
# This file only contains a selection of the most common options. For a full
# list see the documentation:
# http://www.sphinx-doc.org/en/master/config
# -- Path setup --------------------------------------------------------------
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#
# import os
# import sys
# sys.path.insert(0, os.path.abspath('.'))
# -- Project information -----------------------------------------------------
project = 'normativeTypes (C++)'
copyright = '2019, EPICS Controls.'
author = 'EPICS'
# -- General configuration ---------------------------------------------------
# Add any Sphinx extension module names here, as strings. They can be
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
# ones.
extensions = [
'sphinx.ext.intersphinx',
]
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
# This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# Intersphinx links to subprojects
intersphinx_mapping = {
}
# -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
#
html_theme = 'sphinx_rtd_theme'
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
html_css_files = [
'css/custom.css',
]
master_doc = 'index'
html_theme_options = {
'logo_only': True,
}
html_logo = "images/EPICS_white_logo_v02.png"
html_extra_path = [
'../html',
'pvDatabaseCPP.html',
]
# -- Run Doxygen ------------------------------------------------------------
import subprocess
subprocess.call('cd ..; mkdir -p html/doxygen; doxygen', shell=True)

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

17
documentation/index.rst Normal file
View File

@@ -0,0 +1,17 @@
pvDatabase (C++) Library
========================
.. toctree::
:hidden:
EPICS Website <https://epics-controls.org>
EPICS Documentation Home <https://docs.epics-controls.org>
.. toctree::
:maxdepth: 1
:caption: pvDatabaseCPP
Reference Manual <https://docs.epics-controls.org/projects/pvdatabase-cpp/en/latest/pvDatabaseCPP.html>
API Documentation <https://docs.epics-controls.org/projects/pvdatabase-cpp/en/latest/doxygen>
Source Code Repository on GitHub <https://github.com/epics-base/pvDatabaseCPP>

View File

@@ -37,7 +37,7 @@
<div class="head"> <div class="head">
<h1>pvDatabaseCPP</h1> <h1>pvDatabaseCPP</h1>
<h2 class="nocount">Release ? - TBD</h2> <h2 class="nocount">Release ? - TBD</h2>
Latest update 2019.06.19. Latest update 2019.09.11.
<h2 class="nocount">Abstract</h2> <h2 class="nocount">Abstract</h2>
@@ -135,6 +135,10 @@ href="./html/index.html">doxgen</a>
<dd> <dd>
This is a PVRecord that periodical processes a set of PVRecords in the local PVDatabase. This is a PVRecord that periodical processes a set of PVRecords in the local PVDatabase.
</dd> </dd>
<dt>addRecord.h</dt>
<dd>
This is a PVRecord that adds a new PVRecord to the local PVDatabase.
</dd>
<dt>removeRecord.h</dt> <dt>removeRecord.h</dt>
<dd> <dd>
This is a PVRecord that removes a PVRecord in the local PVDatabase. This is a PVRecord that removes a PVRecord in the local PVDatabase.
@@ -174,7 +178,7 @@ href="./html/index.html">doxgen</a>
<p>This has the pvSupport code.</p> <p>This has the pvSupport code.</p>
<h3>src/special</h3> <h3>src/special</h3>
<p> <p>
This has the code for processRecord, removeRecord, and traceRecord. This has the code for processRecord, addRecord, removeRecord, and traceRecord.
</p> </p>
<h3>src/copy</h3> <h3>src/copy</h3>
<p>This has the code for pvStructureCopy and all the plugin support. <p>This has the code for pvStructureCopy and all the plugin support.

25
example/createdestroy/Makefile Executable file
View File

@@ -0,0 +1,25 @@
TOP=../..
include $(TOP)/configure/CONFIG
#----------------------------------------
# ADD MACRO DEFINITIONS AFTER THIS LINE
#=============================
#=============================
# Build the application
TESTPROD_HOST = createdestroy
createdestroy_SRCS += createdestroy.cpp
# Add all the support libraries needed by this application
#pvatest_LIBS += xxx
# Finally link to the EPICS Base libraries
createdestroy_LIBS += pvDatabase pvAccess pvData
createdestroy_LIBS += $(EPICS_BASE_IOC_LIBS)
#===========================
include $(TOP)/configure/RULES
#----------------------------------------
# ADD RULES AFTER THIS LINE

View File

@@ -0,0 +1,20 @@
# pvDatabaseCPP/example/createdestroy
This is an example that:
1) Gets the master PVDatabase
2) Create ChannelProviderLocal
3) Creates a ServerContext
Then it executes a forever loop that:
1) creates a pvRecord and adds it to the pvDatabase.
2) creates a pvac::ClientProvider
3) creates a pvac::ClientChannel
4) creates a monitor on the channel
5) runs a loop 10 times that: does a put to the channel, and then gets the data for any outstanding monitors
6) removes the pvRecord from the pvDatabase
It also has options to set trace level for the pvRecord and to periodically pause by asking for input.

View File

@@ -0,0 +1,179 @@
/******************************************************************************
* This is modeled after a test program created by Bertrand Bauvir from the ITER Organization
******************************************************************************/
#include <iostream>
#include <epicsGetopt.h>
#include <pv/pvData.h>
#include <pv/pvDatabase.h>
#include <pv/serverContext.h>
#include <pv/channelProviderLocal.h>
#include <pva/client.h>
#include <epicsEvent.h>
// Local header files
// Constants
#define DEFAULT_RECORD_NAME "examplechannel"
using std::tr1::static_pointer_cast;
class Record : public ::epics::pvDatabase::PVRecord
{
public:
std::shared_ptr<::epics::pvData::PVStructure> __pv;
static std::shared_ptr<Record> create (std::string const & name, std::shared_ptr<::epics::pvData::PVStructure> const & pvstruct);
Record (std::string const & name, std::shared_ptr<epics::pvData::PVStructure> const & pvstruct)
: epics::pvDatabase::PVRecord(name, pvstruct) { __pv = pvstruct; };
virtual void process (void);
};
std::shared_ptr<Record> Record::create (std::string const & name, std::shared_ptr<::epics::pvData::PVStructure> const & pvstruct)
{
std::shared_ptr<Record> pvrecord (new Record (name, pvstruct));
// Need to be explicitly called .. not part of the base constructor
if(!pvrecord->init()) pvrecord.reset();
return pvrecord;
}
void Record::process (void)
{
PVRecord::process();
std::string name = this->getRecordName();
std::cout << this->getRecordName()
<< " process\n";
}
class MyMonitor
{
private:
std::tr1::shared_ptr<::pvac::MonitorSync> monitor;
MyMonitor(std::tr1::shared_ptr<::pvac::ClientChannel> const &channel)
{
monitor = std::tr1::shared_ptr<::pvac::MonitorSync>(new ::pvac::MonitorSync(channel->monitor()));
}
public:
static std::tr1::shared_ptr<MyMonitor> create(std::tr1::shared_ptr<::pvac::ClientChannel> const &channel)
{
return std::tr1::shared_ptr<MyMonitor>(new MyMonitor(channel));
}
void getData();
};
void MyMonitor::getData()
{
while (true) {
if(!monitor->wait(.001)) break;
switch(monitor->event.event) {
case pvac::MonitorEvent::Fail:
std::cerr<<monitor->name()<<" : Error : "<<monitor->event.message<<"\n";
return;
case pvac::MonitorEvent::Cancel:
std::cout<<monitor->name()<<" <Cancel>\n";
return;
case pvac::MonitorEvent::Disconnect:
std::cout<<monitor->name()<<" <Disconnect>\n";
return;
case pvac::MonitorEvent::Data:
while(monitor->poll()) {
std::cout<<monitor->name()<<" : "<<monitor->root;
}
if(monitor->complete()) {
return;
}
}
}
}
int main (int argc, char** argv)
{
int verbose = 0;
unsigned loopctr = 0;
unsigned pausectr = 0;
bool allowExit = false;
bool callRecord = false;
bool callDatabase = false;
int opt;
while((opt = getopt(argc, argv, "v:ardh")) != -1) {
switch(opt) {
case 'v':
verbose = std::stoi(optarg);
break;
case 'a' :
allowExit = true;
break;
case 'r' :
callRecord = true;
break;
case 'd' :
callDatabase = true;
break;
case 'h':
std::cout << " -v level -a -r -d -h \n";
std::cout << "-r call pvRecord->remove -d call master->removeRecord\n";
std::cout << "default\n";
std::cout << "-v " << verbose
<< " -a false"
<< " -d"
<< "\n";
return 0;
default:
std::cerr<<"Unknown argument: "<<opt<<"\n";
return -1;
}
}
if(!callRecord && !callDatabase) callDatabase = true;
::epics::pvDatabase::PVDatabasePtr master = epics::pvDatabase::PVDatabase::getMaster();
::epics::pvDatabase::ChannelProviderLocalPtr channelProvider = epics::pvDatabase::getChannelProviderLocal();
epics::pvAccess::ServerContext::shared_pointer context
= epics::pvAccess::startPVAServer(epics::pvAccess::PVACCESS_ALL_PROVIDERS, 0, true, true);
std::string startset("starting set of puts valuectr = ");
while (true) {
loopctr++;
std::string name = DEFAULT_RECORD_NAME + std::to_string(loopctr);
// Create record
// Create record structure
::epics::pvData::FieldBuilderPtr builder = epics::pvData::getFieldCreate()->createFieldBuilder();
builder->add("value", ::epics::pvData::pvULong);
std::shared_ptr<::epics::pvData::PVStructure> pvstruct
= ::epics::pvData::getPVDataCreate()->createPVStructure(builder->createStructure());
std::shared_ptr<Record> pvrecord = Record::create(std::string(name), pvstruct);
master->addRecord(pvrecord);
pvrecord->setTraceLevel(verbose);
// Start PVA (local) client
std::tr1::shared_ptr<::pvac::ClientProvider> provider
= std::tr1::shared_ptr<::pvac::ClientProvider>(new ::pvac::ClientProvider ("pva"));
std::tr1::shared_ptr<::pvac::ClientChannel> channel
= std::tr1::shared_ptr<::pvac::ClientChannel>(new ::pvac::ClientChannel (provider->connect(name)));
std::tr1::shared_ptr<MyMonitor> mymonitor = MyMonitor::create(channel);
unsigned valuectr = loopctr;
std::cout << startset << loopctr << "\n";
for (int ind=0; ind<100; ind++) {
channel->put().set("value",valuectr++).exec();
mymonitor->getData();
}
pausectr++;
if(allowExit && pausectr>10) {
pausectr = 0;
std::cout << "Type exit to stop: \n";
int c = std::cin.peek(); // peek character
if ( c == EOF ) continue;
std::string str;
std::getline(std::cin,str);
if(str.compare("exit")==0) break;
}
if(callRecord) {
std::cout << "callRecord\n";
pvrecord->remove();
}
if(callDatabase) {
std::cout << "callDatabase\n";
master->removeRecord(pvrecord);
}
}
return (0);
}

View File

@@ -25,6 +25,7 @@ INC += pv/channelProviderLocal.h
INC += pv/traceRecord.h INC += pv/traceRecord.h
INC += pv/removeRecord.h INC += pv/removeRecord.h
INC += pv/addRecord.h
INC += pv/processRecord.h INC += pv/processRecord.h
INC += pv/pvSupport.h INC += pv/pvSupport.h

View File

@@ -76,9 +76,19 @@ static vector<string> split(string const & colonSeparatedList) {
PVArrayFilterPtr PVArrayFilter::create( PVArrayFilterPtr PVArrayFilter::create(
const std::string & requestValue, const std::string & requestValue,
const PVFieldPtr & master) const PVFieldPtr & masterField)
{ {
Type type = master->getField()->getType(); bool masterIsUnion = false;
PVUnionPtr pvUnion;
Type type = masterField->getField()->getType();
if(type==epics::pvData::union_) {
pvUnion = std::tr1::static_pointer_cast<PVUnion>(masterField);
PVFieldPtr pvField = pvUnion->get();
if(pvField) {
masterIsUnion = true;
type = pvField->getField()->getType();
}
}
if(type!=scalarArray) { if(type!=scalarArray) {
PVArrayFilterPtr filter = PVArrayFilterPtr(); PVArrayFilterPtr filter = PVArrayFilterPtr();
return filter; return filter;
@@ -112,60 +122,82 @@ PVArrayFilterPtr PVArrayFilter::create(
PVArrayFilterPtr filter = PVArrayFilterPtr(); PVArrayFilterPtr filter = PVArrayFilterPtr();
return filter; return filter;
} }
PVScalarArrayPtr masterArray;
if(masterIsUnion) {
masterArray = static_pointer_cast<PVScalarArray>(pvUnion->get());
} else {
masterArray = static_pointer_cast<PVScalarArray>(masterField);
}
PVArrayFilterPtr filter = PVArrayFilterPtr filter =
PVArrayFilterPtr( PVArrayFilterPtr(
new PVArrayFilter( new PVArrayFilter(start,increment,end,masterField,masterArray));
start,increment,end,static_pointer_cast<PVScalarArray>(master)));
return filter; return filter;
} }
PVArrayFilter::PVArrayFilter(long start,long increment,long end,const PVScalarArrayPtr & masterArray) PVArrayFilter::PVArrayFilter(
long start,long increment,long end,
const PVFieldPtr & masterField,
const epics::pvData::PVScalarArrayPtr masterArray)
: start(start), : start(start),
increment(increment), increment(increment),
end(end), end(end),
masterField(masterField),
masterArray(masterArray) masterArray(masterArray)
{ {
} }
bool PVArrayFilter::filter(const PVFieldPtr & pvCopy,const BitSetPtr & bitSet,bool toCopy) bool PVArrayFilter::filter(const PVFieldPtr & pvField,const BitSetPtr & bitSet,bool toCopy)
{ {
PVScalarArrayPtr copyArray = static_pointer_cast<PVScalarArray>(pvCopy); PVFieldPtr pvCopy = pvField;
PVScalarArrayPtr copyArray;
bool isUnion = false;
Type type = masterField->getField()->getType();
if(type==epics::pvData::union_) {
isUnion = true;
PVUnionPtr pvMasterUnion = std::tr1::static_pointer_cast<PVUnion>(masterField);
PVUnionPtr pvCopyUnion = std::tr1::static_pointer_cast<PVUnion>(pvCopy);
if(toCopy) pvCopyUnion->copy(*pvMasterUnion);
PVFieldPtr pvField = pvCopyUnion->get();
copyArray = static_pointer_cast<PVScalarArray>(pvField);
} else {
copyArray = static_pointer_cast<PVScalarArray>(pvCopy);
}
long len = 0; long len = 0;
long start = this->start; long start = this->start;
long end = this->end; long end = this->end;
long no_elements = masterArray->getLength(); long no_elements = masterArray->getLength();
if(start<0) { if(start<0) {
start = no_elements+start; start = no_elements+start;
if(start<0) start = 0; if(start<0) start = 0;
} }
if (end < 0) { if (end < 0) {
end = no_elements + end; end = no_elements + end;
if (end < 0) end = 0; if (end < 0) end = 0;
} }
if(toCopy) { if(toCopy) {
if (end >= no_elements) end = no_elements - 1; if (end >= no_elements) end = no_elements - 1;
if (end - start >= 0) len = 1 + (end - start) / increment; if (end - start >= 0) len = 1 + (end - start) / increment;
if(len<=0 || start>=no_elements) { if(len<=0 || start>=no_elements) {
copyArray->setLength(0); copyArray->setLength(0);
return true; return true;
} }
long indfrom = start; long indfrom = start;
long indto = 0; long indto = 0;
copyArray->setCapacity(len); copyArray->setCapacity(len);
if(increment==1) { if(increment==1) {
copy(*masterArray,indfrom,1,*copyArray,indto,1,len); copy(*masterArray,indfrom,1,*copyArray,indto,1,len);
} else { } else {
for(long i=0; i<len; ++i) { for(long i=0; i<len; ++i) {
copy(*masterArray,indfrom,1,*copyArray,indto,1,1); copy(*masterArray,indfrom,1,*copyArray,indto,1,1);
indfrom += increment; indfrom += increment;
indto += 1; indto += 1;
} }
} }
copyArray->setLength(len); copyArray->setLength(len);
bitSet->set(pvCopy->getFieldOffset()); bitSet->set(pvField->getFieldOffset());
return true; return true;
} }
if (end - start >= 0) len = 1 + (end - start) / increment; if (end - start >= 0) len = 1 + (end - start) / increment;
if(len<=0) return true; if(len<=0) return true;
@@ -173,21 +205,21 @@ bool PVArrayFilter::filter(const PVFieldPtr & pvCopy,const BitSetPtr & bitSet,bo
long indfrom = 0; long indfrom = 0;
long indto = start; long indto = start;
if(increment==1) { if(increment==1) {
copy(*copyArray,indfrom,1,*masterArray,indto,1,len); copy(*copyArray,indfrom,1,*masterArray,indto,1,len);
} else { } else {
for(long i=0; i<len; ++i) { for(long i=0; i<len; ++i) {
copy(*copyArray,indfrom,1,*masterArray,indto,1,1); copy(*copyArray,indfrom,1,*masterArray,indto,1,1);
indfrom += 1; indfrom += 1;
indto += increment; indto += increment;
} }
} }
if(isUnion) masterField->postPut();
return true; return true;
} }
string PVArrayFilter::getName() string PVArrayFilter::getName()
{ {
return name; return name;
} }
}} }}

View File

@@ -244,7 +244,7 @@ void PVCopy::updateMasterCheckBitSet(
bitSet->clear(nextSet); bitSet->clear(nextSet);
PVStructurePtr pv = static_pointer_cast<PVStructure>(pvField); PVStructurePtr pv = static_pointer_cast<PVStructure>(pvField);
PVFieldPtrArray pvFieldArray = pv->getPVFields(); PVFieldPtrArray pvFieldArray = pv->getPVFields();
for(size_t i=0; i>pvFieldArray.size(); ++i) { for(size_t i=0; i<pvFieldArray.size(); ++i) {
PVFieldPtr pvField = pvFieldArray[i]; PVFieldPtr pvField = pvFieldArray[i];
bitSet->set(pvField->getFieldOffset()); bitSet->set(pvField->getFieldOffset());
} }
@@ -710,7 +710,7 @@ void PVCopy::setIgnore(CopyNodePtr const &node) {
CopyNodePtrArrayPtr nodes = structureNode->nodes; CopyNodePtrArrayPtr nodes = structureNode->nodes;
for(size_t i=0; i<nodes->size(); ++i) { for(size_t i=0; i<nodes->size(); ++i) {
CopyNodePtr node = (*nodes)[i]; CopyNodePtr node = (*nodes)[i];
setIgnore(node); } setIgnore(node); }
} else { } else {
size_t num = node->masterPVField->getNumberFields(); size_t num = node->masterPVField->getNumberFields();
if(num>1) { if(num>1) {

View File

@@ -128,8 +128,7 @@ bool PVDeadbandFilter::filter(const PVFieldPtr & pvCopy,const BitSetPtr & bitSet
string PVDeadbandFilter::getName() string PVDeadbandFilter::getName()
{ {
return name; return name;
} }
}} }}

View File

@@ -38,4 +38,3 @@ PVPluginPtr PVPluginRegistry::find(const std::string & name)
} }
}} }}

View File

@@ -120,8 +120,7 @@ bool PVTimestampFilter::filter(const PVFieldPtr & pvCopy,const BitSetPtr & bitSe
string PVTimestampFilter::getName() string PVTimestampFilter::getName()
{ {
return name; return name;
} }
}} }}

View File

@@ -56,14 +56,6 @@ PVDatabase::PVDatabase()
PVDatabase::~PVDatabase() PVDatabase::~PVDatabase()
{ {
if(DEBUG_LEVEL>0) cout << "PVDatabase::~PVDatabase()\n"; if(DEBUG_LEVEL>0) cout << "PVDatabase::~PVDatabase()\n";
size_t len = recordMap.size();
shared_vector<string> names(len);
PVRecordMap::iterator iter;
size_t i = 0;
for(iter = recordMap.begin(); iter!=recordMap.end(); ++iter) {
names[i++] = (*iter).first;
}
for(size_t i=0; i<len; ++i) removeRecord(findRecord(names[i]));
} }
void PVDatabase::lock() { void PVDatabase::lock() {
@@ -100,17 +92,28 @@ bool PVDatabase::addRecord(PVRecordPtr const & record)
return true; return true;
} }
bool PVDatabase::removeRecord(PVRecordPtr const & record) PVRecordWPtr PVDatabase::removeFromMap(PVRecordPtr const & record)
{ {
if(record->getTraceLevel()>0) {
cout << "PVDatabase::removeRecord " << record->getRecordName() << endl;
}
epicsGuard<epics::pvData::Mutex> guard(mutex); epicsGuard<epics::pvData::Mutex> guard(mutex);
string recordName = record->getRecordName(); string recordName = record->getRecordName();
PVRecordMap::iterator iter = recordMap.find(recordName); PVRecordMap::iterator iter = recordMap.find(recordName);
if(iter!=recordMap.end()) { if(iter!=recordMap.end()) {
PVRecordPtr pvRecord = (*iter).second; PVRecordPtr pvRecord = (*iter).second;
recordMap.erase(iter); recordMap.erase(iter);
return pvRecord->shared_from_this();
}
return PVRecordWPtr();
}
bool PVDatabase::removeRecord(PVRecordPtr const & record)
{
if(record->getTraceLevel()>0) {
cout << "PVDatabase::removeRecord " << record->getRecordName() << endl;
}
epicsGuard<epics::pvData::Mutex> guard(mutex);
PVRecordWPtr pvRecord = removeFromMap(record);
if(pvRecord.use_count()!=0) {
pvRecord.lock()->unlistenClients();
return true; return true;
} }
return false; return false;

View File

@@ -58,64 +58,16 @@ PVRecord::PVRecord(
{ {
} }
void PVRecord::notifyClients()
{
{
epicsGuard<epics::pvData::Mutex> guard(mutex);
if(traceLevel>0) {
cout << "PVRecord::notifyClients() " << recordName
<< endl;
}
}
pvTimeStamp.detach();
for(std::list<PVListenerWPtr>::iterator iter = pvListenerList.begin();
iter!=pvListenerList.end();
iter++ )
{
PVListenerPtr listener = iter->lock();
if(!listener) continue;
if(traceLevel>0) {
cout << "PVRecord::notifyClients() calling listener->unlisten "
<< recordName << endl;
}
listener->unlisten(shared_from_this());
}
pvListenerList.clear();
for (std::list<PVRecordClientWPtr>::iterator iter = clientList.begin();
iter!=clientList.end();
iter++ )
{
PVRecordClientPtr client = iter->lock();
if(!client) continue;
if(traceLevel>0) {
cout << "PVRecord::notifyClients() calling client->detach "
<< recordName << endl;
}
client->detach(shared_from_this());
}
if(traceLevel>0) {
cout << "PVRecord::notifyClients() calling clientList.clear() "
<< recordName << endl;
}
clientList.clear();
if(traceLevel>0) {
cout << "PVRecord::notifyClients() returning " << recordName << endl;
}
}
PVRecord::~PVRecord() PVRecord::~PVRecord()
{ {
if(traceLevel>0) { if(traceLevel>0) {
cout << "~PVRecord() " << recordName << endl; cout << "~PVRecord() " << recordName << endl;
} }
notifyClients();
} }
void PVRecord::remove() void PVRecord::unlistenClients()
{ {
PVDatabasePtr pvDatabase(PVDatabase::getMaster()); epicsGuard<epics::pvData::Mutex> guard(mutex);
if(pvDatabase) pvDatabase->removeRecord(shared_from_this());
pvTimeStamp.detach();
for(std::list<PVListenerWPtr>::iterator iter = pvListenerList.begin(); for(std::list<PVListenerWPtr>::iterator iter = pvListenerList.begin();
iter!=pvListenerList.end(); iter!=pvListenerList.end();
iter++ ) iter++ )
@@ -142,6 +94,19 @@ void PVRecord::remove()
clientList.clear(); clientList.clear();
} }
void PVRecord::remove()
{
if(traceLevel>0) {
cout << "PVRecord::remove() " << recordName << endl;
}
unlistenClients();
epicsGuard<epics::pvData::Mutex> guard(mutex);
PVDatabasePtr pvDatabase(PVDatabase::getMaster());
if(pvDatabase) pvDatabase->removeFromMap(shared_from_this());
pvTimeStamp.detach();
}
void PVRecord::initPVRecord() void PVRecord::initPVRecord()
{ {
PVRecordStructurePtr parent; PVRecordStructurePtr parent;

63
src/pv/addRecord.h Normal file
View File

@@ -0,0 +1,63 @@
/* addRecord.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.04.18
*/
#ifndef ADDRECORD_H
#define ADDRECORD_H
#include <pv/channelProviderLocal.h>
#include <shareLib.h>
namespace epics { namespace pvDatabase {
class AddRecord;
typedef std::tr1::shared_ptr<AddRecord> AddRecordPtr;
/**
* @brief Add another record in the same database.
*
* A record to add another record
* It is meant to be used via a channelPutGet request.
* The argument has one field: recordName.
* The result has a field named status.
*/
class epicsShareClass AddRecord :
public PVRecord
{
public:
POINTER_DEFINITIONS(AddRecord);
/**
* Factory methods to create AddRecord.
* @param recordName The name for the AddRecord.
* @return A shared pointer to AddRecord..
*/
static AddRecordPtr create(
std::string const & recordName);
/**
* standard init method required by PVRecord
* @return true unless record name already exists.
*/
virtual bool init();
/**
* @brief Add the record specified by recordName.
*/
virtual void process();
private:
AddRecord(
std::string const & recordName,
epics::pvData::PVStructurePtr const & pvStructure);
epics::pvData::PVStringPtr pvRecordName;
epics::pvData::PVStringPtr pvResult;
};
}}
#endif /* ADDRECORD_H */

View File

@@ -87,4 +87,3 @@ private:
}} }}
#endif /* CONTROLSUPPORT_H */ #endif /* CONTROLSUPPORT_H */

View File

@@ -63,9 +63,13 @@ private:
long start; long start;
long increment; long increment;
long end; long end;
epics::pvData::PVFieldPtr masterField;
epics::pvData::PVScalarArrayPtr masterArray; epics::pvData::PVScalarArrayPtr masterArray;
PVArrayFilter(long start,long increment,long end,const epics::pvData::PVScalarArrayPtr & masterArray); PVArrayFilter(
long start,long increment,long end,
const epics::pvData::PVFieldPtr & masterField,
const epics::pvData::PVScalarArrayPtr masterArray);
public: public:
POINTER_DEFINITIONS(PVArrayFilter); POINTER_DEFINITIONS(PVArrayFilter);
virtual ~PVArrayFilter(); virtual ~PVArrayFilter();
@@ -95,4 +99,3 @@ public:
}} }}
#endif /* PVARRAYPLUGIN_H */ #endif /* PVARRAYPLUGIN_H */

View File

@@ -252,10 +252,12 @@ protected:
*/ */
void initPVRecord(); void initPVRecord();
private: private:
friend class PVDatabase;
void unlistenClients();
PVRecordFieldPtr findPVRecordField( PVRecordFieldPtr findPVRecordField(
PVRecordStructurePtr const & pvrs, PVRecordStructurePtr const & pvrs,
epics::pvData::PVFieldPtr const & pvField); epics::pvData::PVFieldPtr const & pvField);
void notifyClients();
std::string recordName; std::string recordName;
epics::pvData::PVStructurePtr pvStructure; epics::pvData::PVStructurePtr pvStructure;
@@ -499,6 +501,7 @@ public:
/** /**
* @brief Remove a record. * @brief Remove a record.
* @param record The record to remove. * @param record The record to remove.
*
* @return <b>true</b> if record was removed. * @return <b>true</b> if record was removed.
*/ */
bool removeRecord(PVRecordPtr const & record); bool removeRecord(PVRecordPtr const & record);
@@ -508,6 +511,9 @@ public:
*/ */
epics::pvData::PVStringArrayPtr getRecordNames(); epics::pvData::PVStringArrayPtr getRecordNames();
private: private:
friend class PVRecord;
PVRecordWPtr removeFromMap(PVRecordPtr const & record);
PVDatabase(); PVDatabase();
void lock(); void lock();
void unlock(); void unlock();
@@ -519,4 +525,3 @@ private:
}} }}
#endif /* PVDATABASE_H */ #endif /* PVDATABASE_H */

View File

@@ -100,4 +100,3 @@ public:
}} }}
#endif /* PVDEADBANDPLUGIN_H */ #endif /* PVDEADBANDPLUGIN_H */

View File

@@ -75,4 +75,3 @@ public:
}} }}
#endif /* PVSUPPORT_H */ #endif /* PVSUPPORT_H */

View File

@@ -98,4 +98,3 @@ public:
}} }}
#endif /* PVTIMESTAMPPLUGIN_H */ #endif /* PVTIMESTAMPPLUGIN_H */

View File

@@ -108,4 +108,3 @@ private:
}} }}
#endif /* SCALARALARMSUPPORT_H */ #endif /* SCALARALARMSUPPORT_H */

View File

@@ -68,7 +68,7 @@ static bool getProcess(PVStructurePtr pvRequest,bool processDefault)
return pvString->get().compare("true")==0 ? true : false; return pvString->get().compare("true")==0 ? true : false;
} else if(scalar->getScalarType()==pvBoolean) { } else if(scalar->getScalarType()==pvBoolean) {
PVBooleanPtr pvBoolean = static_pointer_cast<PVBoolean>(pvField); PVBooleanPtr pvBoolean = static_pointer_cast<PVBoolean>(pvField);
return pvBoolean->get(); return pvBoolean->get();
} }
return processDefault; return processDefault;
} }
@@ -132,7 +132,7 @@ ChannelProcessLocalPtr ChannelProcessLocal::create(
if(pvField) { if(pvField) {
PVStringPtr pvString = pvOptions->getSubField<PVString>("nProcess"); PVStringPtr pvString = pvOptions->getSubField<PVString>("nProcess");
if(pvString) { if(pvString) {
int size; int size=0;
std::stringstream ss; std::stringstream ss;
ss << pvString->get(); ss << pvString->get();
ss >> size; ss >> size;
@@ -156,10 +156,7 @@ ChannelProcessLocalPtr ChannelProcessLocal::create(
ChannelProcessLocal::~ChannelProcessLocal() ChannelProcessLocal::~ChannelProcessLocal()
{ {
PVRecordPtr pvr(pvRecord.lock()); //cout << "~ChannelProcessLocal()\n";
if(pvr && pvr->getTraceLevel()>0) {
cout << "~ChannelProcessLocal() " << pvr->getRecordName() << endl;
}
} }
std::tr1::shared_ptr<Channel> ChannelProcessLocal::getChannel() std::tr1::shared_ptr<Channel> ChannelProcessLocal::getChannel()
@@ -304,10 +301,7 @@ ChannelGetLocalPtr ChannelGetLocal::create(
ChannelGetLocal::~ChannelGetLocal() ChannelGetLocal::~ChannelGetLocal()
{ {
PVRecordPtr pvr(pvRecord.lock()); //cout << "~ChannelGetLocal()\n";
if(pvr && pvr->getTraceLevel()>0) {
cout << "~ChannelGetLocal() " << pvr->getRecordName() << endl;
}
} }
std::tr1::shared_ptr<Channel> ChannelGetLocal::getChannel() std::tr1::shared_ptr<Channel> ChannelGetLocal::getChannel()
@@ -469,10 +463,7 @@ ChannelPutLocalPtr ChannelPutLocal::create(
ChannelPutLocal::~ChannelPutLocal() ChannelPutLocal::~ChannelPutLocal()
{ {
PVRecordPtr pvr(pvRecord.lock()); //cout << "~ChannelPutLocal()\n";
if(pvr && pvr->getTraceLevel()>0) {
cout << "~ChannelPutLocal() " << pvr->getRecordName() << endl;
}
} }
std::tr1::shared_ptr<Channel> ChannelPutLocal::getChannel() std::tr1::shared_ptr<Channel> ChannelPutLocal::getChannel()
@@ -662,10 +653,7 @@ ChannelPutGetLocalPtr ChannelPutGetLocal::create(
ChannelPutGetLocal::~ChannelPutGetLocal() ChannelPutGetLocal::~ChannelPutGetLocal()
{ {
PVRecordPtr pvr(pvRecord.lock()); //cout << "~ChannelPutGetLocal()\n";
if(pvr && pvr->getTraceLevel()>0) {
cout << "~ChannelPutGetLocal() " << pvr->getRecordName() << endl;
}
} }
std::tr1::shared_ptr<Channel> ChannelPutGetLocal::getChannel() std::tr1::shared_ptr<Channel> ChannelPutGetLocal::getChannel()
@@ -862,10 +850,7 @@ ChannelRPCLocalPtr ChannelRPCLocal::create(
ChannelRPCLocal::~ChannelRPCLocal() ChannelRPCLocal::~ChannelRPCLocal()
{ {
PVRecordPtr pvr(pvRecord.lock()); //cout << "~ChannelRPCLocal()\n";
if(pvr && pvr->getTraceLevel()>0) {
cout << "~ChannelRPCLocal() " << pvr->getRecordName() << endl;
}
} }
std::tr1::shared_ptr<Channel> ChannelRPCLocal::getChannel() std::tr1::shared_ptr<Channel> ChannelRPCLocal::getChannel()
@@ -1104,10 +1089,7 @@ ChannelArrayLocalPtr ChannelArrayLocal::create(
ChannelArrayLocal::~ChannelArrayLocal() ChannelArrayLocal::~ChannelArrayLocal()
{ {
PVRecordPtr pvr(pvRecord.lock()); //cout << "~ChannelArrayLocal()\n";
if(pvr && pvr->getTraceLevel()>0) {
cout << "~ChannelArrayLocal() " << pvr->getRecordName() << endl;
}
} }
std::tr1::shared_ptr<Channel> ChannelArrayLocal::getChannel() std::tr1::shared_ptr<Channel> ChannelArrayLocal::getChannel()
@@ -1261,12 +1243,7 @@ ChannelLocal::ChannelLocal(
ChannelLocal::~ChannelLocal() ChannelLocal::~ChannelLocal()
{ {
PVRecordPtr pvr(pvRecord.lock()); // cout << "~ChannelLocal()" << endl;
if(!pvr) return;
if(pvr->getTraceLevel()>0)
{
cout << "~ChannelLocal()" << endl;
}
} }
ChannelProvider::shared_pointer ChannelLocal::getProvider() ChannelProvider::shared_pointer ChannelLocal::getProvider()

View File

@@ -191,10 +191,7 @@ MonitorLocal::MonitorLocal(
MonitorLocal::~MonitorLocal() MonitorLocal::~MonitorLocal()
{ {
if(pvRecord->getTraceLevel()>0) //cout << "MonitorLocal::~MonitorLocal()" << endl;
{
cout << "MonitorLocal::~MonitorLocal()" << endl;
}
} }
@@ -294,7 +291,7 @@ void MonitorLocal::dataPut(PVRecordFieldPtr const & pvRecordField)
{ {
if(pvRecord->getTraceLevel()>1) if(pvRecord->getTraceLevel()>1)
{ {
cout << "PVCopyMonitor::dataPut(pvRecordField)" << endl; cout << "MonitorLocal::dataPut(pvRecordField)" << endl;
} }
if(state!=active) return; if(state!=active) return;
{ {
@@ -319,7 +316,7 @@ void MonitorLocal::dataPut(
{ {
if(pvRecord->getTraceLevel()>1) if(pvRecord->getTraceLevel()>1)
{ {
cout << "PVCopyMonitor::dataPut(requested,pvRecordField)" << endl; cout << "MonitorLocal::dataPut(requested,pvRecordField)" << endl;
} }
if(state!=active) return; if(state!=active) return;
{ {
@@ -346,7 +343,7 @@ void MonitorLocal::beginGroupPut(PVRecordPtr const & pvRecord)
{ {
if(pvRecord->getTraceLevel()>1) if(pvRecord->getTraceLevel()>1)
{ {
cout << "PVCopyMonitor::beginGroupPut()" << endl; cout << "MonitorLocal::beginGroupPut()" << endl;
} }
if(state!=active) return; if(state!=active) return;
{ {
@@ -360,7 +357,7 @@ void MonitorLocal::endGroupPut(PVRecordPtr const & pvRecord)
{ {
if(pvRecord->getTraceLevel()>1) if(pvRecord->getTraceLevel()>1)
{ {
cout << "PVCopyMonitor::endGroupPut dataChanged " << dataChanged << endl; cout << "MonitorLocal::endGroupPut dataChanged " << dataChanged << endl;
} }
if(state!=active) return; if(state!=active) return;
{ {
@@ -377,7 +374,7 @@ void MonitorLocal::unlisten(PVRecordPtr const & pvRecord)
{ {
if(pvRecord->getTraceLevel()>1) if(pvRecord->getTraceLevel()>1)
{ {
cout << "PVCopyMonitor::unlisten\n"; cout << "MonitorLocal::unlisten\n";
} }
{ {
Lock xx(mutex); Lock xx(mutex);
@@ -387,7 +384,7 @@ void MonitorLocal::unlisten(PVRecordPtr const & pvRecord)
if(requester) { if(requester) {
if(pvRecord->getTraceLevel()>1) if(pvRecord->getTraceLevel()>1)
{ {
cout << "PVCopyMonitor::unlisten calling requester->unlisten\n"; cout << "MonitorLocal::unlisten calling requester->unlisten\n";
} }
requester->unlisten(getPtrSelf()); requester->unlisten(getPtrSelf());
} }

View File

@@ -4,12 +4,15 @@ SRC_DIRS += $(PVDATABASE_SRC)/special
LIBSRCS += traceRecord.cpp LIBSRCS += traceRecord.cpp
LIBSRCS += removeRecord.cpp LIBSRCS += removeRecord.cpp
LIBSRCS += addRecord.cpp
LIBSRCS += processRecord.cpp LIBSRCS += processRecord.cpp
DBD += traceRecordRegister.dbd DBD += traceRecordRegister.dbd
DBD += removeRecordRegister.dbd DBD += removeRecordRegister.dbd
DBD += addRecordRegister.dbd
DBD += processRecordRegister.dbd DBD += processRecordRegister.dbd
LIBSRCS += traceRecordRegister.cpp LIBSRCS += traceRecordRegister.cpp
LIBSRCS += removeRecordRegister.cpp LIBSRCS += removeRecordRegister.cpp
LIBSRCS += addRecordRegister.cpp
LIBSRCS += processRecordRegister.cpp LIBSRCS += processRecordRegister.cpp

117
src/special/addRecord.cpp Normal file
View File

@@ -0,0 +1,117 @@
/* addRecord.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.04.18
*/
#include <string>
#include <cstring>
#include <stdexcept>
#include <memory>
#include <set>
#include <pv/lock.h>
#include <pv/pvType.h>
#include <pv/pvData.h>
#include <pv/standardField.h>
#include <pv/pvTimeStamp.h>
#include <pv/timeStamp.h>
#include <pv/rpcService.h>
#include <pv/pvAccess.h>
#include <pv/status.h>
#include <pv/serverContext.h>
#define epicsExportSharedSymbols
#include "pv/pvStructureCopy.h"
#include "pv/pvDatabase.h"
#include "pv/addRecord.h"
using std::tr1::static_pointer_cast;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace std;
namespace epics { namespace pvDatabase {
AddRecordPtr AddRecord::create(
std::string const & recordName)
{
FieldCreatePtr fieldCreate = getFieldCreate();
PVDataCreatePtr pvDataCreate = getPVDataCreate();
StructureConstPtr topStructure = fieldCreate->createFieldBuilder()->
addNestedStructure("argument")->
add("recordName",pvString)->
addNestedUnion("union") ->
endNested()->
endNested()->
addNestedStructure("result") ->
add("status",pvString) ->
endNested()->
createStructure();
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure);
AddRecordPtr pvRecord(
new AddRecord(recordName,pvStructure));
if(!pvRecord->init()) pvRecord.reset();
return pvRecord;
}
AddRecord::AddRecord(
std::string const & recordName,
epics::pvData::PVStructurePtr const & pvStructure)
: PVRecord(recordName,pvStructure)
{
}
bool AddRecord::init()
{
initPVRecord();
PVStructurePtr pvStructure = getPVStructure();
pvRecordName = pvStructure->getSubField<PVString>("argument.recordName");
if(!pvRecordName) return false;
pvResult = pvStructure->getSubField<PVString>("result.status");
if(!pvResult) return false;
return true;
}
void AddRecord::process()
{
PVDataCreatePtr pvDataCreate = getPVDataCreate();
string name = pvRecordName->get();
PVRecordPtr pvRecord = PVDatabase::getMaster()->findRecord(name);
if(pvRecord) {
pvResult->put(name + " already exists");
return;
}
PVUnionPtr pvUnion = getPVStructure()->getSubField<PVUnion>("argument.union");
if(!pvUnion) {
pvResult->put(name + " argument.union is NULL");
return;
}
PVFieldPtr pvField(pvUnion->get());
if(!pvField) {
pvResult->put(name + " union has no value");
return;
}
if(pvField->getField()->getType()!=epics::pvData::structure) {
pvResult->put(name + " union most be a structure");
return;
}
StructureConstPtr st = static_pointer_cast<const Structure>(pvField->getField());
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(st);
PVRecordPtr pvRec = PVRecord::create(name,pvStructure);
bool result = PVDatabase::getMaster()->addRecord(pvRec);
if(result) {
pvResult->put("success");
} else {
pvResult->put("failure");
}
}
}}

View File

@@ -0,0 +1,62 @@
/*
* Copyright information and license terms for this software can be
* found in the file LICENSE that is included with the distribution
*/
/**
* @author mrk
* @date 2013.07.24
*/
/* Author: Marty Kraimer */
#include <epicsThread.h>
#include <iocsh.h>
#include <pv/event.h>
#include <pv/pvAccess.h>
#include <pv/serverContext.h>
#include <pv/pvData.h>
#include <pv/pvTimeStamp.h>
#include <pv/rpcService.h>
// The following must be the last include for code pvDatabase uses
#include <epicsExport.h>
#define epicsExportSharedSymbols
#include "pv/pvStructureCopy.h"
#include "pv/pvDatabase.h"
#include "pv/addRecord.h"
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::pvDatabase;
using namespace std;
static const iocshArg testArg0 = { "recordName", iocshArgString };
static const iocshArg *testArgs[] = {
&testArg0};
static const iocshFuncDef addRecordFuncDef = {"addRecordCreate", 1,testArgs};
static void addRecordCallFunc(const iocshArgBuf *args)
{
char *recordName = args[0].sval;
if(!recordName) {
throw std::runtime_error("addRecordCreate invalid number of arguments");
}
AddRecordPtr record = AddRecord::create(recordName);
bool result = PVDatabase::getMaster()->addRecord(record);
if(!result) cout << "recordname" << " not added" << endl;
}
static void addRecordRegister(void)
{
static int firstTime = 1;
if (firstTime) {
firstTime = 0;
iocshRegister(&addRecordFuncDef, addRecordCallFunc);
}
}
extern "C" {
epicsExportRegistrar(addRecordRegister);
}

View File

@@ -0,0 +1 @@
registrar("addRecordRegister")

View File

@@ -164,4 +164,3 @@ void ProcessRecord::run()
}} }}

View File

@@ -90,4 +90,3 @@ void RemoveRecord::process()
}} }}

View File

@@ -93,4 +93,3 @@ void TraceRecord::process()
}} }}

View File

@@ -29,7 +29,7 @@ namespace epics { namespace pvDatabase {
ControlSupport::~ControlSupport() ControlSupport::~ControlSupport()
{ {
cout << "ControlSupport::~ControlSupport()\n"; //cout << "ControlSupport::~ControlSupport()\n";
} }
epics::pvData::StructureConstPtr ControlSupport::controlField(ScalarType scalarType) epics::pvData::StructureConstPtr ControlSupport::controlField(ScalarType scalarType)
@@ -135,4 +135,3 @@ void ControlSupport::reset()
}} }}

View File

@@ -30,7 +30,7 @@ namespace epics { namespace pvDatabase {
ScalarAlarmSupport::~ScalarAlarmSupport() ScalarAlarmSupport::~ScalarAlarmSupport()
{ {
cout << "ScalarAlarmSupport::~ScalarAlarmSupport()\n"; //cout << "ScalarAlarmSupport::~ScalarAlarmSupport()\n";
} }
@@ -216,4 +216,3 @@ void ScalarAlarmSupport::setAlarm(
}} }}

View File

@@ -26,7 +26,7 @@
#ifdef listenerEpicsExportSharedSymbols #ifdef listenerEpicsExportSharedSymbols
# define epicsExportSharedSymbols # define epicsExportSharedSymbols
# undef listenerEpicsExportSharedSymbols # undef listenerEpicsExportSharedSymbols
#endif #endif
#include <shareLib.h> #include <shareLib.h>

View File

@@ -25,7 +25,7 @@
#ifdef powerSupplyEpicsExportSharedSymbols #ifdef powerSupplyEpicsExportSharedSymbols
# define epicsExportSharedSymbols # define epicsExportSharedSymbols
# undef powerSupplyEpicsExportSharedSymbols # undef powerSupplyEpicsExportSharedSymbols
#endif #endif
#include <shareLib.h> #include <shareLib.h>

View File

@@ -25,7 +25,7 @@
#ifdef pvRecordClientEpicsExportSharedSymbols #ifdef pvRecordClientEpicsExportSharedSymbols
# define epicsExportSharedSymbols # define epicsExportSharedSymbols
# undef pvRecordClientEpicsExportSharedSymbols # undef pvRecordClientEpicsExportSharedSymbols
#endif #endif
#include <shareLib.h> #include <shareLib.h>

View File

@@ -134,4 +134,3 @@ MAIN(testExampleRecord)
test(); test();
return 0; return 0;
} }

View File

@@ -79,4 +79,3 @@ MAIN(testLocalProvider)
test(); test();
return 0; return 0;
} }

View File

@@ -75,4 +75,3 @@ MAIN(testPVAServer)
test(); test();
return 0; return 0;
} }

View File

@@ -401,4 +401,3 @@ MAIN(testPVCopy)
powerSupplyTest(); powerSupplyTest();
return 0; return 0;
} }

View File

@@ -103,4 +103,3 @@ MAIN(testPVRecord)
powerSupplyTest(); powerSupplyTest();
return 0; return 0;
} }

View File

@@ -145,6 +145,73 @@ static void arrayTest()
testOk1(nset==1); testOk1(nset==1);
} }
static void unionArrayTest()
{
if(debug) {cout << endl << endl << "****unionArrayTest****" << endl;}
bool result = false;
uint32 nset = 0;
size_t n = 10;
shared_vector<double> values(n);
for(size_t i=0; i<n; i++) values[i] = i + .06;
PVDoubleArrayPtr pvDoubleArray =
static_pointer_cast<PVDoubleArray>(PVDataCreate::getPVDataCreate()->createPVScalarArray(pvDouble));
const shared_vector<const double> yyy(freeze(values));
pvDoubleArray->putFrom(yyy);
StandardFieldPtr standardField = getStandardField();
FieldCreatePtr fieldCreate = getFieldCreate();
StructureConstPtr top = fieldCreate->createFieldBuilder()->
add("value",fieldCreate->createVariantUnion()) ->
add("timeStamp", standardField->timeStamp()) ->
addNestedStructure("subfield") ->
add("value",fieldCreate->createVariantUnion()) ->
endNested()->
createStructure();
PVStructurePtr pvRecordStructure(PVDataCreate::getPVDataCreate()->createPVStructure(top));
PVRecordPtr pvRecord(PVRecord::create("unionArrayRecord",pvRecordStructure));
PVUnionPtr pvUnion = pvRecord->getPVStructure()->getSubField<PVUnion>("value");
pvUnion->set(pvDoubleArray);
pvUnion = pvRecord->getPVStructure()->getSubField<PVUnion>("subfield.value");
pvUnion->set(pvDoubleArray);
if(debug) { cout << "initial\n" << pvRecordStructure << "\n";}
PVStructurePtr pvRequest(CreateRequest::create()->createRequest("value[array=1:3]"));
PVCopyPtr pvCopy(PVCopy::create(pvRecordStructure,pvRequest,""));
PVStructurePtr pvStructureCopy(pvCopy->createPVStructure());
BitSetPtr bitSet(new BitSet(pvStructureCopy->getNumberFields()));
PVDoubleArrayPtr pvValue(pvRecordStructure->getSubField<PVDoubleArray>("value"));
result = pvCopy->updateCopySetBitSet(pvStructureCopy,bitSet);
nset = bitSet->cardinality();
if(debug) {
cout << "after get value"
<< " result " << (result ? "true" : "false")
<< " nset " << nset
<< " bitSet " << *bitSet
<< " pvStructureCopy\n" << pvStructureCopy
<< "\n";
}
testOk1(result==true);
testOk1(nset==1);
pvRequest = CreateRequest::create()->createRequest("subfield.value[array=1:3]");
pvCopy = PVCopy::create(pvRecordStructure,pvRequest,"");
pvStructureCopy = pvCopy->createPVStructure();
bitSet = BitSetPtr(new BitSet(pvStructureCopy->getNumberFields()));
pvValue = pvRecordStructure->getSubField<PVDoubleArray>("subfield.value");
result = pvCopy->updateCopySetBitSet(pvStructureCopy,bitSet);
nset = bitSet->cardinality();
if(debug) {
cout << "after get subfield.value"
<< " result " << (result ? "true" : "false")
<< " nset " << nset
<< " bitSet " << *bitSet
<< " pvStructureCopy\n" << pvStructureCopy
<< "\n";
}
testOk1(result==true);
testOk1(nset==1);
}
static void timeStampTest() static void timeStampTest()
{ {
if(debug) {cout << endl << endl << "****timeStampTest****" << endl;} if(debug) {cout << endl << endl << "****timeStampTest****" << endl;}
@@ -267,12 +334,12 @@ static void ignoreTest()
MAIN(testPlugin) MAIN(testPlugin)
{ {
testPlan(22); testPlan(26);
PVDatabasePtr pvDatabase(PVDatabase::getMaster()); PVDatabasePtr pvDatabase(PVDatabase::getMaster());
deadbandTest(); deadbandTest();
arrayTest(); arrayTest();
unionArrayTest();
timeStampTest(); timeStampTest();
ignoreTest(); ignoreTest();
return 0; return 0;
} }