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,
42 const std::string& asGroup)
45 if(!pvRecord->init()) {
53 string const & recordName,
54 PVStructurePtr
const & pvStructure,
56 const std::string& asGroup_)
57 : recordName(recordName),
58 pvStructure(pvStructure),
70 cout <<
"~PVRecord() " << recordName << endl;
74 void PVRecord::unlistenClients()
76 epicsGuard<epics::pvData::Mutex> guard(mutex);
77 for(std::list<PVListenerWPtr>::iterator iter = pvListenerList.begin();
78 iter!=pvListenerList.end();
82 if(!listener)
continue;
84 cout <<
"PVRecord::remove() calling listener->unlisten " << recordName << endl;
86 listener->unlisten(shared_from_this());
88 pvListenerList.clear();
89 for (std::list<PVRecordClientWPtr>::iterator iter = clientList.begin();
90 iter!=clientList.end();
96 cout <<
"PVRecord::remove() calling client->detach " << recordName << endl;
98 client->detach(shared_from_this());
107 cout <<
"PVRecord::remove() " << recordName << endl;
110 epicsGuard<epics::pvData::Mutex> guard(mutex);
112 if(pvDatabase) pvDatabase->removeFromMap(shared_from_this());
113 pvTimeStamp.detach();
121 pvRecordStructure->init();
122 PVFieldPtr pvField = pvStructure->getSubField(
"timeStamp");
123 if(pvField) pvTimeStamp.attach(pvField);
129 cout <<
"PVRecord::process() " << recordName << endl;
131 if(pvTimeStamp.isAttached()) {
132 pvTimeStamp.get(timeStamp);
133 timeStamp.getCurrent();
134 pvTimeStamp.set(timeStamp);
146 PVFieldPtr
const & pvField)
148 size_t desiredOffset = pvField->getFieldOffset();
149 PVFieldPtr pvf = pvrs->getPVField();
150 size_t offset = pvf->getFieldOffset();
151 if(offset==desiredOffset)
return pvrs;
153 PVRecordFieldPtrArray::iterator iter;
154 for (iter = pvrfpap.get()->begin(); iter!=pvrfpap.get()->end(); iter++ ) {
156 pvf = pvrf->getPVField();
157 offset = pvf->getFieldOffset();
158 if(offset==desiredOffset)
return pvrf;
159 size_t nextOffset = pvf->getNextFieldOffset();
160 if(nextOffset<=desiredOffset)
continue;
162 static_pointer_cast<PVRecordStructure>(pvrf),
165 throw std::logic_error(
166 recordName +
" pvField " 167 + pvField->getFieldName() +
" not in PVRecord");
172 cout <<
"PVRecord::lock() " << recordName << endl;
179 cout <<
"PVRecord::unlock() " << recordName << endl;
186 cout <<
"PVRecord::tryLock() " << recordName << endl;
188 return mutex.tryLock();
194 cout <<
"PVRecord::lockOtherRecord() " << recordName << endl;
196 if(
this<otherRecord.get()) {
208 cout <<
"PVRecord::addPVRecordClient() " << recordName << endl;
210 epicsGuard<epics::pvData::Mutex> guard(mutex);
212 bool clientListClean =
false;
213 while(!clientListClean) {
214 if(clientList.empty())
break;
215 clientListClean =
true;
216 std::list<PVRecordClientWPtr>::iterator iter;
217 for (iter = clientList.begin();
218 iter!=clientList.end();
224 cout <<
"PVRecord::addPVRecordClient() erasing client" 225 << recordName << endl;
227 clientList.erase(iter);
228 clientListClean =
false;
232 clientList.push_back(pvRecordClient);
241 cout <<
"PVRecord::addListener() " << recordName << endl;
243 epicsGuard<epics::pvData::Mutex> guard(mutex);
244 pvListenerList.push_back(pvListener);
245 this->pvListener = pvListener;
246 isAddListener =
true;
247 pvCopy->traverseMaster(shared_from_this());
256 if(!listener.get())
return;
258 pvRecordField->addListener(listener);
260 pvRecordField->removeListener(listener);
269 cout <<
"PVRecord::removeListener() " << recordName << endl;
271 epicsGuard<epics::pvData::Mutex> guard(mutex);
272 std::list<PVListenerWPtr>::iterator iter;
273 for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); iter++ )
276 if(!listener.get())
continue;
277 if(listener.get()==pvListener.get()) {
278 pvListenerList.erase(iter);
279 this->pvListener = pvListener;
280 isAddListener =
false;
281 pvCopy->traverseMaster(shared_from_this());
291 if(++depthGroupPut>1)
return;
293 cout <<
"PVRecord::beginGroupPut() " << recordName << endl;
295 std::list<PVListenerWPtr>::iterator iter;
296 for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); iter++)
299 if(!listener.get())
continue;
300 listener->beginGroupPut(shared_from_this());
306 if(--depthGroupPut>0)
return;
308 cout <<
"PVRecord::endGroupPut() " << recordName << endl;
310 std::list<PVListenerWPtr>::iterator iter;
311 for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); iter++)
314 if(!listener.get())
continue;
315 listener->endGroupPut(shared_from_this());
321 o << format::indent() <<
"record " << record.
getRecordName() << endl;
323 format::indent_scope s(o);
330 PVFieldPtr
const & pvField,
334 isStructure(pvField->getField()->getType()==structure ? true : false),
343 fullFieldName = pvField.lock()->getFieldName();
346 string parentName = pvParent->getPVField()->getFieldName();
347 if(parentName.size()>0) {
348 fullFieldName = pvParent->getPVField()->getFieldName()
349 +
'.' + fullFieldName;
351 pvParent = pvParent->getParent();
354 if(fullFieldName.size()>0) {
355 fullName = pvRecord->getRecordName() +
'.' + fullFieldName;
357 fullName = pvRecord->getRecordName();
359 pvField.lock()->setPostHandler(shared_from_this());
364 return parent.lock();
375 bool PVRecordField::addListener(
PVListenerPtr const & pvListener)
378 if(pvRecord && pvRecord->getTraceLevel()>1) {
379 cout <<
"PVRecordField::addListener() " <<
getFullName() << endl;
381 pvListenerList.push_back(pvListener);
385 void PVRecordField::removeListener(
PVListenerPtr const & pvListener)
388 if(pvRecord && pvRecord->getTraceLevel()>1) {
389 cout <<
"PVRecordField::removeListener() " <<
getFullName() << endl;
391 std::list<PVListenerWPtr>::iterator iter;
392 for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); iter++ ) {
394 if(!listener.get())
continue;
395 if(listener.get()==pvListener.get()) {
396 pvListenerList.erase(iter);
406 parent->postParent(shared_from_this());
414 std::list<PVListenerWPtr>::iterator iter;
415 for(iter = pvListenerList.begin(); iter != pvListenerList.end(); ++iter)
418 if(!listener.get())
continue;
419 listener->dataPut(pvrs,subField);
423 parent->postParent(subField);
432 master->callListener();
439 PVRecordFieldPtrArray::iterator iter;
440 for(iter = pvRecordFields->begin() ; iter !=pvRecordFields->end(); iter++) {
441 (*iter)->postSubField();
446 void PVRecordField::callListener()
448 std::list<PVListenerWPtr>::iterator iter;
449 for (iter = pvListenerList.begin(); iter!=pvListenerList.end(); iter++ ) {
451 if(!listener.get())
continue;
452 listener->dataPut(shared_from_this());
457 PVStructurePtr
const &pvStructure,
462 pvStructure(pvStructure),
470 const PVFieldPtrArray & pvFields = pvStructure.lock()->getPVFields();
471 size_t numFields = pvFields.size();
472 pvRecordFields->reserve( numFields);
476 static bool masterFieldCallbackSet =
false;
479 masterFieldCallbackSet =
false;
481 for(
size_t i=0; i<numFields; i++) {
482 PVFieldPtr pvField = pvFields[i];
483 if(pvField->getField()->getType()==structure) {
484 PVStructurePtr xxx = static_pointer_cast<PVStructure>(pvField);
487 pvRecordFields->push_back(pvRecordStructure);
488 pvRecordStructure->init();
492 pvRecordFields->push_back(pvRecordField);
493 pvRecordField->init();
496 if (!masterFieldCallbackSet) {
497 masterFieldCallbackSet =
true;
501 pvRecordField->master = p;
502 p = p->parent.lock();
511 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)