diff --git a/src/Makefile b/src/Makefile index dfb2873..e0cb91c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -23,11 +23,6 @@ INC += pv/pvDatabase.h INC += pv/channelProviderLocal.h -#INC += pv/traceRecord.h -#INC += pv/removeRecord.h -#INC += pv/addRecord.h -#INC += pv/processRecord.h - INC += pv/pvSupport.h INC += pv/controlSupport.h INC += pv/scalarAlarmSupport.h diff --git a/src/pv/addRecord.h b/src/pv/addRecord.h deleted file mode 100644 index ef3ed17..0000000 --- a/src/pv/addRecord.h +++ /dev/null @@ -1,63 +0,0 @@ -/* 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 - -#include - -namespace epics { namespace pvDatabase { - - -class AddRecord; -typedef std::tr1::shared_ptr 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 */ diff --git a/src/pv/processRecord.h b/src/pv/processRecord.h deleted file mode 100644 index 6607e93..0000000 --- a/src/pv/processRecord.h +++ /dev/null @@ -1,89 +0,0 @@ -/* processRecord.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 2019.06.07 - */ -#ifndef PROCESSRECORD_H -#define PROCESSRECORD_H - -#include -#include -#include -#include - -#include - -namespace epics { namespace pvDatabase { - -typedef std::tr1::shared_ptr EpicsThreadPtr; - -class ProcessRecord; -typedef std::tr1::shared_ptr ProcessRecordPtr; - -/** - * @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 ProcessRecord : - public PVRecord, - public epicsThreadRunable -{ -public: - POINTER_DEFINITIONS(ProcessRecord); - /** - * 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 ProcessRecordPtr 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: - ProcessRecord( - 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 /* PROCESSRECORD_H */ diff --git a/src/pv/removeRecord.h b/src/pv/removeRecord.h deleted file mode 100644 index d101e1c..0000000 --- a/src/pv/removeRecord.h +++ /dev/null @@ -1,63 +0,0 @@ -/* removeRecord.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 REMOVERECORD_H -#define REMOVERECORD_H - -#include - -#include - -namespace epics { namespace pvDatabase { - - -class RemoveRecord; -typedef std::tr1::shared_ptr RemoveRecordPtr; - -/** - * @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 RemoveRecord : - public PVRecord -{ -public: - POINTER_DEFINITIONS(RemoveRecord); - /** - * Factory methods to create RemoveRecord. - * @param recordName The name for the RemoveRecord. - * @return A shared pointer to RemoveRecord.. - */ - static RemoveRecordPtr 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: - RemoveRecord( - std::string const & recordName, - epics::pvData::PVStructurePtr const & pvStructure); - epics::pvData::PVStringPtr pvRecordName; - epics::pvData::PVStringPtr pvResult; -}; - -}} - -#endif /* REMOVERECORD_H */ diff --git a/src/pv/traceRecord.h b/src/pv/traceRecord.h deleted file mode 100644 index 6ec5525..0000000 --- a/src/pv/traceRecord.h +++ /dev/null @@ -1,66 +0,0 @@ -/* traceRecord.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 TRACERECORD_H -#define TRACERECORD_H - -#include - -#include - - -namespace epics { namespace pvDatabase { - - -class TraceRecord; -typedef std::tr1::shared_ptr TraceRecordPtr; - -/** - * @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 TraceRecord : - public PVRecord -{ -public: - POINTER_DEFINITIONS(TraceRecord); - /** - * @brief Factory method to create TraceRecord. - * - * @param recordName The name for the TraceRecord. - * @return A shared pointer to TraceRecord.. - */ - static TraceRecordPtr 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: - TraceRecord( - std::string const & recordName, - epics::pvData::PVStructurePtr const & pvStructure); - epics::pvData::PVStringPtr pvRecordName; - epics::pvData::PVIntPtr pvLevel; - epics::pvData::PVStringPtr pvResult; -}; - -}} - -#endif /* TRACERECORD_H */ diff --git a/src/special/Makefile b/src/special/Makefile index 65b4942..95aa467 100644 --- a/src/special/Makefile +++ b/src/special/Makefile @@ -2,20 +2,15 @@ SRC_DIRS += $(PVDATABASE_SRC)/special -#LIBSRCS += traceRecord.cpp -#LIBSRCS += removeRecord.cpp -#LIBSRCS += addRecord.cpp -#LIBSRCS += processRecord.cpp +DBD += traceRecordRegister.dbd +DBD += removeRecordRegister.dbd +DBD += addRecordRegister.dbd +DBD += processRecordRegister.dbd -#DBD += traceRecordRegister.dbd -#DBD += removeRecordRegister.dbd -#DBD += addRecordRegister.dbd -#DBD += processRecordRegister.dbd - -#LIBSRCS += traceRecordRegister.cpp -#LIBSRCS += removeRecordRegister.cpp -#LIBSRCS += addRecordRegister.cpp -#LIBSRCS += processRecordRegister.cpp +LIBSRCS += traceRecordRegister.cpp +LIBSRCS += removeRecordRegister.cpp +LIBSRCS += addRecordRegister.cpp +LIBSRCS += processRecordRegister.cpp DBD += pvdbcrTraceRecordRegister.dbd DBD += pvdbcrRemoveRecordRegister.dbd diff --git a/src/special/addRecord.cpp b/src/special/addRecord.cpp deleted file mode 100644 index 698c8d4..0000000 --- a/src/special/addRecord.cpp +++ /dev/null @@ -1,116 +0,0 @@ -/* 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 -#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/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("argument.recordName"); - if(!pvRecordName) return false; - pvResult = pvStructure->getSubField("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("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/addRecordRegister.cpp b/src/special/addRecordRegister.cpp index 3306044..d39d0cd 100644 --- a/src/special/addRecordRegister.cpp +++ b/src/special/addRecordRegister.cpp @@ -5,11 +5,8 @@ /** * @author mrk - * @date 2013.07.24 + * @date 2021.03.12 */ - - -/* Author: Marty Kraimer */ #include #include #include @@ -17,37 +14,137 @@ #include #include #include +#include +#include -// The following must be the last include for code pvDatabase uses +// The following must be the last include for code exampleLink uses #include #define epicsExportSharedSymbols +#include "pv/pvStructureCopy.h" +#include "pv/channelProviderLocal.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 epics::pvDatabase; using namespace std; -static const iocshArg testArg0 = { "recordName", iocshArgString }; -static const iocshArg *testArgs[] = { - &testArg0}; +class AddRecord; +typedef std::tr1::shared_ptr AddRecordPtr; -static const iocshFuncDef addRecordFuncDef = {"addRecordCreate", 1,testArgs}; + +class epicsShareClass AddRecord : + public PVRecord +{ +private: + AddRecord( + std::string const & recordName, + epics::pvData::PVStructurePtr const & pvStructure); + PVStringPtr pvRecordName; + epics::pvData::PVStringPtr pvResult; +public: + POINTER_DEFINITIONS(AddRecord); + + static AddRecordPtr create( + std::string const & recordName); + virtual bool init(); + virtual void process(); +}; + +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, + PVStructurePtr const & pvStructure) +: PVRecord(recordName,pvStructure) +{ +} + +bool AddRecord::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 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("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"); + } +} + +static const iocshArg arg0 = { "recordName", iocshArgString }; +static const iocshArg *args[] = {&arg0}; + +static const iocshFuncDef addRecordFuncDef = {"addRecordCreate", 1,args}; 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"); + char *sval = args[0].sval; + if(!sval) { + throw std::runtime_error("addRecordCreate recordName not specified"); } + string recordName = string(sval); AddRecordPtr record = AddRecord::create(recordName); - bool result = PVDatabase::getMaster()->addRecord(record); - if(!result) cout << "recordname" << " not added" << endl; + PVDatabasePtr master = PVDatabase::getMaster(); + bool result = master->addRecord(record); + if(!result) cout << "recordname " << recordName << " not added" << endl; } -static void addRecordRegister(void) +static void addRecordCreateRegister(void) { static int firstTime = 1; if (firstTime) { @@ -57,5 +154,5 @@ static void addRecordRegister(void) } extern "C" { - epicsExportRegistrar(addRecordRegister); + epicsExportRegistrar(addRecordCreateRegister); } diff --git a/src/special/processRecord.cpp b/src/special/processRecord.cpp deleted file mode 100644 index c93ea3f..0000000 --- a/src/special/processRecord.cpp +++ /dev/null @@ -1,166 +0,0 @@ -/* processRecord.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 -#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/processRecord.h" - -using std::tr1::static_pointer_cast; -using namespace epics::pvData; -using namespace epics::pvAccess; -using namespace std; - -namespace epics { namespace pvDatabase { - -ProcessRecordPtr ProcessRecord::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); - ProcessRecordPtr pvRecord( - new ProcessRecord(recordName,pvStructure,delay)); - if(!pvRecord->init()) pvRecord.reset(); - return pvRecord; -} - -void ProcessRecord::startThread() -{ - thread = EpicsThreadPtr(new epicsThread( - *this, - "processRecord", - epicsThreadGetStackSize(epicsThreadStackSmall), - epicsThreadPriorityLow)); - thread->start(); -} - -void ProcessRecord::stop() -{ - runStop.signal(); - runReturn.wait(); -} - - -ProcessRecord::ProcessRecord( - std::string const & recordName, - epics::pvData::PVStructurePtr const & pvStructure,double delay) -: PVRecord(recordName,pvStructure), - delay(delay), - pvDatabase(PVDatabase::getMaster()) -{ -} - -bool ProcessRecord::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 ProcessRecord::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 ProcessRecord::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/processRecordRegister.cpp b/src/special/processRecordRegister.cpp index d69cda3..9293b15 100644 --- a/src/special/processRecordRegister.cpp +++ b/src/special/processRecordRegister.cpp @@ -5,11 +5,12 @@ /** * @author mrk - * @date 2013.07.24 + * @date 2021.03.12 */ - - -/* Author: Marty Kraimer */ +#include +#include +#include +#include #include #include #include @@ -17,38 +18,194 @@ #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/channelProviderLocal.h" #include "pv/pvDatabase.h" -#include "pv/processRecord.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 *testArgs[] = { - &testArg0,&testArg1}; +typedef std::tr1::shared_ptr EpicsThreadPtr; +class ProcessRecord; +typedef std::tr1::shared_ptr ProcessRecordPtr; -static const iocshFuncDef processRecordFuncDef = {"processRecordCreate", 2,testArgs}; +class epicsShareClass ProcessRecord : + public PVRecord, + public epicsThreadRunable +{ +public: + POINTER_DEFINITIONS(ProcessRecord); + static ProcessRecordPtr create( + std::string const & recordName,double delay); + virtual bool init(); + virtual void process(); + virtual void run(); + void startThread(); + void stop(); +private: + ProcessRecord( + 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; +}; + +ProcessRecordPtr ProcessRecord::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); + ProcessRecordPtr pvRecord( + new ProcessRecord(recordName,pvStructure,delay)); + if(!pvRecord->init()) pvRecord.reset(); + return pvRecord; +} + +void ProcessRecord::startThread() +{ + thread = EpicsThreadPtr(new epicsThread( + *this, + "processRecord", + epicsThreadGetStackSize(epicsThreadStackSmall), + epicsThreadPriorityLow)); + thread->start(); +} + +void ProcessRecord::stop() +{ + runStop.signal(); + runReturn.wait(); +} + + +ProcessRecord::ProcessRecord( + std::string const & recordName, + epics::pvData::PVStructurePtr const & pvStructure,double delay) +: PVRecord(recordName,pvStructure), + delay(delay), + pvDatabase(PVDatabase::getMaster()) +{ +} + +bool ProcessRecord::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 ProcessRecord::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 ProcessRecord::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(); + } + } +} + +static const iocshArg arg0 = { "recordName", iocshArgString }; +static const iocshArg arg1 = { "delay", iocshArgDouble }; +static const iocshArg *args[] = {&arg0,&arg1}; + +static const iocshFuncDef processRecordFuncDef = {"processRecordCreate", 2,args}; 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"); + char *sval = args[0].sval; + if(!sval) { + throw std::runtime_error("processRecord recordName not specified"); } + string recordName = string(sval); double delay = args[1].dval; if(delay<0.0) delay = 1.0; ProcessRecordPtr record = ProcessRecord::create(recordName,delay); - bool result = PVDatabase::getMaster()->addRecord(record); - if(!result) cout << "recordname" << " not added" << endl; + PVDatabasePtr master = PVDatabase::getMaster(); + bool result = master->addRecord(record); + if(!result) cout << "recordname " << recordName << " not added" << endl; } static void processRecordRegister(void) diff --git a/src/special/removeRecord.cpp b/src/special/removeRecord.cpp deleted file mode 100644 index 6bfc975..0000000 --- a/src/special/removeRecord.cpp +++ /dev/null @@ -1,91 +0,0 @@ -/* removeRecord.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 -#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/removeRecord.h" - -using std::tr1::static_pointer_cast; -using namespace epics::pvData; -using namespace epics::pvAccess; -using namespace std; - -namespace epics { namespace pvDatabase { - -RemoveRecordPtr RemoveRecord::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); - RemoveRecordPtr pvRecord( - new RemoveRecord(recordName,pvStructure)); - if(!pvRecord->init()) pvRecord.reset(); - return pvRecord; -} - -RemoveRecord::RemoveRecord( - std::string const & recordName, - epics::pvData::PVStructurePtr const & pvStructure) -: PVRecord(recordName,pvStructure) -{ -} - -bool RemoveRecord::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 RemoveRecord::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/removeRecordRegister.cpp b/src/special/removeRecordRegister.cpp index 280ee17..c1a264e 100644 --- a/src/special/removeRecordRegister.cpp +++ b/src/special/removeRecordRegister.cpp @@ -5,12 +5,8 @@ /** * @author mrk - * @date 2013.07.24 + * @date 2021.03.12 */ - - -/* Author: Marty Kraimer */ -#include #include #include #include @@ -18,34 +14,107 @@ #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/channelProviderLocal.h" #include "pv/pvDatabase.h" -#include "pv/removeRecord.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}; +class RemoveRecord; +typedef std::tr1::shared_ptr RemoveRecordPtr; -static const iocshFuncDef removeRecordFuncDef = {"removeRecordCreate", 1,testArgs}; + +class epicsShareClass RemoveRecord : + public PVRecord +{ +public: + POINTER_DEFINITIONS(RemoveRecord); + static RemoveRecordPtr create( + std::string const & recordName); + virtual bool init(); + virtual void process(); +private: + RemoveRecord( + std::string const & recordName, + epics::pvData::PVStructurePtr const & pvStructure); + epics::pvData::PVStringPtr pvRecordName; + epics::pvData::PVStringPtr pvResult; +}; + +RemoveRecordPtr RemoveRecord::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); + RemoveRecordPtr pvRecord( + new RemoveRecord(recordName,pvStructure)); + if(!pvRecord->init()) pvRecord.reset(); + return pvRecord; +} + +RemoveRecord::RemoveRecord( + std::string const & recordName, + epics::pvData::PVStructurePtr const & pvStructure) +: PVRecord(recordName,pvStructure) +{ +} + +bool RemoveRecord::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 RemoveRecord::process() +{ + string name = pvRecordName->get(); + PVRecordPtr pvRecord = PVDatabase::getMaster()->findRecord(name); + if(!pvRecord) { + pvResult->put(name + " not found"); + return; + } + pvRecord->remove(); + pvResult->put("success"); +} + +static const iocshArg arg0 = { "recordName", iocshArgString }; +static const iocshArg *args[] = {&arg0}; + +static const iocshFuncDef removeRecordFuncDef = {"removeRecordCreate", 1,args}; 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"); + char *sval = args[0].sval; + if(!sval) { + throw std::runtime_error("removeRecord recordName not specified"); } + string recordName = string(sval); RemoveRecordPtr record = RemoveRecord::create(recordName); - bool result = PVDatabase::getMaster()->addRecord(record); - if(!result) cout << "recordname" << " not added" << endl; + PVDatabasePtr master = PVDatabase::getMaster(); + bool result = master->addRecord(record); + if(!result) cout << "recordname " << recordName << " not added" << endl; } static void removeRecordRegister(void) diff --git a/src/special/traceRecord.cpp b/src/special/traceRecord.cpp deleted file mode 100644 index 1a32bcb..0000000 --- a/src/special/traceRecord.cpp +++ /dev/null @@ -1,95 +0,0 @@ -/* traceRecord.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 -#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/traceRecord.h" - -using std::tr1::static_pointer_cast; -using namespace epics::pvData; -using namespace epics::pvAccess; -using namespace std; - -namespace epics { namespace pvDatabase { - -TraceRecordPtr TraceRecord::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); - TraceRecordPtr pvRecord( - new TraceRecord(recordName,pvStructure)); - if(!pvRecord->init()) pvRecord.reset(); - return pvRecord; -} - -TraceRecord::TraceRecord( - std::string const & recordName, - epics::pvData::PVStructurePtr const & pvStructure) -: PVRecord(recordName,pvStructure) -{ -} - - -bool TraceRecord::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 TraceRecord::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/traceRecordRegister.cpp b/src/special/traceRecordRegister.cpp index ce555eb..c4f93ae 100644 --- a/src/special/traceRecordRegister.cpp +++ b/src/special/traceRecordRegister.cpp @@ -5,11 +5,8 @@ /** * @author mrk - * @date 2013.07.24 + * @date 2021.03.12 */ - - -/* Author: Marty Kraimer */ #include #include #include @@ -17,34 +14,113 @@ #include #include #include -#include +#include +#include -// The following must be the last include for code pvDatabase uses +// The following must be the last include #include #define epicsExportSharedSymbols -#include "pv/traceRecord.h" +#include "pv/pvStructureCopy.h" +#include "pv/channelProviderLocal.h" +#include "pv/pvDatabase.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}; +class TraceRecord; +typedef std::tr1::shared_ptr TraceRecordPtr; -static const iocshFuncDef traceRecordFuncDef = {"traceRecordCreate", 1,testArgs}; +class epicsShareClass TraceRecord : + public PVRecord +{ +public: + POINTER_DEFINITIONS(TraceRecord); + static TraceRecordPtr create( + std::string const & recordName); + virtual bool init(); + virtual void process(); +private: + TraceRecord( + std::string const & recordName, + epics::pvData::PVStructurePtr const & pvStructure); + epics::pvData::PVStringPtr pvRecordName; + epics::pvData::PVIntPtr pvLevel; + epics::pvData::PVStringPtr pvResult; +}; + +TraceRecordPtr TraceRecord::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); + TraceRecordPtr pvRecord( + new TraceRecord(recordName,pvStructure)); + if(!pvRecord->init()) pvRecord.reset(); + return pvRecord; +} + +TraceRecord::TraceRecord( + std::string const & recordName, + epics::pvData::PVStructurePtr const & pvStructure) +: PVRecord(recordName,pvStructure) +{ +} + + +bool TraceRecord::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 TraceRecord::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"); +} + +static const iocshArg arg0 = { "recordName", iocshArgString }; +static const iocshArg *args[] = {&arg0}; + +static const iocshFuncDef traceRecordFuncDef = {"traceRecordCreate", 1,args}; 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"); + char *sval = args[0].sval; + if(!sval) { + throw std::runtime_error("traceRecord recordName not specified"); } + string recordName = string(sval); TraceRecordPtr record = TraceRecord::create(recordName); - bool result = PVDatabase::getMaster()->addRecord(record); - if(!result) cout << "recordname" << " not added" << endl; + PVDatabasePtr master = PVDatabase::getMaster(); + bool result = master->addRecord(record); + if(!result) cout << "recordname " << recordName << " not added" << endl; } static void traceRecordRegister(void)