Skip to content

Commit

Permalink
switch from pvDatabase to SharedPV
Browse files Browse the repository at this point in the history
  • Loading branch information
mdavidsaver committed Jul 7, 2022
1 parent a478483 commit 1f25345
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 69 deletions.
151 changes: 82 additions & 69 deletions ADApp/pluginSrc/NDPluginPva.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,10 @@
#include <string.h>
#include <stdio.h>

#include <pv/pvDatabase.h>
#include <pv/pvAccess.h>
#include <pva/server.h>
#include <pva/sharedstate.h>
#include <pv/nt.h>
#include <pv/channelProviderLocal.h>

#include <iocsh.h>

Expand All @@ -16,74 +17,87 @@

static const char *driverName="NDPluginPva";

using namespace epics;
using namespace epics::pvData;
using namespace epics::pvAccess;
using namespace epics::pvDatabase;
using namespace epics::nt;
using namespace std;

class NDPLUGIN_API NTNDArrayRecord :
public PVRecord
{

private:
NTNDArrayRecord(string const & name, PVStructurePtr const & pvStructure)
:PVRecord(name, pvStructure) {}

NTNDArrayPtr m_ntndArray;
NTNDArrayConverterPtr m_converter;

public:
POINTER_DEFINITIONS(NTNDArrayRecord);

virtual ~NTNDArrayRecord () {}
static NTNDArrayRecordPtr create (string const & name);
virtual bool init ();
virtual void process () {}
void update (NDArray *pArray);
namespace pvd = epics::pvData;
namespace pva = epics::pvAccess;
namespace nt = epics::nt;

namespace {
/* pvDatabase compatibility
* Sends all fields which are assigned by NTNDArrayConverter,
* regardless of whether they change.
*/
struct BitMarker : public pvd::PostHandler {
const pvd::PVFieldPtr fld;
const pvd::BitSetPtr mask;

BitMarker(const pvd::PVFieldPtr& fld,
const pvd::BitSetPtr& mask)
:fld(fld)
,mask(mask)
{}
virtual ~BitMarker() {}

virtual void postPut() OVERRIDE FINAL
{
mask->set(fld->getFieldOffset());
}
};

NTNDArrayRecordPtr NTNDArrayRecord::create (string const & name)
{
NTNDArrayBuilderPtr builder = NTNDArray::createBuilder();
builder->addDescriptor()->addTimeStamp()->addAlarm()->addDisplay();

NTNDArrayRecordPtr pvRecord(new NTNDArrayRecord(name,
builder->createPVStructure()));

if(!pvRecord->init())
pvRecord.reset();

return pvRecord;
}

bool NTNDArrayRecord::init ()
{
initPVRecord();
m_ntndArray = NTNDArray::wrap(getPVStructure());
m_converter.reset(new NTNDArrayConverter(m_ntndArray));
return true;
}

void NTNDArrayRecord::update(NDArray *pArray)
class NTNDArrayRecord
{
lock();

try
public:
pvas::StaticProvider provider;
pvas::SharedPV::shared_pointer pv;

const pvd::PVStructurePtr current;
// wraps 'current'
const nt::NTNDArrayPtr m_ntndArray;
NTNDArrayConverter m_converter;

pvd::BitSetPtr changes;

NTNDArrayRecord(const std::string& name)
:provider(pvas::StaticProvider(name))
,current(nt::NTNDArray::createBuilder()
->addDescriptor()->addTimeStamp()->addAlarm()->addDisplay()
->createPVStructure())
,m_ntndArray(nt::NTNDArray::wrap(current))
,m_converter(m_ntndArray)
,changes(new pvd::BitSet(current->getNumberFields()))
{
beginGroupPut();
m_converter->fromArray(pArray);
endGroupPut();
pvas::SharedPV::Config pv_conf;
// pvDatabase compatibility mode for pvRequest handling
pv_conf.mapperMode = pvd::PVRequestMapper::Slice;

pv = pvas::SharedPV::buildReadOnly(&pv_conf);
pv->open(*current);
provider.add(name, pv);

{
std::tr1::shared_ptr<BitMarker> temp(new BitMarker(current, changes));
current->setPostHandler(temp);
}
for(size_t i=current->getFieldOffset()+1u, N=current->getNextFieldOffset(); i<N; i++) {
pvd::PVFieldPtr fld(current->getSubFieldT(i));
std::tr1::shared_ptr<BitMarker> temp(new BitMarker(fld, changes));
fld->setPostHandler(temp);
}
}
catch(...)

void update(NDArray *pArray)
{
endGroupPut();
unlock();
throw;
changes->clear();
// through several levels of indirection, updates this->current
// and through several more, updates this->changes
m_converter.fromArray(pArray);

// SharedPV::post() makes a lightweight copy of *current,
// so we may safely continue to change it.

pv->post(*current, *changes);
}
unlock();
}
};

/** Callback function that is called by the NDArray driver with new NDArray
* data.
Expand Down Expand Up @@ -155,12 +169,12 @@ NDPluginPva::NDPluginPva(const char *portName, int queueSize,
: NDPluginDriver(portName, queueSize, blockingCallbacks,
NDArrayPort, NDArrayAddr, 1, maxBuffers, maxMemory, 0, 0,
0, 1, priority, stackSize, 1, true),
m_record(NTNDArrayRecord::create(pvName))
m_record(new NTNDArrayRecord(pvName))
{
createParam(NDPluginPvaPvNameString, asynParamOctet, &NDPluginPvaPvName);

if(!m_record.get())
throw runtime_error("failed to create NTNDArrayRecord");
throw std::runtime_error("failed to create NTNDArrayRecord");

/* Set the plugin type string */
setStringParam(NDPluginDriverPluginType, "NDPluginPva");
Expand All @@ -171,13 +185,12 @@ NDPluginPva::NDPluginPva(const char *portName, int queueSize,
/* Try to connect to the NDArray port */
connectToArrayPort();

PVDatabasePtr master = PVDatabase::getMaster();
ChannelProviderLocalPtr channelProvider = getChannelProviderLocal();

if(!master->addRecord(m_record))
throw runtime_error("couldn't add record to master database");
pva::ChannelProviderRegistry::servers()
->addSingleton(m_record->provider.provider());
}

NDPluginPva::~NDPluginPva() {}

/* Configuration routine. Called directly, or from the iocsh function */
extern "C" int NDPvaConfigure(const char *portName, int queueSize,
int blockingCallbacks, const char *NDArrayPort, int NDArrayAddr,
Expand Down
1 change: 1 addition & 0 deletions ADApp/pluginSrc/NDPluginPva.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ class NDPLUGIN_API NDPluginPva : public NDPluginDriver,
NDPluginPva(const char *portName, int queueSize, int blockingCallbacks,
const char *NDArrayPort, int NDArrayAddr, const char *pvName,
int maxBuffers, size_t maxMemory, int priority, int stackSize);
virtual ~NDPluginPva();

/* These methods override the virtual methods in the base class */
void processCallbacks(NDArray *pArray);
Expand Down

0 comments on commit 1f25345

Please sign in to comment.