group put()
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()))
|
||||
|
||||
@@ -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(); }
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user