diff --git a/documentation/RELEASE_NOTES.md b/documentation/RELEASE_NOTES.md index b5c1fe5..105ae6f 100644 --- a/documentation/RELEASE_NOTES.md +++ b/documentation/RELEASE_NOTES.md @@ -2,6 +2,12 @@ This document summarizes the changes to the module between releases. +## Release 4.X.Y (EPICS 7.X.Y, MMM 20YY) + +* Added support for the whole structure (master field) server side plugins. The whole structure +is identified as the `_` string, and the pvRequest string that applies a plugin to it +has the form `field(_[pluginXYZ=optionA:3;optionB:uniqueId])`. + ## Release 4.6.0 (EPICS 7.0.6, Jul 2021) * Access Security is now supported. diff --git a/src/copy/pvCopy.cpp b/src/copy/pvCopy.cpp index fd98a24..7694ecf 100644 --- a/src/copy/pvCopy.cpp +++ b/src/copy/pvCopy.cpp @@ -88,7 +88,6 @@ PVCopyPtr PVCopy::create( bool result = pvCopy->init(pvStructure); if(!result) return PVCopyPtr(); pvCopy->traverseMasterInitPlugin(); -//cout << pvCopy->dump() << endl; return pvCopy; } @@ -433,10 +432,19 @@ bool PVCopy::init(epics::pvData::PVStructurePtr const &pvRequest) PVStructurePtr pvMasterStructure = pvMaster; size_t len = pvRequest->getPVFields().size(); bool entireMaster = false; - if(len==0) entireMaster = true; PVStructurePtr pvOptions; - if(len==1) { - pvOptions = pvRequest->getSubField("_options"); + if(len==0) { + entireMaster = true; + } + else { + // If "_" is in the request, but not in the master structure, + // then assume the top level PV structure is requested + PVStructurePtr masterFieldPtr = pvMaster->getSubField("_"); + PVStructurePtr requestFieldPtr = pvRequest->getSubField("_"); + if (!masterFieldPtr && requestFieldPtr) { + entireMaster = true; + pvOptions = requestFieldPtr->getSubField("_options"); + } } if(entireMaster) { structure = pvMasterStructure->getStructure(); diff --git a/src/database/pvRecord.cpp b/src/database/pvRecord.cpp index ed2b2be..d343b6c 100644 --- a/src/database/pvRecord.cpp +++ b/src/database/pvRecord.cpp @@ -418,7 +418,10 @@ void PVRecordField::postParent(PVRecordFieldPtr const & subField) listener->dataPut(pvrs,subField); } PVRecordStructurePtr parent(this->parent.lock()); - if(parent) parent->postParent(subField); + if(parent) { + parent->postParent(subField); + parent->callListener(); + } } void PVRecordField::postSubField() diff --git a/test/src/testPVCopy.cpp b/test/src/testPVCopy.cpp index b39eeda..a86493f 100644 --- a/test/src/testPVCopy.cpp +++ b/test/src/testPVCopy.cpp @@ -274,6 +274,33 @@ static void testPVScalarArray( } } +static void testMasterField(PVRecordPtr const& pvRecord) +{ + CreateRequest::shared_pointer createRequest = CreateRequest::create(); + PVStructurePtr pvRequest = createRequest->createRequest("field(_)"); + if(debug) { + cout << "pvRequest" << *pvRequest << endl ; + } + PVStructurePtr pvStructureRecord = pvRecord->getPVRecordStructure()->getPVStructure(); + PVCopyPtr pvCopy = PVCopy::create(pvStructureRecord,pvRequest,""); + PVStructurePtr pvMasterField = pvCopy->getPVMaster(); + if(debug) { + cout << "PV structure from record" << endl << *pvStructureRecord << endl; + cout << "Master PV structure from copy" << endl << *pvMasterField << endl; + cout << "Master PV structure from copy offset " << pvMasterField->getFieldOffset() << endl; + } + testOk1(pvMasterField->getNumberFields() == pvStructureRecord->getNumberFields()); + testOk1(pvMasterField->getFieldOffset() == 0); + PVStructurePtr pvStructureCopy = pvCopy->createPVStructure(); + BitSetPtr bitSet = BitSetPtr(new BitSet(pvStructureCopy->getNumberFields())); + pvCopy->initCopy(pvStructureCopy, bitSet); + if(debug) { + cout << "PV structure from copy" << endl << *pvStructureCopy << endl; + cout << "PV structure from copy offset " << pvStructureCopy->getFieldOffset() << endl; + } + testOk1(pvMasterField->getNumberFields() == pvStructureCopy->getNumberFields()); +} + static void scalarTest() { if(debug) {cout << endl << endl << "****scalarTest****" << endl;} @@ -393,11 +420,21 @@ static void powerSupplyTest() testPVScalar(valueNameRecord,valueNameCopy,pvRecord,pvCopy); } +static void masterFieldTest() +{ + if(debug) { + cout << endl << endl << "****masterFieldTest****" << endl; + } + PVRecordPtr pvRecord = createScalar("doubleRecord",pvDouble,"alarm,timeStamp,display"); + testMasterField(pvRecord); +} + MAIN(testPVCopy) { - testPlan(67); + testPlan(70); scalarTest(); arrayTest(); powerSupplyTest(); + masterFieldTest(); return 0; }