diff --git a/src/ca/caChannel.cpp b/src/ca/caChannel.cpp index c60ab53..3580b4f 100644 --- a/src/ca/caChannel.cpp +++ b/src/ca/caChannel.cpp @@ -63,7 +63,23 @@ void CAChannel::connected() if(DEBUG_LEVEL>0) { cout<< "CAChannel::connected " << channelName << endl; } - channelConnectThread->channelConnected(notifyChannelRequester); + bool callChannelConnected = false; + { + Lock lock(requestsMutex); + if(!channelCreated) { + channelCreated = true; + callChannelConnected = true; + } + } + if(callChannelConnected) { + channelConnectThread->channelConnected(notifyChannelRequester); + return; + } + ChannelRequester::shared_pointer req(channelRequester.lock()); + if(req) { + EXCEPTION_GUARD(req->channelStateChange( + shared_from_this(), Channel::CONNECTED)); + } } void CAChannel::notifyClient() @@ -71,6 +87,13 @@ void CAChannel::notifyClient() if(DEBUG_LEVEL>0) { cout<< "CAChannel::notifyClient " << channelName << endl; } + CAChannelProviderPtr provider(channelProvider.lock()); + if(!provider) return; + provider->addChannel(shared_from_this()); + while(!getFieldQueue.empty()) { + getFieldQueue.front()->activate(); + getFieldQueue.pop(); + } while(!putQueue.empty()) { putQueue.front()->activate(); putQueue.pop(); @@ -86,10 +109,9 @@ void CAChannel::notifyClient() monitorQueue.pop(); } ChannelRequester::shared_pointer req(channelRequester.lock()); - if(req) { - EXCEPTION_GUARD(req->channelStateChange( - shared_from_this(), Channel::CONNECTED)); - } + if(!req) return; + EXCEPTION_GUARD(req->channelCreated(Status::Ok, shared_from_this())); + EXCEPTION_GUARD(req->channelStateChange(shared_from_this(), Channel::CONNECTED)); } void CAChannel::disconnected() @@ -122,11 +144,11 @@ CAChannel::CAChannel(std::string const & channelName, void CAChannel::activate(short priority) { + ChannelRequester::shared_pointer req(channelRequester.lock()); + if(!req) return; if(DEBUG_LEVEL>0) { cout<< "CAChannel::activate " << channelName << endl; } - ChannelRequester::shared_pointer req(channelRequester.lock()); - if(!req) return; notifyChannelRequester = NotifyChannelRequesterPtr(new NotifyChannelRequester()); notifyChannelRequester->setChannel(shared_from_this()); attachContext(); @@ -135,13 +157,8 @@ void CAChannel::activate(short priority) this, priority, // TODO mapping &channelID); - if (result == ECA_NORMAL) + if (result != ECA_NORMAL) { - channelCreated = true; - CAChannelProviderPtr provider(channelProvider.lock()); - if(provider) provider->addChannel(shared_from_this()); - EXCEPTION_GUARD(req->channelCreated(Status::Ok, shared_from_this())); - } else { Status errorStatus(Status::STATUSTYPE_ERROR, string(ca_message(result))); EXCEPTION_GUARD(req->channelCreated(errorStatus, shared_from_this())); } @@ -242,7 +259,8 @@ void CAChannel::getField(GetFieldRequester::shared_pointer const & requester, if(DEBUG_LEVEL>0) { cout << "CAChannel::getField " << channelName << endl; } - CAChannelGetFieldPtr getField(new CAChannelGetField(requester,subField)); + CAChannelGetFieldPtr getField( + new CAChannelGetField(shared_from_this(),requester,subField)); { Lock lock(requestsMutex); if(getConnectionState()!=Channel::CONNECTED) { @@ -356,8 +374,10 @@ void CAChannel::printInfo(std::ostream& out) CAChannelGetField::CAChannelGetField( + CAChannelPtr const &channel, GetFieldRequester::shared_pointer const & requester,std::string const & subField) - : getFieldRequester(requester), + : channel(channel), + getFieldRequester(requester), subField(subField) { if(DEBUG_LEVEL>0) { @@ -365,6 +385,12 @@ CAChannelGetField::CAChannelGetField( } } +void CAChannelGetField::activate() +{ + CAChannelPtr chan(channel.lock()); + if(chan) callRequester(chan); +} + CAChannelGetField::~CAChannelGetField() { if(DEBUG_LEVEL>0) { diff --git a/src/ca/caChannel.h b/src/ca/caChannel.h index 625ad81..8a6c068 100644 --- a/src/ca/caChannel.h +++ b/src/ca/caChannel.h @@ -74,10 +74,15 @@ class CAChannelGetField : { public: POINTER_DEFINITIONS(CAChannelGetField); - CAChannelGetField(GetFieldRequester::shared_pointer const & requester,std::string const & subField); + CAChannelGetField( + CAChannelPtr const &channel, + GetFieldRequester::shared_pointer const & requester, + std::string const & subField); ~CAChannelGetField(); void callRequester(CAChannelPtr const & caChannel); + void activate(); private: + CAChannelWPtr channel; GetFieldRequester::weak_pointer getFieldRequester; std::string subField; }; diff --git a/src/ca/caProvider.cpp b/src/ca/caProvider.cpp index f670add..09bcb8b 100644 --- a/src/ca/caProvider.cpp +++ b/src/ca/caProvider.cpp @@ -177,10 +177,8 @@ void CAChannelProvider::attachContext() { ca_client_context* thread_context = ca_current_context(); if (thread_context == current_context) return; - if (thread_context != NULL) { - throw std::runtime_error("CAChannelProvider::attachContext Foreign CA context in use"); - } int result = ca_attach_context(current_context); + if(result==ECA_ISATTACHED) return; if (result != ECA_NORMAL) { std::string mess("CAChannelProvider::attachContext error calling ca_attach_context "); mess += ca_message(result); diff --git a/src/ca/dbdToPv.cpp b/src/ca/dbdToPv.cpp index 636dc5e..09f30f7 100644 --- a/src/ca/dbdToPv.cpp +++ b/src/ca/dbdToPv.cpp @@ -392,7 +392,7 @@ Status DbdToPv::getFromDBD( copy_DBRScalarArray(value,count,pvValue); break; case DBR_LONG: - copy_DBRScalarArray(value,count,pvValue); + copy_DBRScalarArray(value,count,pvValue); break; case DBR_FLOAT: copy_DBRScalarArray(value,count,pvValue); @@ -430,7 +430,7 @@ Status DbdToPv::getFromDBD( case DBR_STRING: copy_DBRScalar(value,pvValue); break; case DBR_CHAR: copy_DBRScalar(value,pvValue); break; case DBR_SHORT: copy_DBRScalar(value,pvValue); break; - case DBR_LONG: copy_DBRScalar(value,pvValue); break; + case DBR_LONG: copy_DBRScalar(value,pvValue); break; case DBR_FLOAT: copy_DBRScalar(value,pvValue); break; case DBR_DOUBLE: copy_DBRScalar(value,pvValue); break; default: diff --git a/testCa/testCaProvider.cpp b/testCa/testCaProvider.cpp index ff275d3..b92c462 100644 --- a/testCa/testCaProvider.cpp +++ b/testCa/testCaProvider.cpp @@ -573,6 +573,7 @@ private: TestClient(string const &channelName,PVStructurePtr const & pvRequest); string channelName; PVStructurePtr pvRequest; + string putValue; TestChannelPtr testChannel; TestChannelGetPtr testChannelGet; TestChannelPutPtr testChannelPut; @@ -611,8 +612,14 @@ void TestClient::getDone( testOk(pvStructure->getSubField("timeStamp").get() != 0,"timeStamp not null"); testOk(pvStructure->getSubField("alarm").get() != 0,"alarm not null"); if (DEBUG) std::cout << testChannel->getChannelName() + " TestClient::getDone" + << " putValue " << putValue << " bitSet " << *bitSet << " pvStructure\n" << pvStructure << "\n"; + PVScalarPtr pvScalar = pvStructure->getSubField("value"); + if(pvScalar) { + string getValue = getConvert()->toString(pvScalar); + testOk(getValue.compare(putValue)==0,"getValue==putValue"); + } waitForGet.signal(); } @@ -649,6 +656,7 @@ void TestClient::put(string const & value) { testDiag("TestClient::put %s := %s", testChannel->getChannelName().c_str(), value.c_str()); + putValue = value; testChannelPut->put(value); waitPut(OPERATION_TIMEOUT); } @@ -756,7 +764,7 @@ void checkClient(const string &channelName, const string &putValue) MAIN(testCaProvider) { - testPlan(84 + EXIT_TESTS); + testPlan(143 + EXIT_TESTS); TestIocPtr testIoc(new TestIoc()); testIoc->start(); @@ -766,10 +774,16 @@ MAIN(testCaProvider) ChannelProviderRegistry::shared_pointer reg(ChannelProviderRegistry::clients()); try { ChannelProvider::shared_pointer channelProvider(reg->getProvider("ca")); - if (!channelProvider) - testAbort("Channel provider 'ca' not registered"); - - checkClient("DBRlongout", "5"); + if (!channelProvider) testAbort("Channel provider 'ca' not registered"); + checkClient("DBRlongout", "0"); + checkClient("DBRlongout", "1"); + checkClient("DBRlongout", "-1"); + checkClient("DBRlongout", "32767"); + checkClient("DBRlongout", "32768"); + checkClient("DBRlongout", "-32768"); + checkClient("DBRlongout", "-32769"); + checkClient("DBRlongout", "2147483647"); + checkClient("DBRlongout", "-2147483648"); checkClient("DBRdoubleout", "1.5"); checkClient("DBRstringout", "test"); checkClient("DBRbyteArray", "1 2 3");