Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changed Field Fix #82

Merged
merged 6 commits into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions documentation/RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

This document summarizes the changes to the module between releases.

## Release 4.7.2

* 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.

## Release 4.7.1 (EPICS 7.0.8, Dec 2023)

* Added data distributor plugin which can be used for distributing data between
Expand Down
4 changes: 4 additions & 0 deletions src/copy/pvCopy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -432,6 +432,7 @@ bool PVCopy::init(epics::pvData::PVStructurePtr const &pvRequest)
PVStructurePtr pvMasterStructure = pvMaster;
size_t len = pvRequest->getPVFields().size();
bool entireMaster = false;
requestHasMasterField = false;
PVStructurePtr pvOptions;
if(len==0) {
entireMaster = true;
Expand All @@ -441,6 +442,9 @@ bool PVCopy::init(epics::pvData::PVStructurePtr const &pvRequest)
// then assume the top level PV structure is requested
PVStructurePtr masterFieldPtr = pvMaster->getSubField<PVStructure>("_");
PVStructurePtr requestFieldPtr = pvRequest->getSubField<PVStructure>("_");
if (requestFieldPtr) {
requestHasMasterField = true;
}
if (!masterFieldPtr && requestFieldPtr) {
entireMaster = true;
pvOptions = requestFieldPtr->getSubField<PVStructure>("_options");
Expand Down
39 changes: 21 additions & 18 deletions src/database/pvRecord.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -481,27 +481,30 @@ void PVRecordStructure::init()
for(size_t i=0; i<numFields; i++) {
PVFieldPtr pvField = pvFields[i];
if(pvField->getField()->getType()==structure) {
PVStructurePtr xxx = static_pointer_cast<PVStructure>(pvField);
PVRecordStructurePtr pvRecordStructure(
PVStructurePtr xxx = static_pointer_cast<PVStructure>(pvField);
PVRecordStructurePtr pvRecordStructure(
new PVRecordStructure(xxx,self,pvRecord));
pvRecordFields->push_back(pvRecordStructure);
pvRecordStructure->init();
pvRecordFields->push_back(pvRecordStructure);
pvRecordStructure->init();
} else {
PVRecordFieldPtr pvRecordField(
PVRecordFieldPtr pvRecordField(
new PVRecordField(pvField,self,pvRecord));
pvRecordFields->push_back(pvRecordField);
pvRecordField->init();
// Master field listeners will be called before
// calling listeners for the first subfield
if (!masterFieldCallbackSet) {
masterFieldCallbackSet = true;
// Find master field
PVRecordStructurePtr p = pvRecordField->parent.lock();
while (p) {
pvRecordField->master = p;
p = p->parent.lock();
}
}
pvRecordFields->push_back(pvRecordField);
pvRecordField->init();
// Master field listeners will be called before
// calling listeners for the first subfield
if (!masterFieldCallbackSet) {
masterFieldCallbackSet = true;
// Find master field
PVRecordStructurePtr p = pvRecordField->parent.lock();
while (p) {
PVRecordStructurePtr p2 = p->parent.lock();
if (!p2) {
pvRecordField->master = p;
}
p = p2;
}
}
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions src/pv/pvStructureCopy.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,10 @@ class epicsShareClass PVCopy :
* name is the subField name and value is the subField value.
*/
epics::pvData::PVStructurePtr getOptions(std::size_t fieldOffset);
/**
* Is master field requested?
*/
bool isMasterFieldRequested() const {return requestHasMasterField;}
/**
* For debugging.
*/
Expand All @@ -183,6 +187,7 @@ class epicsShareClass PVCopy :
CopyNodePtr headNode;
epics::pvData::PVStructurePtr cacheInitStructure;
epics::pvData::BitSetPtr ignorechangeBitSet;
bool requestHasMasterField;

void traverseMaster(
CopyNodePtr const &node,
Expand Down
6 changes: 6 additions & 0 deletions src/pvAccess/monitorFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,12 @@ void MonitorLocal::dataPut(PVRecordFieldPtr const & pvRecordField)
{
cout << "MonitorLocal::dataPut(pvRecordField)" << endl;
}
// If this record field is the master field, and the master field was not
// requested, we do not proceed with copy
bool isMasterField = pvRecordField->getPVRecord()->getPVStructure()->getFieldOffset()==0;
if (isMasterField && !pvCopy->isMasterFieldRequested()) {
return;
}
if(state!=active) return;
{
Lock xx(mutex);
Expand Down
5 changes: 5 additions & 0 deletions test/src/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,8 @@ TESTPROD_HOST += testPVAServer
testPVAServer_SRCS += testPVAServer.cpp
testHarness_SRCS += testPVAServer.cpp
TESTS += testPVAServer

TESTPROD_HOST += testChannelMonitor
testChannelMonitor_SRCS += testChannelMonitor.cpp
testHarness_SRCS += testChannelMonitor.cpp
TESTS += testChannelMonitor
Loading
Loading