Skip to content

Commit c070a34

Browse files
authored
Merge pull request #82 from sveseli/changed-field-fix
Changed Field Fix
2 parents f207e51 + b31d507 commit c070a34

File tree

8 files changed

+359
-19
lines changed

8 files changed

+359
-19
lines changed

documentation/RELEASE_NOTES.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,10 @@
22

33
This document summarizes the changes to the module between releases.
44

5+
## Release 4.7.2
6+
7+
* Resolved issue with changed field set in the case where the top level (master) field ("_") is not requested by the client, but the master field callback causes all fields to be marked as updated, rather than only those fields that have actually been modified.
8+
59
## Release 4.7.1 (EPICS 7.0.8, Dec 2023)
610

711
* Added data distributor plugin which can be used for distributing data between

src/copy/pvCopy.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -432,6 +432,7 @@ bool PVCopy::init(epics::pvData::PVStructurePtr const &pvRequest)
432432
PVStructurePtr pvMasterStructure = pvMaster;
433433
size_t len = pvRequest->getPVFields().size();
434434
bool entireMaster = false;
435+
requestHasMasterField = false;
435436
PVStructurePtr pvOptions;
436437
if(len==0) {
437438
entireMaster = true;
@@ -441,6 +442,9 @@ bool PVCopy::init(epics::pvData::PVStructurePtr const &pvRequest)
441442
// then assume the top level PV structure is requested
442443
PVStructurePtr masterFieldPtr = pvMaster->getSubField<PVStructure>("_");
443444
PVStructurePtr requestFieldPtr = pvRequest->getSubField<PVStructure>("_");
445+
if (requestFieldPtr) {
446+
requestHasMasterField = true;
447+
}
444448
if (!masterFieldPtr && requestFieldPtr) {
445449
entireMaster = true;
446450
pvOptions = requestFieldPtr->getSubField<PVStructure>("_options");

src/database/pvRecord.cpp

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -481,27 +481,30 @@ void PVRecordStructure::init()
481481
for(size_t i=0; i<numFields; i++) {
482482
PVFieldPtr pvField = pvFields[i];
483483
if(pvField->getField()->getType()==structure) {
484-
PVStructurePtr xxx = static_pointer_cast<PVStructure>(pvField);
485-
PVRecordStructurePtr pvRecordStructure(
484+
PVStructurePtr xxx = static_pointer_cast<PVStructure>(pvField);
485+
PVRecordStructurePtr pvRecordStructure(
486486
new PVRecordStructure(xxx,self,pvRecord));
487-
pvRecordFields->push_back(pvRecordStructure);
488-
pvRecordStructure->init();
487+
pvRecordFields->push_back(pvRecordStructure);
488+
pvRecordStructure->init();
489489
} else {
490-
PVRecordFieldPtr pvRecordField(
490+
PVRecordFieldPtr pvRecordField(
491491
new PVRecordField(pvField,self,pvRecord));
492-
pvRecordFields->push_back(pvRecordField);
493-
pvRecordField->init();
494-
// Master field listeners will be called before
495-
// calling listeners for the first subfield
496-
if (!masterFieldCallbackSet) {
497-
masterFieldCallbackSet = true;
498-
// Find master field
499-
PVRecordStructurePtr p = pvRecordField->parent.lock();
500-
while (p) {
501-
pvRecordField->master = p;
502-
p = p->parent.lock();
503-
}
504-
}
492+
pvRecordFields->push_back(pvRecordField);
493+
pvRecordField->init();
494+
// Master field listeners will be called before
495+
// calling listeners for the first subfield
496+
if (!masterFieldCallbackSet) {
497+
masterFieldCallbackSet = true;
498+
// Find master field
499+
PVRecordStructurePtr p = pvRecordField->parent.lock();
500+
while (p) {
501+
PVRecordStructurePtr p2 = p->parent.lock();
502+
if (!p2) {
503+
pvRecordField->master = p;
504+
}
505+
p = p2;
506+
}
507+
}
505508
}
506509
}
507510
}

src/pv/pvStructureCopy.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,10 @@ class epicsShareClass PVCopy :
167167
* name is the subField name and value is the subField value.
168168
*/
169169
epics::pvData::PVStructurePtr getOptions(std::size_t fieldOffset);
170+
/**
171+
* Is master field requested?
172+
*/
173+
bool isMasterFieldRequested() const {return requestHasMasterField;}
170174
/**
171175
* For debugging.
172176
*/
@@ -183,6 +187,7 @@ class epicsShareClass PVCopy :
183187
CopyNodePtr headNode;
184188
epics::pvData::PVStructurePtr cacheInitStructure;
185189
epics::pvData::BitSetPtr ignorechangeBitSet;
190+
bool requestHasMasterField;
186191

187192
void traverseMaster(
188193
CopyNodePtr const &node,

src/pvAccess/monitorFactory.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,12 @@ void MonitorLocal::dataPut(PVRecordFieldPtr const & pvRecordField)
292292
{
293293
cout << "MonitorLocal::dataPut(pvRecordField)" << endl;
294294
}
295+
// If this record field is the master field, and the master field was not
296+
// requested, we do not proceed with copy
297+
bool isMasterField = pvRecordField->getPVRecord()->getPVStructure()->getFieldOffset()==0;
298+
if (isMasterField && !pvCopy->isMasterFieldRequested()) {
299+
return;
300+
}
295301
if(state!=active) return;
296302
{
297303
Lock xx(mutex);

test/src/Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,8 @@ TESTPROD_HOST += testPVAServer
3333
testPVAServer_SRCS += testPVAServer.cpp
3434
testHarness_SRCS += testPVAServer.cpp
3535
TESTS += testPVAServer
36+
37+
TESTPROD_HOST += testChannelMonitor
38+
testChannelMonitor_SRCS += testChannelMonitor.cpp
39+
testHarness_SRCS += testChannelMonitor.cpp
40+
TESTS += testChannelMonitor

0 commit comments

Comments
 (0)