From 349578cd2c59ef952d6f2c175bb694deae0857c5 Mon Sep 17 00:00:00 2001 From: Michael Davidsaver Date: Wed, 2 Mar 2016 20:00:54 -0500 Subject: [PATCH] group put() --- pdbApp/pdbgroup.cpp | 90 ++++++++++++++++++++++++++++++++++++++++++++ pdbApp/pdbgroup.h | 34 ++++++++++++++++- pdbApp/pdbsingle.cpp | 4 +- pdbApp/pdbsingle.h | 4 +- testApp/testpdb.cpp | 62 ++++++++++++++++++++++++------ 5 files changed, 178 insertions(+), 16 deletions(-) diff --git a/pdbApp/pdbgroup.cpp b/pdbApp/pdbgroup.cpp index f3c2ad2..2db0f65 100644 --- a/pdbApp/pdbgroup.cpp +++ b/pdbApp/pdbgroup.cpp @@ -50,6 +50,16 @@ PDBGroupChannel::createChannelGet( return ret; } +pva::ChannelPut::shared_pointer +PDBGroupChannel::createChannelPut( + pva::ChannelPutRequester::shared_pointer const & requester, + pvd::PVStructure::shared_pointer const & pvRequest) +{ + pva::ChannelPut::shared_pointer ret(new PDBGroupPut(shared_from_this(), requester, pvRequest)); + requester->channelPutConnect(pvd::Status(), ret, fielddesc); + return ret; +} + PDBGroupGet::PDBGroupGet(const PDBGroupChannel::shared_pointer &channel, const pva::ChannelGetRequester::shared_pointer &requester, @@ -102,3 +112,83 @@ void PDBGroupGet::get() requester->getDone(pvd::Status(), shared_from_this(), pvf, changed); } + +PDBGroupPut::PDBGroupPut(const PDBGroupChannel::shared_pointer& channel, + const pva::ChannelPutRequester::shared_pointer& requester, + const epics::pvData::PVStructure::shared_pointer &pvReq) + :channel(channel) + ,requester(requester) + ,atomic(false) + ,changed(new pvd::BitSet(channel->fielddesc->getNumberFields())) + ,pvf(pvd::getPVDataCreate()->createPVStructure(channel->fielddesc)) +{ + pvd::PVScalarPtr atomicopt(pvReq->getSubField("record._options.atomic")); + if(atomicopt) { + try { + atomic = atomicopt->getAs(); + }catch(std::exception& e){ + requester->message("Unable to parse 'atomic' request option. Default is false.", pvd::warningMessage); + } + } + + const size_t npvs = channel->pv->attachments.size(); + pvif.resize(npvs); + for(size_t i=0; ipv->chan[i], + pvf->getSubFieldT(channel->pv->attachments[i]) + )); + } +} + +void PDBGroupPut::put(pvd::PVStructure::shared_pointer const & value, + pvd::BitSet::shared_pointer const & changed) +{ + // assume value may be a different struct each time... lot of wasted prep work + const size_t npvs = channel->pv->attachments.size(); + std::vector > putpvif(npvs); + + for(size_t i=0; ipv->chan[i], + value->getSubFieldT(channel->pv->attachments[i]) + )); + } + + if(atomic) { + DBManyLocker L(channel->pv->locker); + for(size_t i=0; iget(*changed); + } else { + for(size_t i=0; ipv->chan[i])); + putpvif[i]->get(*changed); + } + } + + requester->putDone(pvd::Status(), shared_from_this()); +} + +void PDBGroupPut::get() +{ + const size_t npvs = pvif.size(); + + changed->clear(); + if(atomic) { + DBManyLocker L(channel->pv->locker); + for(size_t i=0; iput(*changed, DBE_VALUE|DBE_ALARM|DBE_PROPERTY, NULL); + } else { + + for(size_t i=0; ipv->chan[i])); + pvif[i]->put(*changed, DBE_VALUE|DBE_ALARM|DBE_PROPERTY, NULL); + } + } + //TODO: report unused fields as changed? + changed->clear(); + changed->set(0); + requester->getDone(pvd::Status(), shared_from_this(), pvf, changed); +} diff --git a/pdbApp/pdbgroup.h b/pdbApp/pdbgroup.h index fbfca47..d93a7b7 100644 --- a/pdbApp/pdbgroup.h +++ b/pdbApp/pdbgroup.h @@ -47,6 +47,9 @@ struct PDBGroupChannel : public BaseChannel, virtual epics::pvAccess::ChannelGet::shared_pointer createChannelGet( epics::pvAccess::ChannelGetRequester::shared_pointer const & channelGetRequester, epics::pvData::PVStructure::shared_pointer const & pvRequest); + virtual epics::pvAccess::ChannelPut::shared_pointer createChannelPut( + epics::pvAccess::ChannelPutRequester::shared_pointer const & requester, + epics::pvData::PVStructure::shared_pointer const & pvRequest); virtual void printInfo(std::ostream& out); }; @@ -75,7 +78,36 @@ struct PDBGroupGet : public epics::pvAccess::ChannelGet, virtual void lastRequest() {} virtual void get(); }; -//struct PDBGroupPut : public epics::pvAccess::ChannelPut {}; + +struct PDBGroupPut : public epics::pvAccess::ChannelPut, + public std::tr1::enable_shared_from_this +{ + typedef epics::pvAccess::ChannelPutRequester requester_t; + PDBGroupChannel::shared_pointer channel; + requester_t::shared_pointer requester; + + bool atomic; + epics::pvData::BitSetPtr changed; + epics::pvData::PVStructurePtr pvf; + std::vector > pvif; + + PDBGroupPut(const PDBGroupChannel::shared_pointer &channel, + const epics::pvAccess::ChannelPutRequester::shared_pointer &requester, + const epics::pvData::PVStructure::shared_pointer& pvReq); + virtual ~PDBGroupPut() {} + + virtual void destroy() { pvif.clear(); channel.reset(); requester.reset(); } + virtual void lock() {} + virtual void unlock() {} + virtual std::tr1::shared_ptr getChannel() { return channel; } + virtual void cancel() {} + virtual void lastRequest() {} + virtual void put( + epics::pvData::PVStructure::shared_pointer const & pvPutStructure, + epics::pvData::BitSet::shared_pointer const & putBitSet); + virtual void get(); +}; + //struct PDBGroupMonitor : public epics::pvData::Monitor {}; #endif // PDBGROUP_H diff --git a/pdbApp/pdbsingle.cpp b/pdbApp/pdbsingle.cpp index 9173c65..15edf6c 100644 --- a/pdbApp/pdbsingle.cpp +++ b/pdbApp/pdbsingle.cpp @@ -64,8 +64,8 @@ PDBSingleChannel::createChannelPut( } -PDBSingleGet::PDBSingleGet(PDBSingleChannel::shared_pointer channel, - pva::ChannelGetRequester::shared_pointer requester) +PDBSingleGet::PDBSingleGet(const PDBSingleChannel::shared_pointer &channel, + const epics::pvAccess::ChannelGetRequester::shared_pointer& requester) :channel(channel) ,requester(requester) ,changed(new pvd::BitSet(channel->fielddesc->getNumberFields())) diff --git a/pdbApp/pdbsingle.h b/pdbApp/pdbsingle.h index 25c56b5..9ad3263 100644 --- a/pdbApp/pdbsingle.h +++ b/pdbApp/pdbsingle.h @@ -61,8 +61,8 @@ struct PDBSingleGet : public epics::pvAccess::ChannelGet, epics::pvData::PVStructurePtr pvf; std::auto_ptr pvif; - PDBSingleGet(PDBSingleChannel::shared_pointer channel, - epics::pvAccess::ChannelGetRequester::shared_pointer requester); + PDBSingleGet(const PDBSingleChannel::shared_pointer& channel, + const epics::pvAccess::ChannelGetRequester::shared_pointer& requester); virtual ~PDBSingleGet() {} virtual void destroy() { pvif.reset(); channel.reset(); requester.reset(); } diff --git a/testApp/testpdb.cpp b/testApp/testpdb.cpp index e484097..cee13d8 100644 --- a/testApp/testpdb.cpp +++ b/testApp/testpdb.cpp @@ -28,6 +28,19 @@ void testFieldEqual(const pvd::PVStructurePtr& val, const char *name, typename P } } +pvd::PVStructurePtr makeRequest(bool atomic) +{ pvd::StructureConstPtr def(pvd::getFieldCreate()->createFieldBuilder() + ->addNestedStructure("record") + ->addNestedStructure("_options") + ->add("atomic", pvd::pvBoolean) + ->endNested() + ->endNested() + ->createStructure()); + pvd::PVStructurePtr pvr(pvd::getPVDataCreate()->createPVStructure(def)); + pvr->getSubFieldT("record._options.atomic")->put(atomic); + return pvr; +} + struct PVPut { TestChannelRequester::shared_pointer chreq; @@ -38,7 +51,7 @@ struct PVPut pvd::PVStructurePtr putval; pvd::BitSetPtr putchanged; - PVPut(const pva::ChannelProvider::shared_pointer& prov, const char *name) + PVPut(const pva::ChannelProvider::shared_pointer& prov, const char *name, bool atomic=true) :chreq(new TestChannelRequester()) ,chan(prov->createChannel(name, chreq)) ,fldreq(new TestChannelFieldRequester()) @@ -50,7 +63,8 @@ struct PVPut if(!fldreq->done || !fldreq->fielddesc || fldreq->fielddesc->getType()!=pvd::structure) throw std::runtime_error("Failed to get fielddesc"); putval = pvd::getPVDataCreate()->createPVStructure(std::tr1::static_pointer_cast(fldreq->fielddesc)); - chput = chan->createChannelPut(putreq, putval); + pvd::PVStructurePtr pvr(makeRequest(atomic)); + chput = chan->createChannelPut(putreq, pvr); if(!chput) throw std::runtime_error("Failed to create put op"); putchanged.reset(new pvd::BitSet()); @@ -77,15 +91,7 @@ struct PVPut pvd::PVStructurePtr pvget(const pva::ChannelProvider::shared_pointer& prov, const char *name, bool atomic) { - pvd::StructureConstPtr def(pvd::getFieldCreate()->createFieldBuilder() - ->addNestedStructure("record") - ->addNestedStructure("_options") - ->add("atomic", pvd::pvBoolean) - ->endNested() - ->endNested() - ->createStructure()); - pvd::PVStructurePtr pvr(pvd::getPVDataCreate()->createPVStructure(def)); - pvr->getSubFieldT("record._options.atomic")->put(atomic); + pvd::PVStructurePtr pvr(makeRequest(atomic)); TestChannelRequester::shared_pointer req(new TestChannelRequester()); @@ -175,6 +181,39 @@ void testSinglePut(const PDBProvider::shared_pointer& prov) testdbGetFieldEqual("rec1", DBR_DOUBLE, 2.0); } +void testGroupPut(const PDBProvider::shared_pointer& prov) +{ + testDiag("test group put"); + + testdbPutFieldOk("rec3", DBR_DOUBLE, 3.0); + testdbPutFieldOk("rec4", DBR_DOUBLE, 4.0); + testdbPutFieldOk("rec3.RVAL", DBR_LONG, 30); + testdbPutFieldOk("rec4.RVAL", DBR_LONG, 40); + + PVPut put(prov, "grp1"); + + pvd::PVDoublePtr val(put.putval->getSubFieldT("fld1.value")); + val->put(2.0); + put.putchanged->clear(); + put.put(); + + testdbGetFieldEqual("rec3", DBR_DOUBLE, 3.0); + testdbGetFieldEqual("rec4", DBR_DOUBLE, 4.0); + testdbGetFieldEqual("rec3.RVAL", DBR_LONG, 30); + testdbGetFieldEqual("rec4.RVAL", DBR_LONG, 40); + + put.putchanged->set(val->getFieldOffset()); + val = put.putval->getSubFieldT("fld3.value"); + val->put(5.0); + put.putchanged->set(val->getFieldOffset()); + put.put(); + + testdbGetFieldEqual("rec3", DBR_DOUBLE, 2.0); + testdbGetFieldEqual("rec4", DBR_DOUBLE, 5.0); + testdbGetFieldEqual("rec3.RVAL", DBR_LONG, 30); + testdbGetFieldEqual("rec4.RVAL", DBR_LONG, 40); +} + } // namespace extern "C" @@ -198,6 +237,7 @@ MAIN(testpdb) testGroupGet(prov); testSinglePut(prov); + testGroupPut(prov); } testDiag("check to see that all dbChannel are closed before IOC shuts down"); testEqual(epics::atomic::get(PDBGroupPV::ninstances), 0u);