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