diff --git a/documentation/RELEASE_NOTES.md b/documentation/RELEASE_NOTES.md
index 0f13396..641d4a1 100644
--- a/documentation/RELEASE_NOTES.md
+++ b/documentation/RELEASE_NOTES.md
@@ -2,10 +2,11 @@
This document summarizes the changes to the module between releases.
-## Release 4.6.0 (EPICS 7.0.5.* March 2021)
+## Release 4.6.0 (EPICS 7.0.5.* April 2021)
* Access Security is now supported.
* special has been revised and extended.
+* addRecord, removeRecord, processRecord, and traceRecord are replaced by pvdbcr versions.
* support is DEPRECATED
## Release 4.5.3 (EPICS 7.0.5 Feb 2021)
diff --git a/src/special/Makefile b/src/special/Makefile
index 95aa467..fe47e3e 100644
--- a/src/special/Makefile
+++ b/src/special/Makefile
@@ -2,16 +2,6 @@
SRC_DIRS += $(PVDATABASE_SRC)/special
-DBD += traceRecordRegister.dbd
-DBD += removeRecordRegister.dbd
-DBD += addRecordRegister.dbd
-DBD += processRecordRegister.dbd
-
-LIBSRCS += traceRecordRegister.cpp
-LIBSRCS += removeRecordRegister.cpp
-LIBSRCS += addRecordRegister.cpp
-LIBSRCS += processRecordRegister.cpp
-
DBD += pvdbcrTraceRecordRegister.dbd
DBD += pvdbcrRemoveRecordRegister.dbd
DBD += pvdbcrAddRecordRegister.dbd
diff --git a/src/special/addRecordRegister.cpp b/src/special/addRecordRegister.cpp
deleted file mode 100644
index d39d0cd..0000000
--- a/src/special/addRecordRegister.cpp
+++ /dev/null
@@ -1,158 +0,0 @@
-/*
- * 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
- */
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-// 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"
-using std::tr1::static_pointer_cast;
-using namespace epics::pvData;
-using namespace epics::pvAccess;
-using namespace epics::pvDatabase;
-using namespace std;
-
-class AddRecord;
-typedef std::tr1::shared_ptr AddRecordPtr;
-
-
-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 *sval = args[0].sval;
- if(!sval) {
- throw std::runtime_error("addRecordCreate recordName not specified");
- }
- string recordName = string(sval);
- AddRecordPtr record = AddRecord::create(recordName);
- PVDatabasePtr master = PVDatabase::getMaster();
- bool result = master->addRecord(record);
- if(!result) cout << "recordname " << recordName << " not added" << endl;
-}
-
-static void addRecordCreateRegister(void)
-{
- static int firstTime = 1;
- if (firstTime) {
- firstTime = 0;
- iocshRegister(&addRecordFuncDef, addRecordCallFunc);
- }
-}
-
-extern "C" {
- epicsExportRegistrar(addRecordCreateRegister);
-}
diff --git a/src/special/addRecordRegister.dbd b/src/special/addRecordRegister.dbd
deleted file mode 100644
index 3983cfb..0000000
--- a/src/special/addRecordRegister.dbd
+++ /dev/null
@@ -1 +0,0 @@
-registrar("addRecordRegister")
diff --git a/src/special/processRecordRegister.cpp b/src/special/processRecordRegister.cpp
deleted file mode 100644
index 9293b15..0000000
--- a/src/special/processRecordRegister.cpp
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * 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
- */
-#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/pvDatabase.h"
-using namespace epics::pvData;
-using namespace epics::pvAccess;
-using namespace epics::pvDatabase;
-using namespace std;
-
-typedef std::tr1::shared_ptr EpicsThreadPtr;
-class ProcessRecord;
-typedef std::tr1::shared_ptr ProcessRecordPtr;
-
-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 *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);
- PVDatabasePtr master = PVDatabase::getMaster();
- bool result = master->addRecord(record);
- if(!result) cout << "recordname " << recordName << " not added" << endl;
-}
-
-static void processRecordRegister(void)
-{
- static int firstTime = 1;
- if (firstTime) {
- firstTime = 0;
- iocshRegister(&processRecordFuncDef, processRecordCallFunc);
- }
-}
-
-extern "C" {
- epicsExportRegistrar(processRecordRegister);
-}
diff --git a/src/special/processRecordRegister.dbd b/src/special/processRecordRegister.dbd
deleted file mode 100644
index fd8f945..0000000
--- a/src/special/processRecordRegister.dbd
+++ /dev/null
@@ -1 +0,0 @@
-registrar("processRecordRegister")
diff --git a/src/special/removeRecordRegister.cpp b/src/special/removeRecordRegister.cpp
deleted file mode 100644
index c1a264e..0000000
--- a/src/special/removeRecordRegister.cpp
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * 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
- */
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-#include
-#define epicsExportSharedSymbols
-#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;
-
-class RemoveRecord;
-typedef std::tr1::shared_ptr RemoveRecordPtr;
-
-
-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 *sval = args[0].sval;
- if(!sval) {
- throw std::runtime_error("removeRecord recordName not specified");
- }
- string recordName = string(sval);
- RemoveRecordPtr record = RemoveRecord::create(recordName);
- PVDatabasePtr master = PVDatabase::getMaster();
- bool result = master->addRecord(record);
- if(!result) cout << "recordname " << recordName << " not added" << endl;
-}
-
-static void removeRecordRegister(void)
-{
- static int firstTime = 1;
- if (firstTime) {
- firstTime = 0;
- iocshRegister(&removeRecordFuncDef, removeRecordCallFunc);
- }
-}
-
-extern "C" {
- epicsExportRegistrar(removeRecordRegister);
-}
diff --git a/src/special/removeRecordRegister.dbd b/src/special/removeRecordRegister.dbd
deleted file mode 100644
index aff2356..0000000
--- a/src/special/removeRecordRegister.dbd
+++ /dev/null
@@ -1 +0,0 @@
-registrar("removeRecordRegister")
diff --git a/src/special/traceRecordRegister.cpp b/src/special/traceRecordRegister.cpp
deleted file mode 100644
index c4f93ae..0000000
--- a/src/special/traceRecordRegister.cpp
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * 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
- */
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-#include
-
-// The following must be the last include
-#include
-#define epicsExportSharedSymbols
-#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;
-
-class TraceRecord;
-typedef std::tr1::shared_ptr TraceRecordPtr;
-
-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 *sval = args[0].sval;
- if(!sval) {
- throw std::runtime_error("traceRecord recordName not specified");
- }
- string recordName = string(sval);
- TraceRecordPtr record = TraceRecord::create(recordName);
- PVDatabasePtr master = PVDatabase::getMaster();
- bool result = master->addRecord(record);
- if(!result) cout << "recordname " << recordName << " not added" << endl;
-}
-
-static void traceRecordRegister(void)
-{
- static int firstTime = 1;
- if (firstTime) {
- firstTime = 0;
- iocshRegister(&traceRecordFuncDef, traceRecordCallFunc);
- }
-}
-
-extern "C" {
- epicsExportRegistrar(traceRecordRegister);
-}
diff --git a/src/special/traceRecordRegister.dbd b/src/special/traceRecordRegister.dbd
deleted file mode 100644
index 4dde906..0000000
--- a/src/special/traceRecordRegister.dbd
+++ /dev/null
@@ -1 +0,0 @@
-registrar("traceRecordRegister")