12 #include <epicsGuard.h> 13 #include <epicsThread.h> 14 #include <pv/status.h> 15 #include <pv/pvAccess.h> 16 #include <pv/createRequest.h> 17 #include <pv/pvaVersion.h> 18 #include <pv/pvaVersionNum.h> 19 #include <pv/monitor.h> 20 #include <pv/convert.h> 21 #include <pv/rpcService.h> 22 #include <pv/timeStamp.h> 23 #include <pv/pvData.h> 24 #include <pv/rpcService.h> 25 #include <pv/pvTimeStamp.h> 27 #define epicsExportSharedSymbols 31 using std::tr1::static_pointer_cast;
36 namespace epics {
namespace pvDatabase {
39 string const &recordName,
40 PVStructurePtr
const & pvStructure)
43 if(!pvRecord->init()) {
51 string const & recordName,
52 PVStructurePtr
const & pvStructure)
53 : recordName(recordName),
54 pvStructure(pvStructure),
61 void PVRecord::notifyClients()
64 epicsGuard<epics::pvData::Mutex> guard(mutex);
66 cout <<
"PVRecord::notifyClients() " << recordName
71 for(std::list<PVListenerWPtr>::iterator iter = pvListenerList.begin();
72 iter!=pvListenerList.end();
76 if(!listener)
continue;
78 cout <<
"PVRecord::notifyClients() calling listener->unlisten " 79 << recordName << endl;
81 listener->unlisten(shared_from_this());
83 pvListenerList.clear();
84 for (std::list<PVRecordClientWPtr>::iterator iter = clientList.begin();
85 iter!=clientList.end();
91 cout <<
"PVRecord::notifyClients() calling client->detach " 92 << recordName << endl;
94 client->detach(shared_from_this());
97 cout <<
"PVRecord::notifyClients() calling clientList.clear() " 98 << recordName << endl;
102 cout <<
"PVRecord::notifyClients() returning " << recordName << endl;
109 cout <<
"~PVRecord() " << recordName << endl;
117 if(pvDatabase) pvDatabase->removeRecord(shared_from_this());
118 pvTimeStamp.detach();
119 for(std::list<PVListenerWPtr>::iterator iter = pvListenerList.begin();
120 iter!=pvListenerList.end();
124 if(!listener)
continue;
126 cout <<
"PVRecord::remove() calling listener->unlisten " << recordName << endl;
128 listener->unlisten(shared_from_this());
130 pvListenerList.clear();
131 for (std::list<PVRecordClientWPtr>::iterator iter = clientList.begin();
132 iter!=clientList.end();
136 if(!client)
continue;
138 cout <<
"PVRecord::remove() calling client->detach " << recordName << endl;
140 client->detach(shared_from_this());
150 pvRecordStructure->init();
151 PVFieldPtr pvField = pvStructure->getSubField(
"timeStamp");
152 if(pvField) pvTimeStamp.attach(pvField);
158 cout <<
"PVRecord::process() " << recordName << endl;
160 if(pvTimeStamp.isAttached()) {
161 pvTimeStamp.get(timeStamp);
162 timeStamp.getCurrent();
163 pvTimeStamp.set(timeStamp);
175 PVFieldPtr
const & pvField)
177 size_t desiredOffset = pvField->getFieldOffset();
178 PVFieldPtr pvf = pvrs->getPVField();
179 size_t offset = pvf->getFieldOffset();
180 if(offset==desiredOffset)
return pvrs;
182 PVRecordFieldPtrArray::iterator iter;
183 for (iter = pvrfpap.get()->begin(); iter!=pvrfpap.get()->end(); iter++ ) {
185 pvf = pvrf->getPVField();
186 offset = pvf->getFieldOffset();
187 if(offset==desiredOffset)
return pvrf;
188 size_t nextOffset = pvf->getNextFieldOffset();
189 if(nextOffset<=desiredOffset)
continue;
191 static_pointer_cast<PVRecordStructure>(pvrf),
194 throw std::logic_error(
195 recordName +
" pvField " 196 + pvField->getFieldName() +
" not in PVRecord");
201 cout <<
"PVRecord::lock() " << recordName << endl;
208 cout <<
"PVRecord::unlock() " << recordName << endl;
215 cout <<
"PVRecord::tryLock() " << recordName << endl;
217 return mutex.tryLock();
223 cout <<
"PVRecord::lockOtherRecord() " << recordName << endl;
225 if(
this<otherRecord.get()) {
237 cout <<
"PVRecord::addPVRecordClient() " << recordName << endl;
239 epicsGuard<epics::pvData::Mutex> guard(mutex);
241 bool clientListClean =
false;
242 while(!clientListClean) {
243 if(clientList.empty())
break;
244 clientListClean =
true;
245 std::list<PVRecordClientWPtr>::iterator iter;
246 for (iter = clientList.begin();
247 iter!=clientList.end();
253 cout <<
"PVRecord::addPVRecordClient() erasing client" 254 << recordName << endl;
256 clientList.erase(iter);
257 clientListClean =
false;
261 clientList.push_back(pvRecordClient);
270 cout <<
"PVRecord::addListener() " << recordName << endl;
272 epicsGuard<epics::pvData::Mutex> guard(mutex);
273 pvListenerList.push_back(pvListener);
274 this->pvListener = pvListener;
275 isAddListener =
true;
276 pvCopy->traverseMaster(shared_from_this());
285 if(!listener.get())
return;
287 pvRecordField->addListener(listener);
289 pvRecordField->removeListener(listener);
298 cout <<
"PVRecord::removeListener() " << recordName << endl;
300 epicsGuard<epics::pvData::Mutex> guard(mutex);
301 std::list<PVListenerWPtr>::iterator iter;
302 for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); iter++ )
305 if(!listener.get())
continue;
306 if(listener.get()==pvListener.get()) {
307 pvListenerList.erase(iter);
308 this->pvListener = pvListener;
309 isAddListener =
false;
310 pvCopy->traverseMaster(shared_from_this());
320 if(++depthGroupPut>1)
return;
322 cout <<
"PVRecord::beginGroupPut() " << recordName << endl;
324 std::list<PVListenerWPtr>::iterator iter;
325 for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); iter++)
328 if(!listener.get())
continue;
329 listener->beginGroupPut(shared_from_this());
335 if(--depthGroupPut>0)
return;
337 cout <<
"PVRecord::endGroupPut() " << recordName << endl;
339 std::list<PVListenerWPtr>::iterator iter;
340 for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); iter++)
343 if(!listener.get())
continue;
344 listener->endGroupPut(shared_from_this());
350 o << format::indent() <<
"record " << record.
getRecordName() << endl;
352 format::indent_scope s(o);
359 PVFieldPtr
const & pvField,
363 isStructure(pvField->getField()->getType()==structure ? true : false),
371 fullFieldName = pvField.lock()->getFieldName();
374 string parentName = pvParent->getPVField()->getFieldName();
375 if(parentName.size()>0) {
376 fullFieldName = pvParent->getPVField()->getFieldName()
377 +
'.' + fullFieldName;
379 pvParent = pvParent->getParent();
382 if(fullFieldName.size()>0) {
383 fullName = pvRecord->getRecordName() +
'.' + fullFieldName;
385 fullName = pvRecord->getRecordName();
387 pvField.lock()->setPostHandler(shared_from_this());
392 return parent.lock();
403 bool PVRecordField::addListener(
PVListenerPtr const & pvListener)
406 if(pvRecord && pvRecord->getTraceLevel()>1) {
407 cout <<
"PVRecordField::addListener() " <<
getFullName() << endl;
409 pvListenerList.push_back(pvListener);
413 void PVRecordField::removeListener(
PVListenerPtr const & pvListener)
416 if(pvRecord && pvRecord->getTraceLevel()>1) {
417 cout <<
"PVRecordField::removeListener() " <<
getFullName() << endl;
419 std::list<PVListenerWPtr>::iterator iter;
420 for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); iter++ ) {
422 if(!listener.get())
continue;
423 if(listener.get()==pvListener.get()) {
424 pvListenerList.erase(iter);
434 parent->postParent(shared_from_this());
442 std::list<PVListenerWPtr>::iterator iter;
443 for(iter = pvListenerList.begin(); iter != pvListenerList.end(); ++iter)
446 if(!listener.get())
continue;
447 listener->dataPut(pvrs,subField);
450 if(parent) parent->postParent(subField);
460 PVRecordFieldPtrArray::iterator iter;
461 for(iter = pvRecordFields->begin() ; iter !=pvRecordFields->end(); iter++) {
462 (*iter)->postSubField();
467 void PVRecordField::callListener()
469 std::list<PVListenerWPtr>::iterator iter;
470 for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); iter++ ) {
472 if(!listener.get())
continue;
473 listener->dataPut(shared_from_this());
478 PVStructurePtr
const &pvStructure,
483 pvStructure(pvStructure),
491 const PVFieldPtrArray & pvFields = pvStructure.lock()->getPVFields();
492 size_t numFields = pvFields.size();
493 pvRecordFields->reserve( numFields);
497 for(
size_t i=0; i<numFields; i++) {
498 PVFieldPtr pvField = pvFields[i];
499 if(pvField->getField()->getType()==structure) {
500 PVStructurePtr xxx = static_pointer_cast<PVStructure>(pvField);
503 pvRecordFields->push_back(pvRecordStructure);
504 pvRecordStructure->init();
508 pvRecordFields->push_back(pvRecordField);
509 pvRecordField->init();
516 return pvRecordFields;
bool removeListener(PVListenerPtr const &pvListener, epics::pvCopy::PVCopyPtr const &pvCopy)
Remove a listener.
bool addPVRecordClient(PVRecordClientPtr const &pvRecordClient)
Add a client that wants to access the record.
virtual void process()
Optional method for derived class.
epics::pvData::PVStructurePtr getPVStructure()
Get the data structure/.
std::tr1::shared_ptr< PVListener > PVListenerPtr
std::tr1::shared_ptr< PVCopy > PVCopyPtr
void lockOtherRecord(PVRecordPtr const &otherRecord)
Lock another record.
virtual void remove()
remove record from database.
void lock()
Lock the record.
std::tr1::shared_ptr< PVRecordClient > PVRecordClientPtr
PVRecordField(epics::pvData::PVFieldPtr const &pvField, PVRecordStructurePtr const &parent, PVRecordPtr const &pvRecord)
Constructor.
void nextMasterPVField(epics::pvData::PVFieldPtr const &pvField)
PVCopyTraverseMasterCallback method.
epics::pvData::PVFieldPtr getPVField()
Get the PVField.
Base interface for a PVRecord.
bool tryLock()
Try to lock the record.
PVRecordFieldPtrArrayPtr getPVRecordFields()
Get the sub fields.
std::tr1::shared_ptr< PVDatabase > PVDatabasePtr
PVRecordPtr getPVRecord()
Return the PVRecord to which this field belongs.
void endGroupPut()
Ends a group of puts.
PVRecordStructure(epics::pvData::PVStructurePtr const &pvStructure, PVRecordStructurePtr const &parent, PVRecordPtr const &pvRecord)
Constructor.
std::string getFullName()
Get the recordName plus the full name of the field, i.e. recordName.field,field,..
void beginGroupPut()
Begins a group of puts.
virtual void postSubField()
PVRecordStructurePtr getPVRecordStructure() const
Get the top level PVRecordStructure.
Interface for a field of a record.
std::string getFullFieldName()
Get the full name of the field, i.e. field,field,..
PVRecordStructurePtr getParent()
Get the parent.
static PVDatabasePtr getMaster()
Get the master database.
bool addListener(PVListenerPtr const &pvListener, epics::pvCopy::PVCopyPtr const &pvCopy)
Add a PVListener.
std::tr1::shared_ptr< PVRecord > PVRecordPtr
virtual void postPut()
This is called by the code that implements the data interface. It is called whenever the put method i...
std::vector< PVRecordFieldPtr > PVRecordFieldPtrArray
void initPVRecord()
Initializes the base class.
void unlock()
Unlock the record.
std::tr1::shared_ptr< PVRecordStructure > PVRecordStructurePtr
std::string getRecordName() const
Get the name of the record.
std::tr1::shared_ptr< PVRecordField > PVRecordFieldPtr
Interface for a field that is a structure.
PVRecordFieldPtr findPVRecordField(epics::pvData::PVFieldPtr const &pvField)
Find the PVRecordField for the PVField.
std::tr1::shared_ptr< PVRecordFieldPtrArray > PVRecordFieldPtrArrayPtr
std::ostream & operator<<(std::ostream &o, const PVRecord &record)
virtual void init()
Called by implementation code of PVRecord.
virtual void postParent(PVRecordFieldPtr const &subField)