From dafc37b585d8c234d6137953419d9d53f83acd80 Mon Sep 17 00:00:00 2001 From: mrkraimer Date: Mon, 15 Mar 2021 07:04:32 -0400 Subject: [PATCH] The following changes were made: 1) PVRecord now has two new methods: setAsLevel and setAsGroup. 2) The following special records are DEPRECATED: addRecord,processRecord,removeRecord, and traceRecord. They are replaced by pvdbcrAddRecord,pvdbcrProcessRecord,pvdbcrRemoveRecord, and pvdbcrTraceRecord. 3) A new convention is that all special records start with pvdbcr, which means pvDatabase Create Record. 4) pvdbcrAddRecord,pvdbcrProcessRecord,pvdbcrRemoveRecord, and pvdbcrTraceRecord are like what they replace. But they also allow the asLevel to be set when they are created. 5) pvdbcrScalar and pvdbcrScalarArray are new special records. They created records that have fields value, alarm, and timeStamp. value can have any of the allowed scalar types, i.e. boolean,byte,...,string. --- src/Makefile | 6 + src/pv/pvDatabase.h | 10 ++ src/pv/pvdbcrAddRecord.h | 63 ++++++++ src/pv/pvdbcrProcessRecord.h | 89 +++++++++++ src/pv/pvdbcrRemoveRecord.h | 63 ++++++++ src/pv/pvdbcrTraceRecord.h | 66 ++++++++ src/special/Makefile | 19 +++ src/special/addRecordRegister.cpp | 1 + src/special/processRecordRegister.cpp | 1 + src/special/pvdbcrAddRecord.cpp | 116 ++++++++++++++ src/special/pvdbcrAddRecordRegister.cpp | 64 ++++++++ src/special/pvdbcrAddRecordRegister.dbd | 1 + src/special/pvdbcrProcessRecord.cpp | 166 ++++++++++++++++++++ src/special/pvdbcrProcessRecordRegister.cpp | 69 ++++++++ src/special/pvdbcrProcessRecordRegister.dbd | 1 + src/special/pvdbcrRemoveRecord.cpp | 92 +++++++++++ src/special/pvdbcrRemoveRecordRegister.cpp | 64 ++++++++ src/special/pvdbcrRemoveRecordRegister.dbd | 1 + src/special/pvdbcrScalarArrayRegister.cpp | 85 ++++++++++ src/special/pvdbcrScalarArrayRegister.dbd | 1 + src/special/pvdbcrScalarRegister.cpp | 85 ++++++++++ src/special/pvdbcrScalarRegister.dbd | 1 + src/special/pvdbcrTraceRecord.cpp | 95 +++++++++++ src/special/pvdbcrTraceRecordRegister.cpp | 65 ++++++++ src/special/pvdbcrTraceRecordRegister.dbd | 1 + src/special/removeRecordRegister.cpp | 1 + src/special/traceRecordRegister.cpp | 1 + 27 files changed, 1227 insertions(+) create mode 100644 src/pv/pvdbcrAddRecord.h create mode 100644 src/pv/pvdbcrProcessRecord.h create mode 100644 src/pv/pvdbcrRemoveRecord.h create mode 100644 src/pv/pvdbcrTraceRecord.h create mode 100644 src/special/pvdbcrAddRecord.cpp create mode 100644 src/special/pvdbcrAddRecordRegister.cpp create mode 100644 src/special/pvdbcrAddRecordRegister.dbd create mode 100644 src/special/pvdbcrProcessRecord.cpp create mode 100644 src/special/pvdbcrProcessRecordRegister.cpp create mode 100644 src/special/pvdbcrProcessRecordRegister.dbd create mode 100644 src/special/pvdbcrRemoveRecord.cpp create mode 100644 src/special/pvdbcrRemoveRecordRegister.cpp create mode 100644 src/special/pvdbcrRemoveRecordRegister.dbd create mode 100644 src/special/pvdbcrScalarArrayRegister.cpp create mode 100644 src/special/pvdbcrScalarArrayRegister.dbd create mode 100644 src/special/pvdbcrScalarRegister.cpp create mode 100644 src/special/pvdbcrScalarRegister.dbd create mode 100644 src/special/pvdbcrTraceRecord.cpp create mode 100644 src/special/pvdbcrTraceRecordRegister.cpp create mode 100644 src/special/pvdbcrTraceRecordRegister.dbd diff --git a/src/Makefile b/src/Makefile index 0e6db8c..a6def5b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -28,6 +28,11 @@ INC += pv/removeRecord.h INC += pv/addRecord.h INC += pv/processRecord.h +INC += pv/pvdbcrTraceRecord.h +INC += pv/pvdbcrRemoveRecord.h +INC += pv/pvdbcrAddRecord.h +INC += pv/pvdbcrProcessRecord.h + INC += pv/pvSupport.h INC += pv/controlSupport.h INC += pv/scalarAlarmSupport.h @@ -39,6 +44,7 @@ include $(PVDATABASE_SRC)/pvAccess/Makefile include $(PVDATABASE_SRC)/special/Makefile include $(PVDATABASE_SRC)/support/Makefile +pvDatabase_LIBS += nt pvDatabase_LIBS += $(EPICS_BASE_PVA_CORE_LIBS) pvDatabase_LIBS += $(EPICS_BASE_IOC_LIBS) diff --git a/src/pv/pvDatabase.h b/src/pv/pvDatabase.h index f21799d..a072466 100644 --- a/src/pv/pvDatabase.h +++ b/src/pv/pvDatabase.h @@ -248,6 +248,16 @@ public: * @return The name. */ std::string getAsGroup() const {return asGroup;} + /** + * @brief set access security level. + * @param level The level + */ + void setAsLevel(int level) {asLevel=level;} + /** + * @brief set access security group + * @param group The group name + */ + void setAsGroup(const std::string& group) {asGroup = group;} protected: /** * @brief Constructor diff --git a/src/pv/pvdbcrAddRecord.h b/src/pv/pvdbcrAddRecord.h new file mode 100644 index 0000000..8e7cbd7 --- /dev/null +++ b/src/pv/pvdbcrAddRecord.h @@ -0,0 +1,63 @@ +/* PvdbcrAddRecord.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 2021.03.12 + */ +#ifndef PVDBCRADDRECORD_H +#define PVDBCRADDRECORD_H + +#include + +#include + +namespace epics { namespace pvDatabase { + + +class PvdbcrAddRecord; +typedef std::tr1::shared_ptr PvdbcrAddRecordPtr; + +/** + * @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 PvdbcrAddRecord : + public PVRecord +{ +public: + POINTER_DEFINITIONS(PvdbcrAddRecord); + /** + * Factory methods to create PvdbcrAddRecord. + * @param recordName The name for the PvdbcrAddRecord. + * @return A shared pointer to PvdbcrAddRecord. + */ + static PvdbcrAddRecordPtr 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: + PvdbcrAddRecord( + std::string const & recordName, + epics::pvData::PVStructurePtr const & pvStructure); + epics::pvData::PVStringPtr pvRecordName; + epics::pvData::PVStringPtr pvResult; +}; + +}} + +#endif /* PVDBCRADDRECORD_H */ diff --git a/src/pv/pvdbcrProcessRecord.h b/src/pv/pvdbcrProcessRecord.h new file mode 100644 index 0000000..c87ee6a --- /dev/null +++ b/src/pv/pvdbcrProcessRecord.h @@ -0,0 +1,89 @@ +/* PvdbcrProcessRecord.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 2021.03.12 + */ +#ifndef PVDBCRPROCESSRECORD_H +#define PVDBCRPROCESSRECORD_H + +#include +#include +#include +#include + +#include + +namespace epics { namespace pvDatabase { + +typedef std::tr1::shared_ptr EpicsThreadPtr; + +class PvdbcrProcessRecord; +typedef std::tr1::shared_ptr PvdbcrProcessRecordPtr; + +/** + * @brief Process another record in the same database. + * + * A record to process 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 PvdbcrProcessRecord : + public PVRecord, + public epicsThreadRunable +{ +public: + POINTER_DEFINITIONS(PvdbcrProcessRecord); + /** + * Factory methods to create ProcessRecord. + * @param recordName The name for the ProcessRecord. + * @param delay Delay time to wait between process requests. + * @return A shared pointer to ProcessRecord. + */ + static PvdbcrProcessRecordPtr create( + std::string const & recordName,double delay); + /** + * standard init method required by PVRecord + * @return true unless record name already exists. + */ + virtual bool init(); + /** + * @brief Process the record specified by recordName. + */ + virtual void process(); + /** + * @brief The run method for the thread. + */ + virtual void run(); + /** + * @brief Start the thread + */ + void startThread(); + /** + * @brief Stop the thread + */ + void stop(); +private: + PvdbcrProcessRecord( + std::string const & recordName, + epics::pvData::PVStructurePtr const & pvStructure,double delay); + double delay; + EpicsThreadPtr thread; + epics::pvData::Event runStop; + epics::pvData::Event runReturn; + PVDatabasePtr pvDatabase; + PVRecordMap pvRecordMap; + epics::pvData::PVStringPtr pvCommand; + epics::pvData::PVStringPtr pvRecordName; + epics::pvData::PVStringPtr pvResult; + epics::pvData::Mutex mutex; +}; + +}} + +#endif /* PVDBCRPROCESSRECORD_H */ diff --git a/src/pv/pvdbcrRemoveRecord.h b/src/pv/pvdbcrRemoveRecord.h new file mode 100644 index 0000000..166edeb --- /dev/null +++ b/src/pv/pvdbcrRemoveRecord.h @@ -0,0 +1,63 @@ +/* PvdbcrRemoveRecord.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 2021.03.12 + */ +#ifndef PVDBCRREMOVERECORD_H +#define PVDBCRREMOVERECORD_H + +#include + +#include + +namespace epics { namespace pvDatabase { + + +class PvdbcrRemoveRecord; +typedef std::tr1::shared_ptr PvdbcrRemoveRecordPtr; + +/** + * @brief Remove another record in the same database. + * + * A record to remove 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 PvdbcrRemoveRecord : + public PVRecord +{ +public: + POINTER_DEFINITIONS(PvdbcrRemoveRecord); + /** + * Factory methods to create PvdbcrRemoveRecord. + * @param recordName The name for the PvdbcrRemoveRecord. + * @return A shared pointer to PvdbcrRemoveRecord.. + */ + static PvdbcrRemoveRecordPtr create( + std::string const & recordName); + /** + * standard init method required by PVRecord + * @return true unless record name already exists. + */ + virtual bool init(); + /** + * @brief Remove the record specified by recordName. + */ + virtual void process(); +private: + PvdbcrRemoveRecord( + std::string const & recordName, + epics::pvData::PVStructurePtr const & pvStructure); + epics::pvData::PVStringPtr pvRecordName; + epics::pvData::PVStringPtr pvResult; +}; + +}} + +#endif /* PVDBCRREMOVERECORD_H */ diff --git a/src/pv/pvdbcrTraceRecord.h b/src/pv/pvdbcrTraceRecord.h new file mode 100644 index 0000000..38eccdd --- /dev/null +++ b/src/pv/pvdbcrTraceRecord.h @@ -0,0 +1,66 @@ +/* PvdbcrTraceRecord.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 2021.03.12 + */ +#ifndef PVDBCRTRACERECORD_H +#define PVDBCRTRACERECORD_H + +#include + +#include + + +namespace epics { namespace pvDatabase { + + +class PvdbcrTraceRecord; +typedef std::tr1::shared_ptr PvdbcrTraceRecordPtr; + +/** + * @brief Trace activity of PVRecord. + * + * A record to set the trace value for another record + * It is meant to be used via a channelPutGet request. + * The argument has two fields: recordName and level. + * The result has a field named status. + */ +class epicsShareClass PvdbcrTraceRecord : + public PVRecord +{ +public: + POINTER_DEFINITIONS(PvdbcrTraceRecord); + /** + * @brief Factory method to create PvdbcrTraceRecord. + * + * @param recordName The name for the PvdbcrTraceRecord. + * @return A shared pointer to PvdbcrTraceRecord. + */ + static PvdbcrTraceRecordPtr create( + std::string const & recordName); + /** + * standard init method required by PVRecord + * @return true unless record name already exists. + */ + virtual bool init(); + /** + * @brief Set the trace level for record specified by recordName. + */ + virtual void process(); +private: + PvdbcrTraceRecord( + std::string const & recordName, + epics::pvData::PVStructurePtr const & pvStructure); + epics::pvData::PVStringPtr pvRecordName; + epics::pvData::PVIntPtr pvLevel; + epics::pvData::PVStringPtr pvResult; +}; + +}} + +#endif /* PVDBCRTRACERECORD_H */ diff --git a/src/special/Makefile b/src/special/Makefile index e928d8f..b8b419d 100644 --- a/src/special/Makefile +++ b/src/special/Makefile @@ -2,6 +2,25 @@ SRC_DIRS += $(PVDATABASE_SRC)/special +LIBSRCS += pvdbcrTraceRecord.cpp +LIBSRCS += pvdbcrRemoveRecord.cpp +LIBSRCS += pvdbcrAddRecord.cpp +LIBSRCS += pvdbcrProcessRecord.cpp + +DBD += pvdbcrTraceRecordRegister.dbd +DBD += pvdbcrRemoveRecordRegister.dbd +DBD += pvdbcrAddRecordRegister.dbd +DBD += pvdbcrProcessRecordRegister.dbd +DBD += pvdbcrScalarRegister.dbd +DBD += pvdbcrScalarArrayRegister.dbd + +LIBSRCS += pvdbcrTraceRecordRegister.cpp +LIBSRCS += pvdbcrRemoveRecordRegister.cpp +LIBSRCS += pvdbcrAddRecordRegister.cpp +LIBSRCS += pvdbcrProcessRecordRegister.cpp +LIBSRCS += pvdbcrScalarRegister.cpp +LIBSRCS += pvdbcrScalarArrayRegister.cpp + LIBSRCS += traceRecord.cpp LIBSRCS += removeRecord.cpp LIBSRCS += addRecord.cpp diff --git a/src/special/addRecordRegister.cpp b/src/special/addRecordRegister.cpp index 32e581b..4dee555 100644 --- a/src/special/addRecordRegister.cpp +++ b/src/special/addRecordRegister.cpp @@ -39,6 +39,7 @@ static const iocshFuncDef addRecordFuncDef = {"addRecordCreate", 1,testArgs}; static void addRecordCallFunc(const iocshArgBuf *args) { + cerr << "DEPRECATED use pvdbcrAddRecord instead\n"; char *recordName = args[0].sval; if(!recordName) { throw std::runtime_error("addRecordCreate invalid number of arguments"); diff --git a/src/special/processRecordRegister.cpp b/src/special/processRecordRegister.cpp index 5fb38ea..985f476 100644 --- a/src/special/processRecordRegister.cpp +++ b/src/special/processRecordRegister.cpp @@ -42,6 +42,7 @@ static const iocshFuncDef processRecordFuncDef = {"processRecordCreate", 2,testA static void processRecordCallFunc(const iocshArgBuf *args) { + cerr << "DEPRECATED use pvdbcrProcessRecord instead\n"; char *recordName = args[0].sval; if(!recordName) { throw std::runtime_error("processRecordCreate invalid number of arguments"); diff --git a/src/special/pvdbcrAddRecord.cpp b/src/special/pvdbcrAddRecord.cpp new file mode 100644 index 0000000..35c9073 --- /dev/null +++ b/src/special/pvdbcrAddRecord.cpp @@ -0,0 +1,116 @@ +/* pvdbcrAddRecord.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 2021.03.12 + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define epicsExportSharedSymbols +#include "pv/pvStructureCopy.h" +#include "pv/pvDatabase.h" +#include "pv/pvdbcrAddRecord.h" + +using std::tr1::static_pointer_cast; +using namespace epics::pvData; +using namespace epics::pvAccess; +using namespace std; + +namespace epics { namespace pvDatabase { +PvdbcrAddRecordPtr PvdbcrAddRecord::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); + PvdbcrAddRecordPtr pvRecord( + new PvdbcrAddRecord(recordName,pvStructure)); + if(!pvRecord->init()) pvRecord.reset(); + return pvRecord; +} + +PvdbcrAddRecord::PvdbcrAddRecord( + std::string const & recordName, + epics::pvData::PVStructurePtr const & pvStructure) +: PVRecord(recordName,pvStructure) +{ +} + +bool PvdbcrAddRecord::init() +{ + initPVRecord(); + PVStructurePtr pvStructure = getPVStructure(); + pvRecordName = pvStructure->getSubField("argument.recordName"); + if(!pvRecordName) return false; + pvResult = pvStructure->getSubField("result.status"); + if(!pvResult) return false; + return true; +} + +void PvdbcrAddRecord::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("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(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"); + } +} + + +}} diff --git a/src/special/pvdbcrAddRecordRegister.cpp b/src/special/pvdbcrAddRecordRegister.cpp new file mode 100644 index 0000000..ee79897 --- /dev/null +++ b/src/special/pvdbcrAddRecordRegister.cpp @@ -0,0 +1,64 @@ +/* + * Copyright information and license terms for this software can be + * found in the file LICENSE that is included with the distribution + */ + +/** + * @author mrk + * @date 2021.03.12 + */ + + +/* Author: Marty Kraimer */ +#include +#include +#include +#include +#include +#include +#include +#include + +// The following must be the last include for code pvDatabase uses +#include +#define epicsExportSharedSymbols +#include "pv/pvStructureCopy.h" +#include "pv/pvDatabase.h" +#include "pv/pvdbcrAddRecord.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 testArg1 = { "asLevel", iocshArgInt }; +static const iocshArg *testArgs[] = {&testArg0,&testArg1}; + +static const iocshFuncDef pvdbcrAddRecordFuncDef = {"pvdbcrAddRecord", 2,testArgs}; + +static void pvdbcrAddRecordCallFunc(const iocshArgBuf *args) +{ + char *recordName = args[0].sval; + if(!recordName) { + throw std::runtime_error("pvdbcrAddRecord invalid number of arguments"); + } + int asLevel = args[1].ival; + PvdbcrAddRecordPtr record = PvdbcrAddRecord::create(recordName); + record->setAsLevel(asLevel); + bool result = PVDatabase::getMaster()->addRecord(record); + if(!result) cout << "recordname" << " not added" << endl; +} + +static void pvdbcrAddRecordRegister(void) +{ + static int firstTime = 1; + if (firstTime) { + firstTime = 0; + iocshRegister(&pvdbcrAddRecordFuncDef, pvdbcrAddRecordCallFunc); + } +} + +extern "C" { + epicsExportRegistrar(pvdbcrAddRecordRegister); +} diff --git a/src/special/pvdbcrAddRecordRegister.dbd b/src/special/pvdbcrAddRecordRegister.dbd new file mode 100644 index 0000000..65f7c9b --- /dev/null +++ b/src/special/pvdbcrAddRecordRegister.dbd @@ -0,0 +1 @@ +registrar("pvdbcrAddRecordRegister") diff --git a/src/special/pvdbcrProcessRecord.cpp b/src/special/pvdbcrProcessRecord.cpp new file mode 100644 index 0000000..7e6f78b --- /dev/null +++ b/src/special/pvdbcrProcessRecord.cpp @@ -0,0 +1,166 @@ +/* pvdbcrProcessRecord.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 2021.03.12 + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define epicsExportSharedSymbols +#include "pv/pvStructureCopy.h" +#include "pv/pvDatabase.h" +#include "pv/pvdbcrProcessRecord.h" + +using std::tr1::static_pointer_cast; +using namespace epics::pvData; +using namespace epics::pvAccess; +using namespace std; + +namespace epics { namespace pvDatabase { + +PvdbcrProcessRecordPtr PvdbcrProcessRecord::create( + std::string const & recordName,double delay) +{ + FieldCreatePtr fieldCreate = getFieldCreate(); + PVDataCreatePtr pvDataCreate = getPVDataCreate(); + StructureConstPtr topStructure = fieldCreate->createFieldBuilder()-> + addNestedStructure("argument")-> + add("command",pvString)-> + add("recordName",pvString)-> + endNested()-> + addNestedStructure("result") -> + add("status",pvString) -> + endNested()-> + createStructure(); + PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure); + PvdbcrProcessRecordPtr pvRecord( + new PvdbcrProcessRecord(recordName,pvStructure,delay)); + if(!pvRecord->init()) pvRecord.reset(); + return pvRecord; +} + +void PvdbcrProcessRecord::startThread() +{ + thread = EpicsThreadPtr(new epicsThread( + *this, + "processRecord", + epicsThreadGetStackSize(epicsThreadStackSmall), + epicsThreadPriorityLow)); + thread->start(); +} + +void PvdbcrProcessRecord::stop() +{ + runStop.signal(); + runReturn.wait(); +} + + +PvdbcrProcessRecord::PvdbcrProcessRecord( + std::string const & recordName, + epics::pvData::PVStructurePtr const & pvStructure,double delay) +: PVRecord(recordName,pvStructure), + delay(delay), + pvDatabase(PVDatabase::getMaster()) +{ +} + +bool PvdbcrProcessRecord::init() +{ + initPVRecord(); + PVStructurePtr pvStructure = getPVStructure(); + pvCommand = pvStructure->getSubField("argument.command"); + pvRecordName = pvStructure->getSubField("argument.recordName"); + if(!pvRecordName) return false; + pvResult = pvStructure->getSubField("result.status"); + if(!pvResult) return false; + startThread(); + return true; +} + +void PvdbcrProcessRecord::process() +{ + string recordName = pvRecordName->get(); + string command = pvCommand->get(); + if(command.compare("add")==0) { + epicsGuard guard(mutex); + std::map::iterator iter = pvRecordMap.find(recordName); + if(iter!=pvRecordMap.end()) { + pvResult->put(recordName + " already present"); + return; + } + PVRecordPtr pvRecord = pvDatabase->findRecord(recordName); + if(!pvRecord) { + pvResult->put(recordName + " not in pvDatabase"); + return; + } + pvRecordMap.insert(PVRecordMap::value_type(recordName,pvRecord)); + pvResult->put("success"); + return; + } else if(command.compare("remove")==0) { + epicsGuard guard(mutex); + std::map::iterator iter = pvRecordMap.find(recordName); + if(iter==pvRecordMap.end()) { + pvResult->put(recordName + " not found"); + return; + } + pvRecordMap.erase(iter); + pvResult->put("success"); + return; + } else { + pvResult->put(command + " not a valid command: only add and remove are valid"); + return; + } +} + +void PvdbcrProcessRecord::run() +{ + while(true) { + if(runStop.tryWait()) { + runReturn.signal(); + return; + } + if(delay>0.0) epicsThreadSleep(delay); + epicsGuard guard(mutex); + PVRecordMap::iterator iter; + for(iter = pvRecordMap.begin(); iter!=pvRecordMap.end(); ++iter) { + PVRecordPtr pvRecord = (*iter).second; + pvRecord->lock(); + pvRecord->beginGroupPut(); + try { + pvRecord->process(); + } catch (std::exception& ex) { + std::cout << "record " << pvRecord->getRecordName() << "exception " << ex.what() << "\n"; + } catch (...) { + std::cout<< "record " << pvRecord->getRecordName() << " process exception\n"; + } + pvRecord->endGroupPut(); + pvRecord->unlock(); + } + } +} + + +}} diff --git a/src/special/pvdbcrProcessRecordRegister.cpp b/src/special/pvdbcrProcessRecordRegister.cpp new file mode 100644 index 0000000..bc0228b --- /dev/null +++ b/src/special/pvdbcrProcessRecordRegister.cpp @@ -0,0 +1,69 @@ +/* + * Copyright information and license terms for this software can be + * found in the file LICENSE that is included with the distribution + */ + +/** + * @author mrk + * @date 2021.03.12 + */ + + +/* Author: Marty Kraimer */ + +#include +#include +#include +#include +#include +#include +#include +#include + +// The following must be the last include for code pvDatabase uses +#include +#define epicsExportSharedSymbols +#include "pv/pvStructureCopy.h" +#include "pv/pvDatabase.h" +#include "pv/pvdbcrProcessRecord.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 testArg1 = { "delay", iocshArgDouble }; +static const iocshArg testArg2 = { "asLevel", iocshArgInt }; +static const iocshArg *testArgs[] = {&testArg0,&testArg1,&testArg2}; + +static const iocshFuncDef pvdbcrProcessRecordFuncDef = {"pvdbcrProcessRecord", 3,testArgs}; + +static void pvdbcrProcessRecordCallFunc(const iocshArgBuf *args) +{ + char *recordName = args[0].sval; + if(!recordName) { + throw std::runtime_error("pvdbcrProcessRecordCreate invalid number of arguments"); + } + double delay = args[1].dval; + int asLevel = args[2].ival; + if(delay<0.0) delay = 1.0; + PvdbcrProcessRecordPtr record = PvdbcrProcessRecord::create(recordName,delay); + record->setAsLevel(asLevel); + bool result = PVDatabase::getMaster()->addRecord(record); + if(!result) cout << "recordname" << " not added" << endl; +} + +static void pvdbcrProcessRecordRegister(void) +{ + static int firstTime = 1; + if (firstTime) { + firstTime = 0; + iocshRegister(&pvdbcrProcessRecordFuncDef, pvdbcrProcessRecordCallFunc); + } +} + +extern "C" { + epicsExportRegistrar(pvdbcrProcessRecordRegister); +} diff --git a/src/special/pvdbcrProcessRecordRegister.dbd b/src/special/pvdbcrProcessRecordRegister.dbd new file mode 100644 index 0000000..8948909 --- /dev/null +++ b/src/special/pvdbcrProcessRecordRegister.dbd @@ -0,0 +1 @@ +registrar("pvdbcrProcessRecordRegister") diff --git a/src/special/pvdbcrRemoveRecord.cpp b/src/special/pvdbcrRemoveRecord.cpp new file mode 100644 index 0000000..726a537 --- /dev/null +++ b/src/special/pvdbcrRemoveRecord.cpp @@ -0,0 +1,92 @@ +/* pvdbcrRemoveRecord.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 2021.03.12 + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define epicsExportSharedSymbols +#include "pv/pvStructureCopy.h" +#include "pv/pvDatabase.h" +#include "pv/pvdbcrRemoveRecord.h" + +using std::tr1::static_pointer_cast; +using namespace epics::pvData; +using namespace epics::pvAccess; +using namespace std; + +namespace epics { namespace pvDatabase { + +PvdbcrRemoveRecordPtr PvdbcrRemoveRecord::create( + std::string const & recordName) +{ + FieldCreatePtr fieldCreate = getFieldCreate(); + PVDataCreatePtr pvDataCreate = getPVDataCreate(); + StructureConstPtr topStructure = fieldCreate->createFieldBuilder()-> + addNestedStructure("argument")-> + add("recordName",pvString)-> + endNested()-> + addNestedStructure("result") -> + add("status",pvString) -> + endNested()-> + createStructure(); + PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure); + PvdbcrRemoveRecordPtr pvRecord( + new PvdbcrRemoveRecord(recordName,pvStructure)); + if(!pvRecord->init()) pvRecord.reset(); + return pvRecord; +} + +PvdbcrRemoveRecord::PvdbcrRemoveRecord( + std::string const & recordName, + epics::pvData::PVStructurePtr const & pvStructure) +: PVRecord(recordName,pvStructure) +{ +} + +bool PvdbcrRemoveRecord::init() +{ + initPVRecord(); + PVStructurePtr pvStructure = getPVStructure(); + pvRecordName = pvStructure->getSubField("argument.recordName"); + if(!pvRecordName) return false; + pvResult = pvStructure->getSubField("result.status"); + if(!pvResult) return false; + return true; +} + +void PvdbcrRemoveRecord::process() +{ + string name = pvRecordName->get(); + PVRecordPtr pvRecord = PVDatabase::getMaster()->findRecord(name); + if(!pvRecord) { + pvResult->put(name + " not found"); + return; + } + pvRecord->remove(); + pvResult->put("success"); +} + + +}} diff --git a/src/special/pvdbcrRemoveRecordRegister.cpp b/src/special/pvdbcrRemoveRecordRegister.cpp new file mode 100644 index 0000000..fbbde3e --- /dev/null +++ b/src/special/pvdbcrRemoveRecordRegister.cpp @@ -0,0 +1,64 @@ +/* + * Copyright information and license terms for this software can be + * found in the file LICENSE that is included with the distribution + */ + +/** + * @author mrk + * @date 2021.03.12 + */ + + +/* Author: Marty Kraimer */ +#include +#include +#include +#include +#include +#include +#include +#include + +// The following must be the last include for code pvDatabase uses +#include +#define epicsExportSharedSymbols +#include "pv/pvStructureCopy.h" +#include "pv/pvDatabase.h" +#include "pv/pvdbcrRemoveRecord.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 testArg1 = { "asLevel", iocshArgInt }; +static const iocshArg *testArgs[] = {&testArg0,&testArg1}; + +static const iocshFuncDef pvdbcrRemoveRecordFuncDef = {"pvdbcrRemoveRecord", 2,testArgs}; + +static void pvdbcrRemoveRecordCallFunc(const iocshArgBuf *args) +{ + char *recordName = args[0].sval; + if(!recordName) { + throw std::runtime_error("pvdbcrRemoveRecordCreate invalid number of arguments"); + } + int asLevel = args[1].ival; + PvdbcrRemoveRecordPtr record = PvdbcrRemoveRecord::create(recordName); + record->setAsLevel(asLevel); + bool result = PVDatabase::getMaster()->addRecord(record); + if(!result) cout << "recordname" << " not added" << endl; +} + +static void pvdbcrRemoveRecordRegister(void) +{ + static int firstTime = 1; + if (firstTime) { + firstTime = 0; + iocshRegister(&pvdbcrRemoveRecordFuncDef, pvdbcrRemoveRecordCallFunc); + } +} + +extern "C" { + epicsExportRegistrar(pvdbcrRemoveRecordRegister); +} diff --git a/src/special/pvdbcrRemoveRecordRegister.dbd b/src/special/pvdbcrRemoveRecordRegister.dbd new file mode 100644 index 0000000..99d21c5 --- /dev/null +++ b/src/special/pvdbcrRemoveRecordRegister.dbd @@ -0,0 +1 @@ +registrar("pvdbcrRemoveRecordRegister") diff --git a/src/special/pvdbcrScalarArrayRegister.cpp b/src/special/pvdbcrScalarArrayRegister.cpp new file mode 100644 index 0000000..7b564a8 --- /dev/null +++ b/src/special/pvdbcrScalarArrayRegister.cpp @@ -0,0 +1,85 @@ +/* + * Copyright information and license terms for this software can be + * found in the file LICENSE that is included with the distribution + */ + +/** + * @author mrk + * @date 2021.03.12 + */ + + +/* Author: Marty Kraimer */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// The following must be the last include for code pvDatabase uses +#include +#define epicsExportSharedSymbols +#include "pv/pvStructureCopy.h" +#include "pv/pvDatabase.h" + +using namespace epics::pvData; +using namespace epics::nt; +using namespace epics::pvAccess; +using namespace epics::pvDatabase; +using namespace std; + +static const iocshArg testArg0 = { "recordName", iocshArgString }; +static const iocshArg testArg1 = { "scalarType", iocshArgString }; +static const iocshArg testArg2 = { "asLevel", iocshArgInt }; +static const iocshArg *testArgs[] = {&testArg0,&testArg1,&testArg2}; + +static const iocshFuncDef pvdbcrScalarArrayFuncDef = {"pvdbcrScalarArray", 3,testArgs}; + +static void pvdbcrScalarArrayCallFunc(const iocshArgBuf *args) +{ + char *sval = args[0].sval; + if(!sval) { + throw std::runtime_error("pvdbcrScalarArrayCreate recordName not specified"); + } + string recordName = string(sval); + sval = args[1].sval; + if(!sval) { + throw std::runtime_error("pvdbcrScalarArrayCreate scalarType not specified"); + } + string scalarType = string(sval); + int asLevel = args[2].ival; + try { + ScalarType st = epics::pvData::ScalarTypeFunc::getScalarType(scalarType); + NTScalarArrayBuilderPtr ntScalarArrayBuilder = NTScalarArray::createBuilder(); + PVStructurePtr pvStructure = ntScalarArrayBuilder-> + value(st)-> + addAlarm()-> + addTimeStamp()-> + createPVStructure(); + PVRecordPtr record = PVRecord::create(recordName,pvStructure); + record->setAsLevel(asLevel); + PVDatabasePtr master = PVDatabase::getMaster(); + bool result = master->addRecord(record); + if(!result) cout << "recordname " << recordName << " not added" << endl; + } catch(std::exception& ex) { + cerr << "failure " << ex.what() << "/n"; + } +} + +static void pvdbcrScalarArrayRegister(void) +{ + static int firstTime = 1; + if (firstTime) { + firstTime = 0; + iocshRegister(&pvdbcrScalarArrayFuncDef, pvdbcrScalarArrayCallFunc); + } +} + +extern "C" { + epicsExportRegistrar(pvdbcrScalarArrayRegister); +} diff --git a/src/special/pvdbcrScalarArrayRegister.dbd b/src/special/pvdbcrScalarArrayRegister.dbd new file mode 100644 index 0000000..db27b53 --- /dev/null +++ b/src/special/pvdbcrScalarArrayRegister.dbd @@ -0,0 +1 @@ +registrar("pvdbcrScalarArrayRegister") diff --git a/src/special/pvdbcrScalarRegister.cpp b/src/special/pvdbcrScalarRegister.cpp new file mode 100644 index 0000000..e44a777 --- /dev/null +++ b/src/special/pvdbcrScalarRegister.cpp @@ -0,0 +1,85 @@ +/* + * Copyright information and license terms for this software can be + * found in the file LICENSE that is included with the distribution + */ + +/** + * @author mrk + * @date 2021.03.12 + */ + + +/* Author: Marty Kraimer */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// The following must be the last include for code pvDatabase uses +#include +#define epicsExportSharedSymbols +#include "pv/pvStructureCopy.h" +#include "pv/pvDatabase.h" + +using namespace epics::pvData; +using namespace epics::nt; +using namespace epics::pvAccess; +using namespace epics::pvDatabase; +using namespace std; + +static const iocshArg testArg0 = { "recordName", iocshArgString }; +static const iocshArg testArg1 = { "scalarType", iocshArgString }; +static const iocshArg testArg2 = { "asLevel", iocshArgInt }; +static const iocshArg *testArgs[] = {&testArg0,&testArg1,&testArg2}; + +static const iocshFuncDef pvdbcrScalarFuncDef = {"pvdbcrScalar", 3,testArgs}; + +static void pvdbcrScalarCallFunc(const iocshArgBuf *args) +{ + char *sval = args[0].sval; + if(!sval) { + throw std::runtime_error("pvdbcrScalarCreate recordName not specified"); + } + string recordName = string(sval); + sval = args[1].sval; + if(!sval) { + throw std::runtime_error("pvdbcrScalarCreate scalarType not specified"); + } + string scalarType = string(sval); + int asLevel = args[2].ival; + try { + ScalarType st = epics::pvData::ScalarTypeFunc::getScalarType(scalarType); + NTScalarBuilderPtr ntScalarBuilder = NTScalar::createBuilder(); + PVStructurePtr pvStructure = ntScalarBuilder-> + value(st)-> + addAlarm()-> + addTimeStamp()-> + createPVStructure(); + PVRecordPtr record = PVRecord::create(recordName,pvStructure); + record->setAsLevel(asLevel); + PVDatabasePtr master = PVDatabase::getMaster(); + bool result = master->addRecord(record); + if(!result) cout << "recordname " << recordName << " not added" << endl; + } catch(std::exception& ex) { + cerr << "failure " << ex.what() << "/n"; + } +} + +static void pvdbcrScalarRegister(void) +{ + static int firstTime = 1; + if (firstTime) { + firstTime = 0; + iocshRegister(&pvdbcrScalarFuncDef, pvdbcrScalarCallFunc); + } +} + +extern "C" { + epicsExportRegistrar(pvdbcrScalarRegister); +} diff --git a/src/special/pvdbcrScalarRegister.dbd b/src/special/pvdbcrScalarRegister.dbd new file mode 100644 index 0000000..1202c71 --- /dev/null +++ b/src/special/pvdbcrScalarRegister.dbd @@ -0,0 +1 @@ +registrar("pvdbcrScalarRegister") diff --git a/src/special/pvdbcrTraceRecord.cpp b/src/special/pvdbcrTraceRecord.cpp new file mode 100644 index 0000000..e0a481a --- /dev/null +++ b/src/special/pvdbcrTraceRecord.cpp @@ -0,0 +1,95 @@ +/* pvdbcrTraceRecord.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 2021.03.12 + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define epicsExportSharedSymbols +#include "pv/pvStructureCopy.h" +#include "pv/channelProviderLocal.h" +#include "pv/pvdbcrTraceRecord.h" + +using std::tr1::static_pointer_cast; +using namespace epics::pvData; +using namespace epics::pvAccess; +using namespace std; + +namespace epics { namespace pvDatabase { + +PvdbcrTraceRecordPtr PvdbcrTraceRecord::create( + std::string const & recordName) +{ + FieldCreatePtr fieldCreate = getFieldCreate(); + PVDataCreatePtr pvDataCreate = getPVDataCreate(); + StructureConstPtr topStructure = fieldCreate->createFieldBuilder()-> + addNestedStructure("argument")-> + add("recordName",pvString)-> + add("level",pvInt)-> + endNested()-> + addNestedStructure("result") -> + add("status",pvString) -> + endNested()-> + createStructure(); + PVStructurePtr pvStructure = pvDataCreate->createPVStructure(topStructure); + PvdbcrTraceRecordPtr pvRecord( + new PvdbcrTraceRecord(recordName,pvStructure)); + if(!pvRecord->init()) pvRecord.reset(); + return pvRecord; +} + +PvdbcrTraceRecord::PvdbcrTraceRecord( + std::string const & recordName, + epics::pvData::PVStructurePtr const & pvStructure) +: PVRecord(recordName,pvStructure) +{ +} + + +bool PvdbcrTraceRecord::init() +{ + initPVRecord(); + PVStructurePtr pvStructure = getPVStructure(); + pvRecordName = pvStructure->getSubField("argument.recordName"); + if(!pvRecordName) return false; + pvLevel = pvStructure->getSubField("argument.level"); + if(!pvLevel) return false; + pvResult = pvStructure->getSubField("result.status"); + if(!pvResult) return false; + return true; +} + +void PvdbcrTraceRecord::process() +{ + string name = pvRecordName->get(); + PVRecordPtr pvRecord = PVDatabase::getMaster()->findRecord(name); + if(!pvRecord) { + pvResult->put(name + " not found"); + return; + } + pvRecord->setTraceLevel(pvLevel->get()); + pvResult->put("success"); +} + + +}} diff --git a/src/special/pvdbcrTraceRecordRegister.cpp b/src/special/pvdbcrTraceRecordRegister.cpp new file mode 100644 index 0000000..a9b5f0c --- /dev/null +++ b/src/special/pvdbcrTraceRecordRegister.cpp @@ -0,0 +1,65 @@ +/* + * Copyright information and license terms for this software can be + * found in the file LICENSE that is included with the distribution + */ + +/** + * @author mrk + * @date 2021.03.12 + */ + + +/* Author: Marty Kraimer */ + +#include +#include +#include +#include +#include +#include +#include +#include + +// The following must be the last include for code pvDatabase uses +#include +#define epicsExportSharedSymbols +#include "pv/pvStructureCopy.h" +#include "pv/pvDatabase.h" +#include "pv/pvdbcrTraceRecord.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 testArg1 = { "asLevel", iocshArgInt }; +static const iocshArg *testArgs[] = {&testArg0,&testArg1}; + +static const iocshFuncDef pvdbcrTraceRecordFuncDef = {"pvdbcrTraceRecord", 2,testArgs}; + +static void pvdbcrTraceRecordCallFunc(const iocshArgBuf *args) +{ + char *recordName = args[0].sval; + if(!recordName) { + throw std::runtime_error("traceRecordCreate invalid number of arguments"); + } + int asLevel = args[1].ival; + PvdbcrTraceRecordPtr record = PvdbcrTraceRecord::create(recordName); + record->setAsLevel(asLevel); + bool result = PVDatabase::getMaster()->addRecord(record); + if(!result) cout << "recordname" << " not added" << endl; +} + +static void pvdbcrTraceRecordRegister(void) +{ + static int firstTime = 1; + if (firstTime) { + firstTime = 0; + iocshRegister(&pvdbcrTraceRecordFuncDef, pvdbcrTraceRecordCallFunc); + } +} + +extern "C" { + epicsExportRegistrar(pvdbcrTraceRecordRegister); +} diff --git a/src/special/pvdbcrTraceRecordRegister.dbd b/src/special/pvdbcrTraceRecordRegister.dbd new file mode 100644 index 0000000..c525320 --- /dev/null +++ b/src/special/pvdbcrTraceRecordRegister.dbd @@ -0,0 +1 @@ +registrar("pvdbcrTraceRecordRegister") diff --git a/src/special/removeRecordRegister.cpp b/src/special/removeRecordRegister.cpp index c55f34a..4976c3e 100644 --- a/src/special/removeRecordRegister.cpp +++ b/src/special/removeRecordRegister.cpp @@ -39,6 +39,7 @@ static const iocshFuncDef removeRecordFuncDef = {"removeRecordCreate", 1,testArg static void removeRecordCallFunc(const iocshArgBuf *args) { + cerr << "DEPRECATED use pvdbcrRemoveRecord instead\n"; char *recordName = args[0].sval; if(!recordName) { throw std::runtime_error("removeRecordCreate invalid number of arguments"); diff --git a/src/special/traceRecordRegister.cpp b/src/special/traceRecordRegister.cpp index 57d20f4..3c60400 100644 --- a/src/special/traceRecordRegister.cpp +++ b/src/special/traceRecordRegister.cpp @@ -40,6 +40,7 @@ static const iocshFuncDef traceRecordFuncDef = {"traceRecordCreate", 1,testArgs} static void traceRecordCallFunc(const iocshArgBuf *args) { + cerr << "DEPRECATED use pvdbcrTraceRecord instead\n"; char *recordName = args[0].sval; if(!recordName) { throw std::runtime_error("traceRecordCreate invalid number of arguments");