/* pvaClientPutGet.cpp */ /** * Copyright - See the COPYRIGHT that is included with this distribution. * EPICS pvData is distributed subject to a Software License Agreement found * in file LICENSE that is included with this distribution. */ /** * @author mrk * @date 2015.02 */ #include #define epicsExportSharedSymbols #include using namespace epics::pvData; using namespace epics::pvAccess; using namespace std; namespace epics { namespace pvaClient { class ChannelPutGetRequesterImpl : public ChannelPutGetRequester { PvaClientPutGet::weak_pointer pvaClientPutGet; PvaClient::weak_pointer pvaClient; public: ChannelPutGetRequesterImpl( PvaClientPutGetPtr const & pvaClientPutGet, PvaClientPtr const &pvaClient) : pvaClientPutGet(pvaClientPutGet), pvaClient(pvaClient) {} virtual ~ChannelPutGetRequesterImpl() { if(PvaClient::getDebug()) std::cout << "~ChannelPutGetRequesterImpl" << std::endl; } virtual std::string getRequesterName() { PvaClientPutGetPtr clientPutGet(pvaClientPutGet.lock()); if(!clientPutGet) return string("clientPutGet is null"); return clientPutGet->getRequesterName(); } virtual void message(std::string const & message, epics::pvData::MessageType messageType) { PvaClientPutGetPtr clientPutGet(pvaClientPutGet.lock()); if(!clientPutGet) return; clientPutGet->message(message,messageType); } virtual void channelPutGetConnect( const Status& status, ChannelPutGet::shared_pointer const & channelPutGet, Structure::const_shared_pointer const & putStructure, Structure::const_shared_pointer const & getStructure) { PvaClientPutGetPtr clientPutGet(pvaClientPutGet.lock()); if(!clientPutGet) return; clientPutGet->channelPutGetConnect(status,channelPutGet,putStructure,getStructure); } virtual void putGetDone( const Status& status, ChannelPutGet::shared_pointer const & channelPutGet, PVStructurePtr const & getPVStructure, BitSet::shared_pointer const & getBitSet) { PvaClientPutGetPtr clientPutGet(pvaClientPutGet.lock()); if(!clientPutGet) return; clientPutGet->putGetDone(status,channelPutGet,getPVStructure,getBitSet); } virtual void getPutDone( const Status& status, ChannelPutGet::shared_pointer const & channelPutGet, PVStructurePtr const & putPVStructure, BitSet::shared_pointer const & putBitSet) { PvaClientPutGetPtr clientPutGet(pvaClientPutGet.lock()); if(!clientPutGet) return; clientPutGet->getPutDone(status,channelPutGet,putPVStructure,putBitSet); } virtual void getGetDone( const Status& status, ChannelPutGet::shared_pointer const & channelPutGet, PVStructurePtr const & getPVStructure, BitSet::shared_pointer const & getBitSet) { PvaClientPutGetPtr clientPutGet(pvaClientPutGet.lock()); if(!clientPutGet) return; clientPutGet->getGetDone(status,channelPutGet,getPVStructure,getBitSet); } }; PvaClientPutGetPtr PvaClientPutGet::create( PvaClientPtr const &pvaClient, PvaClientChannelPtr const & pvaClientChannel, PVStructurePtr const &pvRequest) { PvaClientPutGetPtr clientPutGet(new PvaClientPutGet(pvaClient,pvaClientChannel,pvRequest)); clientPutGet->channelPutGetRequester = ChannelPutGetRequesterImplPtr( new ChannelPutGetRequesterImpl(clientPutGet,pvaClient)); return clientPutGet; } PvaClientPutGet::PvaClientPutGet( PvaClientPtr const &pvaClient, PvaClientChannelPtr const & pvaClientChannel, PVStructurePtr const &pvRequest) : pvaClient(pvaClient), pvaClientChannel(pvaClientChannel), pvRequest(pvRequest), connectState(connectIdle), putGetState(putGetIdle) { if(PvaClient::getDebug()) { cout<< "PvaClientPutGet::PvaClientPutGet" << " channelName " << pvaClientChannel->getChannel()->getChannelName() << endl; } } PvaClientPutGet::~PvaClientPutGet() { if(PvaClient::getDebug()) { cout<< "PvaClientPutGet::~PvaClientPutGet" << " channelName " << pvaClientChannel->getChannel()->getChannelName() << endl; } } void PvaClientPutGet::checkPutGetState() { if(PvaClient::getDebug()) { cout << "PvaClientPutGet::checkPutGetState" << " channelName " << pvaClientChannel->getChannel()->getChannelName() << endl; } if(connectState==connectIdle){ connect(); } if(connectState==connectActive){ string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName() + " " + channelPutGetConnectStatus.getMessage(); throw std::runtime_error(message); } } string PvaClientPutGet::getRequesterName() { PvaClientPtr yyy = pvaClient.lock(); if(!yyy) return string("PvaClientPutGet::getRequesterName() PvaClient isDestroyed"); return yyy->getRequesterName(); } void PvaClientPutGet::message(string const & message,MessageType messageType) { PvaClientPtr yyy = pvaClient.lock(); if(!yyy) return; yyy->message(message, messageType); } void PvaClientPutGet::channelPutGetConnect( const Status& status, ChannelPutGet::shared_pointer const & channelPutGet, StructureConstPtr const & putStructure, StructureConstPtr const & getStructure) { if(PvaClient::getDebug()) { cout << "PvaClientPutGet::channelPutGetConnect" << " channelName " << pvaClientChannel->getChannel()->getChannelName() << " status.isOK " << (status.isOK() ? "true" : "false") << endl; } { Lock xx(mutex); this->channelPutGet = channelPutGet; if(status.isOK()) { channelPutGetConnectStatus = status; connectState = connected; pvaClientPutData = PvaClientPutData::create(putStructure); pvaClientPutData->setMessagePrefix(channelPutGet->getChannel()->getChannelName()); pvaClientGetData = PvaClientGetData::create(getStructure); pvaClientGetData->setMessagePrefix(channelPutGet->getChannel()->getChannelName()); } else { stringstream ss; ss << pvRequest; string message = string("\nPvaClientPutGet::channelPutGetConnect)") + "\npvRequest\n" + ss.str() + "\nerror\n" + status.getMessage(); channelPutGetConnectStatus = Status(Status::STATUSTYPE_ERROR,message); } } PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock()); if(req) { req->channelPutGetConnect(status,shared_from_this()); } waitForConnect.signal(); } void PvaClientPutGet::putGetDone( const Status& status, ChannelPutGet::shared_pointer const & channelPutGet, PVStructurePtr const & getPVStructure, BitSetPtr const & getChangedBitSet) { if(PvaClient::getDebug()) { cout << "PvaClientPutGet::putGetDone" << " channelName " << pvaClientChannel->getChannel()->getChannelName() << " status.isOK " << (status.isOK() ? "true" : "false") << endl; } { Lock xx(mutex); channelPutGetStatus = status; putGetState = putGetComplete; if(status.isOK()) { pvaClientGetData->setData(getPVStructure,getChangedBitSet); } } PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock()); if(req) { req->putGetDone(status,shared_from_this()); } waitForPutGet.signal(); } void PvaClientPutGet::getPutDone( const Status& status, ChannelPutGet::shared_pointer const & channelPutGet, PVStructurePtr const & putPVStructure, BitSetPtr const & putBitSet) { if(PvaClient::getDebug()) { cout << "PvaClientPutGet::getPutDone" << " channelName " << pvaClientChannel->getChannel()->getChannelName() << " status.isOK " << (status.isOK() ? "true" : "false") << endl; } { Lock xx(mutex); channelPutGetStatus = status; putGetState = putGetComplete; if(status.isOK()) { PVStructurePtr pvs = pvaClientPutData->getPVStructure(); pvs->copyUnchecked(*putPVStructure,*putBitSet); BitSetPtr bs = pvaClientPutData->getChangedBitSet(); bs->clear(); *bs |= *putBitSet; } } PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock()); if(req) { req->getPutDone(status,shared_from_this()); } waitForPutGet.signal(); } void PvaClientPutGet::getGetDone( const Status& status, ChannelPutGet::shared_pointer const & channelPutGet, PVStructurePtr const & getPVStructure, BitSetPtr const & getChangedBitSet) { if(PvaClient::getDebug()) { cout << "PvaClientPutGet::getGetDone" << " channelName " << pvaClientChannel->getChannel()->getChannelName() << " status.isOK " << (status.isOK() ? "true" : "false") << endl; } { Lock xx(mutex); channelPutGetStatus = status; putGetState = putGetComplete; if(status.isOK()) { pvaClientGetData->setData(getPVStructure,getChangedBitSet); } } PvaClientPutGetRequesterPtr req(pvaClientPutGetRequester.lock()); if(req) { req->getGetDone(status,shared_from_this()); } waitForPutGet.signal(); } void PvaClientPutGet::connect() { if(PvaClient::getDebug()) { cout << "PvaClientPutGet::connect" << " channelName " << pvaClientChannel->getChannel()->getChannelName() << endl; } issueConnect(); Status status = waitConnect(); if(status.isOK()) return; string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName() + " PvaClientPutGet::connect " + status.getMessage(); throw std::runtime_error(message); } void PvaClientPutGet::issueConnect() { if(PvaClient::getDebug()) { cout << "PvaClientPutGet::issueConnect" << " channelName " << pvaClientChannel->getChannel()->getChannelName() << endl; } if(connectState!=connectIdle) { string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName() + " pvaClientPutGet already connected "; throw std::runtime_error(message); } connectState = connectActive; channelPutGetConnectStatus = Status(Status::STATUSTYPE_ERROR, "connect active"); channelPutGet = pvaClientChannel->getChannel()->createChannelPutGet(channelPutGetRequester,pvRequest); } Status PvaClientPutGet::waitConnect() { if(PvaClient::getDebug()) { cout << "PvaClientPutGet::waitConnect" << " channelName " << pvaClientChannel->getChannel()->getChannelName() << endl; } { Lock xx(mutex); if(connectState==connected) { if(!channelPutGetConnectStatus.isOK()) connectState = connectIdle; return channelPutGetConnectStatus; } if(connectState!=connectActive) { string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName() + " PvaClientPutGet::waitConnect illegal connect state "; throw std::runtime_error(message); } } waitForConnect.wait(); if(!channelPutGetConnectStatus.isOK()) connectState = connectIdle; return channelPutGetConnectStatus; } void PvaClientPutGet::putGet() { if(PvaClient::getDebug()) { cout << "PvaClientPutGet::putGet" << " channelName " << pvaClientChannel->getChannel()->getChannelName() << endl; } issuePutGet(); Status status = waitPutGet(); if(status.isOK()) return; string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName() + " PvaClientPut::putGet " + status.getMessage(); throw std::runtime_error(message); } void PvaClientPutGet::issuePutGet() { if(PvaClient::getDebug()) { cout << "PvaClientPutGet::issuePutGet" << " channelName " << pvaClientChannel->getChannel()->getChannelName() << endl; } if(connectState==connectIdle) connect(); if(putGetState==putGetActive) { string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName() + " PvaClientPutGet::issuePutGet get or put aleady active "; throw std::runtime_error(message); } putGetState = putGetActive; channelPutGet->putGet(pvaClientPutData->getPVStructure(),pvaClientPutData->getChangedBitSet()); } Status PvaClientPutGet::waitPutGet() { if(PvaClient::getDebug()) { cout << "PvaClientPutGet::waitPutGet" << " channelName " << pvaClientChannel->getChannel()->getChannelName() << endl; } if(putGetState==putGetComplete) return channelPutGetStatus; if(putGetState!=putGetActive){ string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName() + " PvaClientPutGet::waitPutGet get or put aleady active "; throw std::runtime_error(message); } waitForPutGet.wait(); if(channelPutGetStatus.isOK()) pvaClientPutData->getChangedBitSet()->clear(); return channelPutGetStatus; } void PvaClientPutGet::getGet() { if(PvaClient::getDebug()) { cout << "PvaClientPutGet::getGet" << " channelName " << pvaClientChannel->getChannel()->getChannelName() << endl; } issueGetGet(); Status status = waitGetGet(); if(status.isOK()) return; string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName() + " PvaClientPut::getGet " + status.getMessage(); throw std::runtime_error(message); } void PvaClientPutGet::issueGetGet() { if(PvaClient::getDebug()) { cout << "PvaClientPutGet::issueGetGet" << " channelName " << pvaClientChannel->getChannel()->getChannelName() << endl; } if(connectState==connectIdle) connect(); if(putGetState==putGetActive) { string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName() + " PvaClientPutGet::issueGetGet get or put aleady active "; throw std::runtime_error(message); } putGetState = putGetActive; channelPutGet->getGet(); } Status PvaClientPutGet::waitGetGet() { if(PvaClient::getDebug()) { cout << "PvaClientPutGet::waitGetGet" << " channelName " << pvaClientChannel->getChannel()->getChannelName() << endl; } if(putGetState==putGetComplete) return channelPutGetStatus; if(putGetState!=putGetActive){ string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName() + " PvaClientPutGet::waitGetGet get or put aleady active "; throw std::runtime_error(message); } waitForPutGet.wait(); return channelPutGetStatus; } void PvaClientPutGet::getPut() { if(PvaClient::getDebug()) { cout << "PvaClientPutGet::getGetPut" << " channelName " << pvaClientChannel->getChannel()->getChannelName() << endl; } issueGetPut(); Status status = waitGetPut(); if(status.isOK()) return; string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName() + " PvaClientPut::getPut " + status.getMessage(); throw std::runtime_error(message); } void PvaClientPutGet::issueGetPut() { if(PvaClient::getDebug()) { cout << "PvaClientPutGet::issueGetPut" << " channelName " << pvaClientChannel->getChannel()->getChannelName() << endl; } if(connectState==connectIdle) connect(); if(putGetState==putGetActive) { string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName() + " PvaClientPutGet::issueGetPut get or put aleady active "; throw std::runtime_error(message); } putGetState = putGetActive; channelPutGet->getPut(); } Status PvaClientPutGet::waitGetPut() { if(PvaClient::getDebug()) { cout << "PvaClientPutGet::waitGetPut" << " channelName " << pvaClientChannel->getChannel()->getChannelName() << endl; } if(putGetState==putGetComplete) return channelPutGetStatus; if(putGetState!=putGetActive){ string message = string("channel ") + pvaClientChannel->getChannel()->getChannelName() + " PvaClientPutGet::waitGetPut get or put aleady active "; throw std::runtime_error(message); } waitForPutGet.wait(); return channelPutGetStatus; } PvaClientGetDataPtr PvaClientPutGet::getGetData() { if(PvaClient::getDebug()) { cout<< "PvaClientPutGet::getGetData" << " channelName " << pvaClientChannel->getChannel()->getChannelName() << endl; } checkPutGetState(); if(putGetState==putGetIdle){ getGet(); getPut(); } return pvaClientGetData; } PvaClientPutDataPtr PvaClientPutGet::getPutData() { if(PvaClient::getDebug()) { cout<< "PvaClientPutGet::getPutData" << " channelName " << pvaClientChannel->getChannel()->getChannelName() << endl; } checkPutGetState(); if(putGetState==putGetIdle){ getGet(); getPut(); } return pvaClientPutData; } void PvaClientPutGet::setRequester(PvaClientPutGetRequesterPtr const & pvaClientPutGetRequester) { if(PvaClient::getDebug()) { cout << "PvaClientPutGet::setRequester" << " channelName " << pvaClientChannel->getChannel()->getChannelName() << endl; } this->pvaClientPutGetRequester = pvaClientPutGetRequester; } PvaClientChannelPtr PvaClientPutGet::getPvaClientChannel() { return pvaClientChannel; } }}