2
2
#include < string.h>
3
3
#include < stdio.h>
4
4
5
- #include < pv/pvDatabase.h>
5
+ #include < pv/pvAccess.h>
6
+ #include < pva/server.h>
7
+ #include < pva/sharedstate.h>
6
8
#include < pv/nt.h>
7
- #include < pv/channelProviderLocal.h>
8
9
9
10
#include < iocsh.h>
10
11
16
17
17
18
static const char *driverName=" NDPluginPva" ;
18
19
19
- using namespace epics ;
20
- using namespace epics ::pvData;
21
- using namespace epics ::pvAccess;
22
- using namespace epics ::pvDatabase;
23
- using namespace epics ::nt;
24
- using namespace std ;
25
-
26
- class NDPLUGIN_API NTNDArrayRecord :
27
- public PVRecord
28
- {
29
-
30
- private:
31
- NTNDArrayRecord (string const & name, PVStructurePtr const & pvStructure)
32
- :PVRecord(name, pvStructure) {}
33
-
34
- NTNDArrayPtr m_ntndArray;
35
- NTNDArrayConverterPtr m_converter;
36
-
37
- public:
38
- POINTER_DEFINITIONS (NTNDArrayRecord);
39
-
40
- virtual ~NTNDArrayRecord () {}
41
- static NTNDArrayRecordPtr create (string const & name);
42
- virtual bool init ();
43
- virtual void process () {}
44
- void update (NDArray *pArray);
20
+ namespace pvd = epics::pvData;
21
+ namespace pva = epics::pvAccess;
22
+ namespace nt = epics::nt;
23
+
24
+ namespace {
25
+ /* pvDatabase compatibility
26
+ * Sends all fields which are assigned by NTNDArrayConverter,
27
+ * regardless of whether they change.
28
+ */
29
+ struct BitMarker : public pvd ::PostHandler {
30
+ const pvd::PVFieldPtr fld;
31
+ const pvd::BitSetPtr mask;
32
+
33
+ BitMarker (const pvd::PVFieldPtr& fld,
34
+ const pvd::BitSetPtr& mask)
35
+ :fld(fld)
36
+ ,mask(mask)
37
+ {}
38
+ virtual ~BitMarker () {}
39
+
40
+ virtual void postPut () OVERRIDE FINAL
41
+ {
42
+ mask->set (fld->getFieldOffset ());
43
+ }
45
44
};
46
-
47
- NTNDArrayRecordPtr NTNDArrayRecord::create (string const & name)
48
- {
49
- NTNDArrayBuilderPtr builder = NTNDArray::createBuilder ();
50
- builder->addDescriptor ()->addTimeStamp ()->addAlarm ()->addDisplay ();
51
-
52
- NTNDArrayRecordPtr pvRecord (new NTNDArrayRecord (name,
53
- builder->createPVStructure ()));
54
-
55
- if (!pvRecord->init ())
56
- pvRecord.reset ();
57
-
58
- return pvRecord;
59
- }
60
-
61
- bool NTNDArrayRecord::init ()
62
- {
63
- initPVRecord ();
64
- m_ntndArray = NTNDArray::wrap (getPVStructure ());
65
- m_converter.reset (new NTNDArrayConverter (m_ntndArray));
66
- return true ;
67
45
}
68
46
69
- void NTNDArrayRecord::update (NDArray *pArray)
47
+ class NTNDArrayRecord
70
48
{
71
- lock ();
72
-
73
- try
49
+ public:
50
+ pvas::StaticProvider provider;
51
+ pvas::SharedPV::shared_pointer pv;
52
+
53
+ const pvd::PVStructurePtr current;
54
+ // wraps 'current'
55
+ const nt::NTNDArrayPtr m_ntndArray;
56
+ NTNDArrayConverter m_converter;
57
+
58
+ pvd::BitSetPtr changes;
59
+
60
+ NTNDArrayRecord (const std::string& name)
61
+ :provider(pvas::StaticProvider(name))
62
+ ,current(nt::NTNDArray::createBuilder()
63
+ ->addDescriptor ()->addTimeStamp()->addAlarm()->addDisplay()
64
+ ->createPVStructure())
65
+ ,m_ntndArray(nt::NTNDArray::wrap(current))
66
+ ,m_converter(m_ntndArray)
67
+ ,changes(new pvd::BitSet(current->getNumberFields ()))
74
68
{
75
- beginGroupPut ();
76
- m_converter->fromArray (pArray);
77
- endGroupPut ();
69
+ pvas::SharedPV::Config pv_conf;
70
+ // pvDatabase compatibility mode for pvRequest handling
71
+ pv_conf.mapperMode = pvd::PVRequestMapper::Slice;
72
+
73
+ pv = pvas::SharedPV::buildReadOnly (&pv_conf);
74
+ pv->open (*current);
75
+ provider.add (name, pv);
76
+
77
+ {
78
+ const pvd::PVFieldPtrArray& fields (current->getPVFields ());
79
+ for (size_t i=0 , N=fields.size (); i<N; i++) {
80
+ std::tr1::shared_ptr<BitMarker> temp (new BitMarker (fields[i], changes));
81
+ fields[i]->setPostHandler (temp);
82
+ }
83
+ }
78
84
}
79
- catch (...)
85
+
86
+ void update (NDArray *pArray)
80
87
{
81
- endGroupPut ();
82
- unlock ();
83
- throw ;
88
+ changes->clear ();
89
+ // through several levels of indirection, updates this->current
90
+ // and through several more, updates this->changes
91
+ m_converter.fromArray (pArray);
92
+
93
+ // SharedPV::post() makes a lightweight copy of *current,
94
+ // so we may safely continue to change it.
95
+
96
+ pv->post (*current, *changes);
84
97
}
85
- unlock ();
86
- }
98
+ };
87
99
88
100
/* * Callback function that is called by the NDArray driver with new NDArray
89
101
* data.
@@ -155,12 +167,12 @@ NDPluginPva::NDPluginPva(const char *portName, int queueSize,
155
167
: NDPluginDriver(portName, queueSize, blockingCallbacks,
156
168
NDArrayPort, NDArrayAddr, 1 , maxBuffers, maxMemory, 0 , 0 ,
157
169
0 , 1 , priority, stackSize, 1 , true ),
158
- m_record(NTNDArrayRecord::create (pvName))
170
+ m_record(new NTNDArrayRecord(pvName))
159
171
{
160
172
createParam (NDPluginPvaPvNameString, asynParamOctet, &NDPluginPvaPvName);
161
173
162
174
if (!m_record.get ())
163
- throw runtime_error (" failed to create NTNDArrayRecord" );
175
+ throw std:: runtime_error (" failed to create NTNDArrayRecord" );
164
176
165
177
/* Set the plugin type string */
166
178
setStringParam (NDPluginDriverPluginType, " NDPluginPva" );
@@ -171,13 +183,12 @@ NDPluginPva::NDPluginPva(const char *portName, int queueSize,
171
183
/* Try to connect to the NDArray port */
172
184
connectToArrayPort ();
173
185
174
- PVDatabasePtr master = PVDatabase::getMaster ();
175
- ChannelProviderLocalPtr channelProvider = getChannelProviderLocal ();
176
-
177
- if (!master->addRecord (m_record))
178
- throw runtime_error (" couldn't add record to master database" );
186
+ pva::ChannelProviderRegistry::servers ()
187
+ ->addSingleton (m_record->provider .provider ());
179
188
}
180
189
190
+ NDPluginPva::~NDPluginPva () {}
191
+
181
192
/* Configuration routine. Called directly, or from the iocsh function */
182
193
extern " C" int NDPvaConfigure (const char *portName, int queueSize,
183
194
int blockingCallbacks, const char *NDArrayPort, int NDArrayAddr,
0 commit comments