diff --git a/pdbApp/pvalink.cpp b/pdbApp/pvalink.cpp index e5b09c8..981fc24 100644 --- a/pdbApp/pvalink.cpp +++ b/pdbApp/pvalink.cpp @@ -27,6 +27,8 @@ namespace pva = epics::pvAccess; extern "C" void (*dbAddLinkHook)(struct link *link, short dbfType); +int pvaLinkDebug = 4; + namespace { typedef epicsGuard Guard; @@ -136,6 +138,8 @@ struct pvaLinkChannel : public pva::ChannelRequester, pva::MonitorRequester, std::cerr<<"pvaLink: channel destroy "<3) std::cerr<<"pvaLink channelStateChange "<create->createPVStructure(pvaGlobal->reqtype)); @@ -365,6 +374,7 @@ void pvaLinkChannel::channelStateChange(pva::Channel::shared_pointer const & cha chanmon.reset(); std::cerr<<"pvaLink: monitor destroy "<3) std::cerr<<"pvaLink monitorEvent "<3) std::cerr<<"pvaLink monitorEvent "<poll())) { try{ lastval->copyUnchecked(*elem->pvStructurePtr, *elem->changedBitSet); - atomic = isatomic->getAs(); + atomic = isatomic ? isatomic->getAs() : false; updated = true; monitor->release(elem); @@ -416,22 +428,25 @@ void pvaLinkChannel::monitorEvent(pva::Monitor::shared_pointer const & monitor) } } - bool doscan = false; - if(updated) { - // check if we actually need to scan anything - FOREACH(it, end, links) { - pvaLink* L = *it; - struct pv_link *ppv_link = &L->plink->value.pv_link; + if(updated) triggerProc(atomic); +} - if ((ppv_link->pvlMask & pvlOptCP) || - ((ppv_link->pvlMask & pvlOptCPP) && L->plink->precord->scan == 0)) - { - doscan = true; - } +// caller must have channel's lock +void pvaLinkChannel::triggerProc(bool atomic) +{ + bool doscan = false; + // check if we actually need to scan anything + FOREACH(it, end, links) { + pvaLink* L = *it; + struct pv_link *ppv_link = &L->plink->value.pv_link; + + if ((ppv_link->pvlMask & pvlOptCP) || + ((ppv_link->pvlMask & pvlOptCPP) && L->plink->precord->scan == 0)) + { + doscan = true; } } if(doscan && !scanself) { // need to scan, and not already queued, then queue - std::cerr<<"pvaLink: queue scan from "<3) std::cerr<<"pvaLink scan "<name<<"\n"; + std::tr1::shared_ptr self; Guard G(selfraw->lock); @@ -469,8 +486,6 @@ void pvaLinkChannel::scan(void* arg, epicsJobMode mode) pvaGlobal->scanmagic.set(usecached ? &myscan : NULL); - std::cerr<<"pvaLink: scan from "<name<<" "<<(usecached?" use cached":"")<<"\n"; - { UnGuard U(G); // we may scan a record after the originating link is re-targeted @@ -493,7 +508,7 @@ void pvaLinkChannel::scan(void* arg, epicsJobMode mode) if(usecached) { FOREACH(it, end, links) { pvaLink *link = *it; - link->atomcache.valid = false; + link->atomcache.clear(); } } @@ -615,7 +630,7 @@ long pvaGetValue(struct link *plink, short dbrType, void *pbuffer, TRY { if(pvaGlobal->scanmagic.get()) { const void *buf; - size_t count = pnRequest ? *pnRequest : 0; + size_t count = pnRequest ? *pnRequest : 1; if(self->atomcache.scalar) { buf = (void*)&self->atomcache.valueS; count = std::min((size_t)1u, count); @@ -627,6 +642,8 @@ long pvaGetValue(struct link *plink, short dbrType, void *pbuffer, pvd::castUnsafeV(count, DBR2PVD(dbrType), pbuffer, self->atomcache.etype, buf); *psevr = self->atomcache.sevr; *pstat = *psevr ? LINK_ALARM : 0; + if(pnRequest) *pnRequest = count; + return 0; } Guard G(self->lchan->lock); @@ -637,6 +654,7 @@ long pvaGetValue(struct link *plink, short dbrType, void *pbuffer, long nelem = std::min(*pnRequest, (long)arrval.size()); pvd::castUnsafeV(nelem, DBR2PVD(dbrType), pbuffer, arrval.original_type(), arrval.data()); + if(pnRequest) *pnRequest = nelem; *psevr = self->sevr->getAs(); } else if(self->valueS) { @@ -658,6 +676,7 @@ long pvaGetValue(struct link *plink, short dbrType, void *pbuffer, default: throw std::runtime_error("putValue unsupported DBR code"); } + if(pnRequest) *pnRequest = 1; *psevr = self->sevr->getAs(); } else { @@ -883,6 +902,7 @@ void installPVAAddLinkHook() { initHookRegister(&initPVALink); iocshRegister("pvalr", "level"); + iocshVariable("pvaLinkDebug"); } epicsExportRegistrar(installPVAAddLinkHook);