group put()

This commit is contained in:
Michael Davidsaver
2016-03-02 20:00:54 -05:00
parent e5b886b59d
commit 349578cd2c
5 changed files with 178 additions and 16 deletions

View File

@@ -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<pvd::PVScalar>("record._options.atomic"));
if(atomicopt) {
try {
atomic = atomicopt->getAs<pvd::boolean>();
}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; i<npvs; i++)
{
pvif[i].reset(PVIF::attach(channel->pv->chan[i],
pvf->getSubFieldT<pvd::PVStructure>(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<std::tr1::shared_ptr<PVIF> > putpvif(npvs);
for(size_t i=0; i<npvs; i++)
{
putpvif[i].reset(PVIF::attach(channel->pv->chan[i],
value->getSubFieldT<pvd::PVStructure>(channel->pv->attachments[i])
));
}
if(atomic) {
DBManyLocker L(channel->pv->locker);
for(size_t i=0; i<npvs; i++)
putpvif[i]->get(*changed);
} else {
for(size_t i=0; i<npvs; i++)
{
DBScanLocker L(dbChannelRecord(channel->pv->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; i<npvs; i++)
pvif[i]->put(*changed, DBE_VALUE|DBE_ALARM|DBE_PROPERTY, NULL);
} else {
for(size_t i=0; i<npvs; i++)
{
DBScanLocker L(dbChannelRecord(channel->pv->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);
}

View File

@@ -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<PDBGroupPut>
{
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<std::tr1::shared_ptr<PVIF> > 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<epics::pvAccess::Channel> 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

View File

@@ -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()))

View File

@@ -61,8 +61,8 @@ struct PDBSingleGet : public epics::pvAccess::ChannelGet,
epics::pvData::PVStructurePtr pvf;
std::auto_ptr<PVIF> 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(); }

View File

@@ -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<pvd::PVBoolean>("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<const pvd::Structure>(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<pvd::PVBoolean>("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<pvd::PVDouble>("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<pvd::PVDouble>("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);