completed merge
This commit is contained in:
4
TODO
4
TODO
@@ -1,5 +1,3 @@
|
||||
redefine size encoding to be able to carry negative values (to handle negative offsets), i.e. -128 means take larger integer size (same pattern for 32-bit integer). This also bings symmetric integer range (-value ... value).
|
||||
|
||||
opt) connection validation message sends max paylaod size
|
||||
readSize checks if size is in limits of size_t?
|
||||
|
||||
@@ -19,5 +17,3 @@ readSize checks if size is in limits of size_t?
|
||||
|
||||
void transportUnresponsive() { not implemented (also in Java)
|
||||
|
||||
socket termination - usage of epicsSocketSystemCallInterruptMechanismQuery() API
|
||||
|
||||
|
||||
@@ -9,80 +9,80 @@ configure/RULES_TOP
|
||||
documentation/pvAccessCPP.html
|
||||
documentation/README
|
||||
jenkins/cloudbees_build
|
||||
pvAccessApp/pva/pvaConstants.h
|
||||
pvAccessApp/pva/clientFactory.cpp
|
||||
pvAccessApp/pva/clientFactory.h
|
||||
pvAccessApp/pva/pvaVersion.cpp
|
||||
pvAccessApp/pva/pvaVersion.h
|
||||
pvAccessApp/client/pvAccess.cpp
|
||||
pvAccessApp/client/pvAccess.h
|
||||
pvAccessApp/factory/ChannelAccessFactory.cpp
|
||||
pvAccessApp/factory/CreateRequestFactory.cpp
|
||||
pvAccessApp/mb/pvAccessMB.cpp
|
||||
pvAccessApp/mb/pvAccessMB.h
|
||||
pvAccessApp/remote/abstractResponseHandler.cpp
|
||||
pvAccessApp/remote/beaconHandler.cpp
|
||||
pvAccessApp/remote/beaconHandler.h
|
||||
pvAccessApp/remote/blockingTCP.h
|
||||
pvAccessApp/remote/blockingTCPAcceptor.cpp
|
||||
pvAccessApp/remote/blockingTCPConnector.cpp
|
||||
pvAccessApp/remote/blockingUDP.h
|
||||
pvAccessApp/remote/blockingUDPConnector.cpp
|
||||
pvAccessApp/remote/blockingUDPTransport.cpp
|
||||
pvAccessApp/remote/channelSearchManager.h
|
||||
pvAccessApp/remote/remote.h
|
||||
pvAccessApp/remote/serializationHelper.cpp
|
||||
pvAccessApp/remote/serializationHelper.h
|
||||
pvAccessApp/remote/simpleChannelSearchManagerImpl.cpp
|
||||
pvAccessApp/remote/simpleChannelSearchManagerImpl.h
|
||||
pvAccessApp/remote/transportRegistry.cpp
|
||||
pvAccessApp/remote/transportRegistry.h
|
||||
pvAccessApp/remote/codec.cpp
|
||||
pvAccessApp/remote/codec.h
|
||||
pvAccessApp/remoteClient/clientContextImpl.cpp
|
||||
pvAccessApp/remoteClient/clientContextImpl.h
|
||||
pvAccessApp/remoteClient/clientContextImpl.h.orig
|
||||
pvAccessApp/rpcClient/rpcClient.cpp
|
||||
pvAccessApp/rpcClient/rpcClient.h
|
||||
pvAccessApp/rpcService/rpcServer.cpp
|
||||
pvAccessApp/rpcService/rpcServer.h
|
||||
pvAccessApp/rpcService/rpcService.h
|
||||
pvAccessApp/server/baseChannelRequester.cpp
|
||||
pvAccessApp/server/baseChannelRequester.h
|
||||
pvAccessApp/server/beaconEmitter.cpp
|
||||
pvAccessApp/server/beaconEmitter.h
|
||||
pvAccessApp/server/beaconServerStatusProvider.cpp
|
||||
pvAccessApp/server/beaconServerStatusProvider.h
|
||||
pvAccessApp/server/responseHandlers.cpp
|
||||
pvAccessApp/server/responseHandlers.h
|
||||
pvAccessApp/server/serverChannelImpl.cpp
|
||||
pvAccessApp/server/serverChannelImpl.h
|
||||
pvAccessApp/server/serverContext.cpp
|
||||
pvAccessApp/server/serverContext.h
|
||||
pvAccessApp/utils/configuration.cpp
|
||||
pvAccessApp/utils/configuration.h
|
||||
pvAccessApp/utils/hexDump.cpp
|
||||
pvAccessApp/utils/hexDump.h
|
||||
pvAccessApp/utils/inetAddressUtil.cpp
|
||||
pvAccessApp/utils/inetAddressUtil.h
|
||||
pvAccessApp/utils/introspectionRegistry.cpp
|
||||
pvAccessApp/utils/introspectionRegistry.h
|
||||
pvAccessApp/utils/likely.h
|
||||
pvAccessApp/utils/logger.cpp
|
||||
pvAccessApp/utils/logger.h
|
||||
pvAccessApp/utils/namedLockPattern.h
|
||||
pvAccessApp/utils/referenceCountingLock.cpp
|
||||
pvAccessApp/utils/referenceCountingLock.h
|
||||
src/pva/pvaConstants.h
|
||||
src/pva/clientFactory.cpp
|
||||
src/pva/clientFactory.h
|
||||
src/pva/pvaVersion.cpp
|
||||
src/pva/pvaVersion.h
|
||||
src/client/pvAccess.cpp
|
||||
src/client/pvAccess.h
|
||||
src/factory/ChannelAccessFactory.cpp
|
||||
src/factory/CreateRequestFactory.cpp
|
||||
src/mb/pvAccessMB.cpp
|
||||
src/mb/pvAccessMB.h
|
||||
src/remote/abstractResponseHandler.cpp
|
||||
src/remote/beaconHandler.cpp
|
||||
src/remote/beaconHandler.h
|
||||
src/remote/blockingTCP.h
|
||||
src/remote/blockingTCPAcceptor.cpp
|
||||
src/remote/blockingTCPConnector.cpp
|
||||
src/remote/blockingUDP.h
|
||||
src/remote/blockingUDPConnector.cpp
|
||||
src/remote/blockingUDPTransport.cpp
|
||||
src/remote/channelSearchManager.h
|
||||
src/remote/remote.h
|
||||
src/remote/serializationHelper.cpp
|
||||
src/remote/serializationHelper.h
|
||||
src/remote/simpleChannelSearchManagerImpl.cpp
|
||||
src/remote/simpleChannelSearchManagerImpl.h
|
||||
src/remote/transportRegistry.cpp
|
||||
src/remote/transportRegistry.h
|
||||
src/remote/codec.cpp
|
||||
src/remote/codec.h
|
||||
src/remoteClient/clientContextImpl.cpp
|
||||
src/remoteClient/clientContextImpl.h
|
||||
src/remoteClient/clientContextImpl.h.orig
|
||||
src/rpcClient/rpcClient.cpp
|
||||
src/rpcClient/rpcClient.h
|
||||
src/rpcService/rpcServer.cpp
|
||||
src/rpcService/rpcServer.h
|
||||
src/rpcService/rpcService.h
|
||||
src/server/baseChannelRequester.cpp
|
||||
src/server/baseChannelRequester.h
|
||||
src/server/beaconEmitter.cpp
|
||||
src/server/beaconEmitter.h
|
||||
src/server/beaconServerStatusProvider.cpp
|
||||
src/server/beaconServerStatusProvider.h
|
||||
src/server/responseHandlers.cpp
|
||||
src/server/responseHandlers.h
|
||||
src/server/serverChannelImpl.cpp
|
||||
src/server/serverChannelImpl.h
|
||||
src/server/serverContext.cpp
|
||||
src/server/serverContext.h
|
||||
src/utils/configuration.cpp
|
||||
src/utils/configuration.h
|
||||
src/utils/hexDump.cpp
|
||||
src/utils/hexDump.h
|
||||
src/utils/inetAddressUtil.cpp
|
||||
src/utils/inetAddressUtil.h
|
||||
src/utils/introspectionRegistry.cpp
|
||||
src/utils/introspectionRegistry.h
|
||||
src/utils/likely.h
|
||||
src/utils/logger.cpp
|
||||
src/utils/logger.h
|
||||
src/utils/namedLockPattern.h
|
||||
src/utils/referenceCountingLock.cpp
|
||||
src/utils/referenceCountingLock.h
|
||||
scripts/gcovr
|
||||
testApp/client/MockClientImpl.cpp
|
||||
testApp/client/testChannelAccessFactory.cpp
|
||||
testApp/client/testCreateRequest.cpp
|
||||
testApp/client/testMockClient.cpp
|
||||
testApp/client/testStartStop.cpp
|
||||
testApp/remote/eget.cpp
|
||||
pvtoolsSrc/eget.cpp
|
||||
testApp/remote/epicsv4Grayscale.h
|
||||
testApp/remote/pvget.cpp
|
||||
testApp/remote/pvput.cpp
|
||||
pvtoolsSrc/pvget.cpp
|
||||
pvtoolsSrc/pvput.cpp
|
||||
testApp/remote/pvutils.cpp
|
||||
testApp/remote/pvutils.h
|
||||
testApp/remote/rpcServiceExample.cpp
|
||||
@@ -115,11 +115,12 @@ Doxyfile
|
||||
README
|
||||
runTestServer
|
||||
TODO
|
||||
testApp/remote/pvinfo.cpp
|
||||
pvAccessApp/ca/caProvider.h
|
||||
pvAccessApp/ca/caProvider.cpp
|
||||
pvAccessApp/ca/caChannel.h
|
||||
pvAccessApp/ca/caChannel.cpp
|
||||
pvtoolsSrc/pvinfo.cpp
|
||||
src/ca/caProvider.h
|
||||
src/ca/caProvider.cpp
|
||||
src/ca/caChannel.h
|
||||
src/ca/caChannel.cpp
|
||||
testApp/utils/Makefile
|
||||
testApp/remote/channelAccessIFTest.cpp
|
||||
testApp/remote/channelAccessIFTest.h
|
||||
testApp/remote/channelAccessIFTest.cpp
|
||||
testApp/remote/syncTestRequesters.h
|
||||
@@ -1049,7 +1049,6 @@ private:
|
||||
String m_channelName;
|
||||
bool m_printValue;
|
||||
|
||||
ChannelGet::shared_pointer m_channelGet;
|
||||
PVStructure::shared_pointer m_pvStructure;
|
||||
BitSet::shared_pointer m_bitSet;
|
||||
Mutex m_pointerMutex;
|
||||
@@ -1076,9 +1075,9 @@ public:
|
||||
std::cerr << "[" << getRequesterName() << "] message(" << message << ", " << getMessageTypeName(messageType) << ")" << std::endl;
|
||||
}
|
||||
|
||||
virtual void channelGetConnect(const epics::pvData::Status& status,ChannelGet::shared_pointer const & channelGet,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvStructure,
|
||||
epics::pvData::BitSet::shared_pointer const & bitSet)
|
||||
virtual void channelGetConnect(const epics::pvData::Status& status,
|
||||
ChannelGet::shared_pointer const & channelGet,
|
||||
epics::pvData::Structure::const_shared_pointer const & /*structure*/)
|
||||
{
|
||||
if (status.isSuccess())
|
||||
{
|
||||
@@ -1088,15 +1087,8 @@ public:
|
||||
std::cerr << "[" << m_channelName << "] channel get create: " << status << std::endl;
|
||||
}
|
||||
|
||||
// assign smart pointers
|
||||
{
|
||||
Lock lock(m_pointerMutex);
|
||||
m_channelGet = channelGet;
|
||||
m_pvStructure = pvStructure;
|
||||
m_bitSet = bitSet;
|
||||
}
|
||||
|
||||
channelGet->get(true);
|
||||
channelGet->lastRequest();
|
||||
channelGet->get();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1105,7 +1097,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void getDone(const epics::pvData::Status& status)
|
||||
virtual void getDone(const epics::pvData::Status& status,
|
||||
ChannelGet::shared_pointer const & /*channelGet*/,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvStructure,
|
||||
epics::pvData::BitSet::shared_pointer const & bitSet)
|
||||
{
|
||||
if (status.isSuccess())
|
||||
{
|
||||
@@ -1118,30 +1113,19 @@ public:
|
||||
// access smart pointers
|
||||
{
|
||||
Lock lock(m_pointerMutex);
|
||||
m_pvStructure = pvStructure;
|
||||
m_bitSet = bitSet;
|
||||
m_done = true;
|
||||
|
||||
if (m_printValue)
|
||||
{
|
||||
m_done = true;
|
||||
|
||||
if (m_printValue)
|
||||
{
|
||||
// needed since we access the data
|
||||
ScopedLock dataLock(m_channelGet);
|
||||
|
||||
printValue(m_channelName, m_pvStructure);
|
||||
}
|
||||
printValue(m_channelName, m_pvStructure);
|
||||
}
|
||||
|
||||
// this is OK since callee holds also owns it
|
||||
m_channelGet.reset();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "[" << m_channelName << "] failed to get: " << status << std::endl;
|
||||
{
|
||||
Lock lock(m_pointerMutex);
|
||||
// this is OK since caller holds also owns it
|
||||
m_channelGet.reset();
|
||||
}
|
||||
}
|
||||
|
||||
m_event.signal();
|
||||
@@ -1171,10 +1155,10 @@ public:
|
||||
class ChannelRPCRequesterImpl : public ChannelRPCRequester
|
||||
{
|
||||
private:
|
||||
ChannelRPC::shared_pointer m_channelRPC;
|
||||
Mutex m_pointerMutex;
|
||||
Event m_event;
|
||||
Event m_connectionEvent;
|
||||
bool m_successfullyConnected;
|
||||
String m_channelName;
|
||||
|
||||
PVStructure::shared_pointer m_lastResponse;
|
||||
@@ -1182,7 +1166,12 @@ private:
|
||||
|
||||
public:
|
||||
|
||||
ChannelRPCRequesterImpl(String channelName) : m_channelName(channelName), m_done(false) {}
|
||||
ChannelRPCRequesterImpl(String channelName) :
|
||||
m_successfullyConnected(false),
|
||||
m_channelName(channelName),
|
||||
m_done(false)
|
||||
{
|
||||
}
|
||||
|
||||
virtual String getRequesterName()
|
||||
{
|
||||
@@ -1194,7 +1183,7 @@ public:
|
||||
std::cerr << "[" << getRequesterName() << "] message(" << message << ", " << getMessageTypeName(messageType) << ")" << std::endl;
|
||||
}
|
||||
|
||||
virtual void channelRPCConnect(const epics::pvData::Status& status,ChannelRPC::shared_pointer const & channelRPC)
|
||||
virtual void channelRPCConnect(const epics::pvData::Status& status, ChannelRPC::shared_pointer const & /*channelRPC*/)
|
||||
{
|
||||
if (status.isSuccess())
|
||||
{
|
||||
@@ -1204,10 +1193,9 @@ public:
|
||||
std::cerr << "[" << m_channelName << "] channel RPC create: " << status << std::endl;
|
||||
}
|
||||
|
||||
// assign smart pointers
|
||||
{
|
||||
{
|
||||
Lock lock(m_pointerMutex);
|
||||
m_channelRPC = channelRPC;
|
||||
m_successfullyConnected = status.isSuccess();
|
||||
}
|
||||
|
||||
m_connectionEvent.signal();
|
||||
@@ -1219,7 +1207,9 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void requestDone (const epics::pvData::Status &status, epics::pvData::PVStructure::shared_pointer const &pvResponse)
|
||||
virtual void requestDone (const epics::pvData::Status &status,
|
||||
ChannelRPC::shared_pointer const & /*channelRPC*/,
|
||||
epics::pvData::PVStructure::shared_pointer const &pvResponse)
|
||||
{
|
||||
if (status.isSuccess())
|
||||
{
|
||||
@@ -1240,19 +1230,11 @@ public:
|
||||
formatNT(std::cout, pvResponse);
|
||||
std::cout << std::endl;
|
||||
*/
|
||||
|
||||
// this is OK since calle holds also owns it
|
||||
m_channelRPC.reset();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "[" << m_channelName << "] failed to RPC: " << status << std::endl;
|
||||
{
|
||||
Lock lock(m_pointerMutex);
|
||||
// this is OK since caller holds also owns it
|
||||
m_channelRPC.reset();
|
||||
}
|
||||
}
|
||||
|
||||
m_event.signal();
|
||||
@@ -1294,12 +1276,8 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
bool connected;
|
||||
{
|
||||
Lock lock(m_pointerMutex);
|
||||
connected = (m_channelRPC.get() != 0);
|
||||
}
|
||||
return connected ? true : false;
|
||||
Lock lock(m_pointerMutex);
|
||||
return m_successfullyConnected;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1486,9 +1464,18 @@ int main (int argc, char *argv[])
|
||||
{
|
||||
string param = optarg;
|
||||
size_t eqPos = param.find('=');
|
||||
if (eqPos==0)
|
||||
{
|
||||
// no name
|
||||
|
||||
fprintf(stderr, "Parameter not specified in '-a name=value' form. ('eget -h' for help.)\n");
|
||||
return 1;
|
||||
}
|
||||
if (eqPos==string::npos)
|
||||
{
|
||||
//fprintf(stderr, "Parameter not specified in name=value form. ('eget -h' for help.)\n");
|
||||
// no value
|
||||
|
||||
//fprintf(stderr, "Parameter not specified in '-a name=value' form. ('eget -h' for help.)\n");
|
||||
//return 1;
|
||||
parameters.push_back(pair<string,string>(param, ""));
|
||||
}
|
||||
@@ -1729,7 +1716,7 @@ int main (int argc, char *argv[])
|
||||
{
|
||||
shared_ptr<ChannelRequesterImpl> channelRequesterImpl(new ChannelRequesterImpl(quiet));
|
||||
// TODO no provider check
|
||||
channels[n] = getChannelAccess()->getProvider(providerNames[n])->createChannel(pvs[n], channelRequesterImpl);
|
||||
channels[n] = getChannelProviderRegistry()->getProvider(providerNames[n])->createChannel(pvs[n], channelRequesterImpl);
|
||||
}
|
||||
|
||||
// TODO maybe unify for nPvs == 1?!
|
||||
@@ -1803,7 +1790,7 @@ int main (int argc, char *argv[])
|
||||
|
||||
shared_ptr<ChannelRequesterImpl> channelRequesterImpl(new ChannelRequesterImpl(quiet));
|
||||
// TODO no provider check
|
||||
channel = getChannelAccess()->getProvider(cp)->createChannel(cn, channelRequesterImpl);
|
||||
channel = getChannelProviderRegistry()->getProvider(cp)->createChannel(cn, channelRequesterImpl);
|
||||
}
|
||||
|
||||
if (monitor)
|
||||
@@ -2035,7 +2022,7 @@ int main (int argc, char *argv[])
|
||||
|
||||
|
||||
ClientFactory::start();
|
||||
ChannelProvider::shared_pointer provider = getChannelAccess()->getProvider("pva");
|
||||
ChannelProvider::shared_pointer provider = getChannelProviderRegistry()->getProvider("pva");
|
||||
|
||||
shared_ptr<ChannelRequesterImpl> channelRequesterImpl(new ChannelRequesterImpl(quiet));
|
||||
Channel::shared_pointer channel =
|
||||
@@ -2051,7 +2038,8 @@ int main (int argc, char *argv[])
|
||||
|
||||
if (rpcRequesterImpl->waitUntilConnected(timeOut))
|
||||
{
|
||||
channelRPC->request(arg, true);
|
||||
channelRPC->lastRequest();
|
||||
channelRPC->request(arg);
|
||||
allOK &= rpcRequesterImpl->waitUntilRPC(timeOut);
|
||||
if (allOK)
|
||||
{
|
||||
|
||||
@@ -102,7 +102,6 @@ void printValue(String const & channelName, PVStructure::shared_pointer const &
|
||||
class ChannelGetRequesterImpl : public ChannelGetRequester
|
||||
{
|
||||
private:
|
||||
ChannelGet::shared_pointer m_channelGet;
|
||||
PVStructure::shared_pointer m_pvStructure;
|
||||
BitSet::shared_pointer m_bitSet;
|
||||
Mutex m_pointerMutex;
|
||||
@@ -125,9 +124,8 @@ class ChannelGetRequesterImpl : public ChannelGetRequester
|
||||
std::cerr << "[" << getRequesterName() << "] message(" << message << ", " << getMessageTypeName(messageType) << ")" << std::endl;
|
||||
}
|
||||
|
||||
virtual void channelGetConnect(const epics::pvData::Status& status,ChannelGet::shared_pointer const & channelGet,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvStructure,
|
||||
epics::pvData::BitSet::shared_pointer const & bitSet)
|
||||
virtual void channelGetConnect(const epics::pvData::Status& status, ChannelGet::shared_pointer const & channelGet,
|
||||
epics::pvData::Structure::const_shared_pointer const & /*structure*/)
|
||||
{
|
||||
if (status.isSuccess())
|
||||
{
|
||||
@@ -137,15 +135,8 @@ class ChannelGetRequesterImpl : public ChannelGetRequester
|
||||
std::cerr << "[" << m_channelName << "] channel get create: " << status << std::endl;
|
||||
}
|
||||
|
||||
// assign smart pointers
|
||||
{
|
||||
Lock lock(m_pointerMutex);
|
||||
m_channelGet = channelGet;
|
||||
m_pvStructure = pvStructure;
|
||||
m_bitSet = bitSet;
|
||||
}
|
||||
|
||||
channelGet->get(true);
|
||||
channelGet->lastRequest();
|
||||
channelGet->get();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -154,7 +145,10 @@ class ChannelGetRequesterImpl : public ChannelGetRequester
|
||||
}
|
||||
}
|
||||
|
||||
virtual void getDone(const epics::pvData::Status& status)
|
||||
virtual void getDone(const epics::pvData::Status& status,
|
||||
ChannelGet::shared_pointer const & /*channelGet*/,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvStructure,
|
||||
epics::pvData::BitSet::shared_pointer const & bitSet)
|
||||
{
|
||||
if (status.isSuccess())
|
||||
{
|
||||
@@ -167,30 +161,17 @@ class ChannelGetRequesterImpl : public ChannelGetRequester
|
||||
// access smart pointers
|
||||
{
|
||||
Lock lock(m_pointerMutex);
|
||||
|
||||
m_pvStructure = pvStructure;
|
||||
m_bitSet = bitSet;
|
||||
|
||||
m_done = true;
|
||||
|
||||
/*
|
||||
{
|
||||
// needed since we access the data
|
||||
ScopedLock dataLock(m_channelGet);
|
||||
|
||||
printValue(m_channelName, m_pvStructure);
|
||||
|
||||
}
|
||||
*/
|
||||
// this is OK since callee holds also owns it
|
||||
m_channelGet.reset();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cerr << "[" << m_channelName << "] failed to get: " << status << std::endl;
|
||||
{
|
||||
Lock lock(m_pointerMutex);
|
||||
// this is OK since caller holds also owns it
|
||||
m_channelGet.reset();
|
||||
}
|
||||
}
|
||||
|
||||
m_event.signal();
|
||||
@@ -484,10 +465,10 @@ int main (int argc, char *argv[])
|
||||
}
|
||||
|
||||
ClientFactory::start();
|
||||
ChannelProvider::shared_pointer provider = getChannelAccess()->getProvider("pva");
|
||||
ChannelProvider::shared_pointer provider = getChannelProviderRegistry()->getProvider("pva");
|
||||
|
||||
//epics::pvAccess::ca::CAClientFactory::start();
|
||||
//ChannelProvider::shared_pointer provider = getChannelAccess()->getProvider("ca");
|
||||
//ChannelProvider::shared_pointer provider = getChannelProviderRegistry()->getProvider("ca");
|
||||
|
||||
// first connect to all, this allows resource (e.g. TCP connection) sharing
|
||||
vector<Channel::shared_pointer> channels(nPvs);
|
||||
|
||||
@@ -122,7 +122,7 @@ int main (int argc, char *argv[])
|
||||
Requester::shared_pointer requester(new RequesterImpl("pvinfo"));
|
||||
|
||||
ClientFactory::start();
|
||||
ChannelProvider::shared_pointer provider = getChannelAccess()->getProvider("pva");
|
||||
ChannelProvider::shared_pointer provider = getChannelProviderRegistry()->getProvider("pva");
|
||||
|
||||
// first connect to all, this allows resource (e.g. TCP connection) sharing
|
||||
vector<Channel::shared_pointer> channels(nPvs);
|
||||
|
||||
@@ -251,7 +251,6 @@ class AtomicBoolean
|
||||
class ChannelPutRequesterImpl : public ChannelPutRequester
|
||||
{
|
||||
private:
|
||||
ChannelPut::shared_pointer m_channelPut;
|
||||
PVStructure::shared_pointer m_pvStructure;
|
||||
BitSet::shared_pointer m_bitSet;
|
||||
Mutex m_pointerMutex;
|
||||
@@ -279,8 +278,7 @@ class ChannelPutRequesterImpl : public ChannelPutRequester
|
||||
|
||||
virtual void channelPutConnect(const epics::pvData::Status& status,
|
||||
ChannelPut::shared_pointer const & channelPut,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvStructure,
|
||||
epics::pvData::BitSet::shared_pointer const & bitSet)
|
||||
epics::pvData::Structure::const_shared_pointer const & /*structure*/)
|
||||
{
|
||||
if (status.isSuccess())
|
||||
{
|
||||
@@ -290,17 +288,6 @@ class ChannelPutRequesterImpl : public ChannelPutRequester
|
||||
std::cerr << "[" << m_channelName << "] channel put create: " << status << std::endl;
|
||||
}
|
||||
|
||||
// assign smart pointers
|
||||
{
|
||||
Lock lock(m_pointerMutex);
|
||||
m_channelPut = channelPut;
|
||||
m_pvStructure = pvStructure;
|
||||
m_bitSet = bitSet;
|
||||
}
|
||||
|
||||
// we always put all
|
||||
m_bitSet->set(0);
|
||||
|
||||
// get immediately old value
|
||||
channelPut->get();
|
||||
}
|
||||
@@ -311,7 +298,9 @@ class ChannelPutRequesterImpl : public ChannelPutRequester
|
||||
}
|
||||
}
|
||||
|
||||
virtual void getDone(const epics::pvData::Status& status)
|
||||
virtual void getDone(const epics::pvData::Status& status, ChannelPut::shared_pointer const & /*channelPut*/,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvStructure,
|
||||
epics::pvData::BitSet::shared_pointer const & bitSet)
|
||||
{
|
||||
if (status.isSuccess())
|
||||
{
|
||||
@@ -323,21 +312,12 @@ class ChannelPutRequesterImpl : public ChannelPutRequester
|
||||
|
||||
m_done.set();
|
||||
|
||||
/*
|
||||
// access smart pointers
|
||||
// do not print old value in terseMode
|
||||
if (!m_supressGetValue.get())
|
||||
{
|
||||
Lock lock(m_pointerMutex);
|
||||
{
|
||||
|
||||
// needed since we access the data
|
||||
ScopedLock dataLock(m_channelPut);
|
||||
|
||||
printValue(m_channelName, m_pvStructure);
|
||||
}
|
||||
m_pvStructure = pvStructure;
|
||||
// we always put all, so current bitSet is OK
|
||||
m_bitSet = bitSet;
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
else
|
||||
@@ -348,7 +328,7 @@ class ChannelPutRequesterImpl : public ChannelPutRequester
|
||||
m_event->signal();
|
||||
}
|
||||
|
||||
virtual void putDone(const epics::pvData::Status& status)
|
||||
virtual void putDone(const epics::pvData::Status& status, ChannelPut::shared_pointer const & /*channelPut*/)
|
||||
{
|
||||
if (status.isSuccess())
|
||||
{
|
||||
@@ -374,6 +354,12 @@ class ChannelPutRequesterImpl : public ChannelPutRequester
|
||||
return m_pvStructure;
|
||||
}
|
||||
|
||||
BitSet::shared_pointer getBitSet()
|
||||
{
|
||||
Lock lock(m_pointerMutex);
|
||||
return m_bitSet;
|
||||
}
|
||||
|
||||
void resetEvent()
|
||||
{
|
||||
Lock lock(m_eventMutex);
|
||||
@@ -551,10 +537,10 @@ int main (int argc, char *argv[])
|
||||
terseSeparator(fieldSeparator);
|
||||
|
||||
ClientFactory::start();
|
||||
ChannelProvider::shared_pointer provider = getChannelAccess()->getProvider("pva");
|
||||
ChannelProvider::shared_pointer provider = getChannelProviderRegistry()->getProvider("pva");
|
||||
|
||||
//epics::pvAccess::ca::CAClientFactory::start();
|
||||
//ChannelProvider::shared_pointer provider = getChannelAccess()->getProvider("ca");
|
||||
//ChannelProvider::shared_pointer provider = getChannelProviderRegistry()->getProvider("ca");
|
||||
|
||||
bool allOK = true;
|
||||
|
||||
@@ -587,7 +573,8 @@ int main (int argc, char *argv[])
|
||||
|
||||
// we do a put
|
||||
putRequesterImpl->resetEvent();
|
||||
channelPut->put(false);
|
||||
// note on bitSet: we get all, we set all
|
||||
channelPut->put(putRequesterImpl->getStructure(), putRequesterImpl->getBitSet());
|
||||
allOK &= putRequesterImpl->waitUntilDone(timeOut);
|
||||
|
||||
if (allOK)
|
||||
|
||||
@@ -16,4 +16,4 @@ fi
|
||||
|
||||
# testServer
|
||||
echo "Starting pvAccess C++ test server..."
|
||||
./bin/$EPICS_HOST_ARCH/testServer
|
||||
./bin/$EPICS_HOST_ARCH/testServer $*
|
||||
|
||||
@@ -343,7 +343,7 @@ ChannelPutGet::shared_pointer CAChannel::createChannelPutGet(
|
||||
Status errorStatus(Status::STATUSTYPE_ERROR, "not supported");
|
||||
ChannelPutGet::shared_pointer nullChannelPutGet;
|
||||
EXCEPTION_GUARD(channelPutGetRequester->channelPutGetConnect(errorStatus, nullChannelPutGet,
|
||||
PVStructure::shared_pointer(), PVStructure::shared_pointer()));
|
||||
Structure::const_shared_pointer(), Structure::const_shared_pointer()));
|
||||
return nullChannelPutGet;
|
||||
}
|
||||
|
||||
@@ -374,7 +374,7 @@ ChannelArray::shared_pointer CAChannel::createChannelArray(
|
||||
Status errorStatus(Status::STATUSTYPE_ERROR, "not supported");
|
||||
ChannelArray::shared_pointer nullChannelArray;
|
||||
EXCEPTION_GUARD(channelArrayRequester->channelArrayConnect(errorStatus, nullChannelArray,
|
||||
PVArray::shared_pointer()));
|
||||
Array::const_shared_pointer()));
|
||||
return nullChannelArray;
|
||||
}
|
||||
|
||||
@@ -527,7 +527,7 @@ CAChannelGet::CAChannelGet(CAChannel::shared_pointer const & _channel,
|
||||
void CAChannelGet::activate()
|
||||
{
|
||||
EXCEPTION_GUARD(channelGetRequester->channelGetConnect(Status::Ok, shared_from_this(),
|
||||
pvStructure, bitSet));
|
||||
pvStructure->getStructure()));
|
||||
}
|
||||
|
||||
|
||||
@@ -852,17 +852,17 @@ void CAChannelGet::getDone(struct event_handler_args &args)
|
||||
std::cout << "no copy func implemented" << std::endl;
|
||||
}
|
||||
|
||||
EXCEPTION_GUARD(channelGetRequester->getDone(Status::Ok));
|
||||
EXCEPTION_GUARD(channelGetRequester->getDone(Status::Ok, shared_from_this(), pvStructure, bitSet));
|
||||
}
|
||||
else
|
||||
{
|
||||
Status errorStatus(Status::STATUSTYPE_ERROR, String(ca_message(args.status)));
|
||||
EXCEPTION_GUARD(channelGetRequester->getDone(errorStatus));
|
||||
EXCEPTION_GUARD(channelGetRequester->getDone(errorStatus, shared_from_this(), PVStructure::shared_pointer(), BitSet::shared_pointer()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CAChannelGet::get(bool lastRequest)
|
||||
void CAChannelGet::get()
|
||||
{
|
||||
int result = ca_array_get_callback(getType, channel->getElementCount(),
|
||||
channel->getChannelID(), ca_get_handler, this);
|
||||
@@ -873,14 +873,32 @@ void CAChannelGet::get(bool lastRequest)
|
||||
else
|
||||
{
|
||||
Status errorStatus(Status::STATUSTYPE_ERROR, String(ca_message(result)));
|
||||
EXCEPTION_GUARD(channelGetRequester->getDone(errorStatus));
|
||||
EXCEPTION_GUARD(channelGetRequester->getDone(errorStatus, shared_from_this(), PVStructure::shared_pointer(), BitSet::shared_pointer()));
|
||||
}
|
||||
|
||||
if (lastRequest)
|
||||
if (lastRequestFlag)
|
||||
destroy();
|
||||
}
|
||||
|
||||
|
||||
/* --------------- epics::pvData::ChannelRequest --------------- */
|
||||
|
||||
Channel::shared_pointer CAChannelGet::getChannel()
|
||||
{
|
||||
return channel;
|
||||
}
|
||||
|
||||
void CAChannelGet::cancel()
|
||||
{
|
||||
// noop
|
||||
}
|
||||
|
||||
void CAChannelGet::lastRequest()
|
||||
{
|
||||
// TODO sync !!!
|
||||
lastRequestFlag = true;
|
||||
}
|
||||
|
||||
/* --------------- epics::pvData::Destroyable --------------- */
|
||||
|
||||
|
||||
@@ -948,7 +966,7 @@ CAChannelPut::CAChannelPut(CAChannel::shared_pointer const & _channel,
|
||||
void CAChannelPut::activate()
|
||||
{
|
||||
EXCEPTION_GUARD(channelPutRequester->channelPutConnect(Status::Ok, shared_from_this(),
|
||||
pvStructure, bitSet));
|
||||
pvStructure->getStructure()));
|
||||
}
|
||||
|
||||
|
||||
@@ -1103,26 +1121,28 @@ void CAChannelPut::putDone(struct event_handler_args &args)
|
||||
{
|
||||
if (args.status == ECA_NORMAL)
|
||||
{
|
||||
EXCEPTION_GUARD(channelPutRequester->putDone(Status::Ok));
|
||||
EXCEPTION_GUARD(channelPutRequester->putDone(Status::Ok, shared_from_this()));
|
||||
}
|
||||
else
|
||||
{
|
||||
Status errorStatus(Status::STATUSTYPE_ERROR, String(ca_message(args.status)));
|
||||
EXCEPTION_GUARD(channelPutRequester->putDone(errorStatus));
|
||||
EXCEPTION_GUARD(channelPutRequester->putDone(errorStatus, shared_from_this()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CAChannelPut::put(bool lastRequest)
|
||||
void CAChannelPut::put(PVStructure::shared_pointer const & pvPutStructure,
|
||||
BitSet::shared_pointer const & /*putBitSet*/)
|
||||
{
|
||||
doPut putFunc = doPutFuncTable[channel->getNativeType()];
|
||||
if (putFunc)
|
||||
{
|
||||
int result = putFunc(channel, this, pvStructure);
|
||||
// TODO now we always put all
|
||||
int result = putFunc(channel, this, pvPutStructure);
|
||||
if (result != ECA_NORMAL)
|
||||
{
|
||||
Status errorStatus(Status::STATUSTYPE_ERROR, String(ca_message(result)));
|
||||
EXCEPTION_GUARD(channelPutRequester->getDone(errorStatus));
|
||||
EXCEPTION_GUARD(channelPutRequester->putDone(errorStatus, shared_from_this()));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1132,7 +1152,7 @@ void CAChannelPut::put(bool lastRequest)
|
||||
}
|
||||
|
||||
// TODO here???!!!
|
||||
if (lastRequest)
|
||||
if (lastRequestFlag)
|
||||
destroy();
|
||||
}
|
||||
|
||||
@@ -1150,13 +1170,18 @@ void CAChannelPut::getDone(struct event_handler_args &args)
|
||||
std::cout << "no copy func implemented" << std::endl;
|
||||
}
|
||||
|
||||
EXCEPTION_GUARD(channelPutRequester->getDone(Status::Ok));
|
||||
EXCEPTION_GUARD(channelPutRequester->getDone(Status::Ok, shared_from_this(), pvStructure, bitSet));
|
||||
}
|
||||
else
|
||||
{
|
||||
Status errorStatus(Status::STATUSTYPE_ERROR, String(ca_message(args.status)));
|
||||
EXCEPTION_GUARD(channelPutRequester->getDone(errorStatus));
|
||||
EXCEPTION_GUARD(channelPutRequester->getDone(errorStatus, shared_from_this(),
|
||||
PVStructure::shared_pointer(), BitSet::shared_pointer()));
|
||||
}
|
||||
|
||||
// TODO here???!!!
|
||||
if (lastRequestFlag)
|
||||
destroy();
|
||||
}
|
||||
|
||||
|
||||
@@ -1171,11 +1196,31 @@ void CAChannelPut::get()
|
||||
else
|
||||
{
|
||||
Status errorStatus(Status::STATUSTYPE_ERROR, String(ca_message(result)));
|
||||
EXCEPTION_GUARD(channelPutRequester->getDone(errorStatus));
|
||||
EXCEPTION_GUARD(channelPutRequester->getDone(errorStatus, shared_from_this(),
|
||||
PVStructure::shared_pointer(), BitSet::shared_pointer()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* --------------- epics::pvData::ChannelRequest --------------- */
|
||||
|
||||
Channel::shared_pointer CAChannelPut::getChannel()
|
||||
{
|
||||
return channel;
|
||||
}
|
||||
|
||||
void CAChannelPut::cancel()
|
||||
{
|
||||
// noop
|
||||
}
|
||||
|
||||
void CAChannelPut::lastRequest()
|
||||
{
|
||||
// TODO sync !!!
|
||||
lastRequestFlag = true;
|
||||
}
|
||||
|
||||
/* --------------- epics::pvData::Destroyable --------------- */
|
||||
|
||||
|
||||
@@ -1350,6 +1395,14 @@ void CAChannelMonitor::release(epics::pvData::MonitorElementPtr const & /*monito
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* --------------- epics::pvData::ChannelRequest --------------- */
|
||||
|
||||
void CAChannelMonitor::cancel()
|
||||
{
|
||||
// noop
|
||||
}
|
||||
|
||||
/* --------------- epics::pvData::Destroyable --------------- */
|
||||
|
||||
|
||||
|
||||
@@ -142,7 +142,13 @@ public:
|
||||
|
||||
/* --------------- epics::pvAccess::ChannelGet --------------- */
|
||||
|
||||
virtual void get(bool lastRequest);
|
||||
virtual void get();
|
||||
|
||||
/* --------------- epics::pvData::ChannelRequest --------------- */
|
||||
|
||||
virtual Channel::shared_pointer getChannel();
|
||||
virtual void cancel();
|
||||
virtual void lastRequest();
|
||||
|
||||
/* --------------- epics::pvData::Destroyable --------------- */
|
||||
|
||||
@@ -166,6 +172,9 @@ private:
|
||||
|
||||
epics::pvData::PVStructure::shared_pointer pvStructure;
|
||||
epics::pvData::BitSet::shared_pointer bitSet;
|
||||
|
||||
// TODO AtomicBoolean !!!
|
||||
bool lastRequestFlag;
|
||||
};
|
||||
|
||||
|
||||
@@ -189,9 +198,18 @@ public:
|
||||
|
||||
/* --------------- epics::pvAccess::ChannelPut --------------- */
|
||||
|
||||
virtual void put(bool lastRequest);
|
||||
virtual void put(
|
||||
epics::pvData::PVStructure::shared_pointer const & pvPutStructure,
|
||||
epics::pvData::BitSet::shared_pointer const & putBitSet
|
||||
);
|
||||
virtual void get();
|
||||
|
||||
/* --------------- epics::pvData::ChannelRequest --------------- */
|
||||
|
||||
virtual Channel::shared_pointer getChannel();
|
||||
virtual void cancel();
|
||||
virtual void lastRequest();
|
||||
|
||||
/* --------------- epics::pvData::Destroyable --------------- */
|
||||
|
||||
virtual void destroy();
|
||||
@@ -214,6 +232,9 @@ private:
|
||||
|
||||
epics::pvData::PVStructure::shared_pointer pvStructure;
|
||||
epics::pvData::BitSet::shared_pointer bitSet;
|
||||
|
||||
// TODO AtomicBoolean !!!
|
||||
bool lastRequestFlag;
|
||||
};
|
||||
|
||||
|
||||
@@ -240,6 +261,10 @@ public:
|
||||
virtual epics::pvData::MonitorElementPtr poll();
|
||||
virtual void release(epics::pvData::MonitorElementPtr const & monitorElement);
|
||||
|
||||
/* --------------- epics::pvData::ChannelRequest --------------- */
|
||||
|
||||
virtual void cancel();
|
||||
|
||||
/* --------------- epics::pvData::Destroyable --------------- */
|
||||
|
||||
virtual void destroy();
|
||||
|
||||
@@ -57,6 +57,19 @@ ChannelFind::shared_pointer CAChannelProvider::channelFind(
|
||||
return nullChannelFind;
|
||||
}
|
||||
|
||||
ChannelFind::shared_pointer CAChannelProvider::channelList(
|
||||
ChannelListRequester::shared_pointer const & channelListRequester)
|
||||
{
|
||||
if (!channelListRequester.get())
|
||||
throw std::runtime_error("null requester");
|
||||
|
||||
Status errorStatus(Status::STATUSTYPE_ERROR, "not implemented");
|
||||
ChannelFind::shared_pointer nullChannelFind;
|
||||
PVStringArray::const_svector none;
|
||||
EXCEPTION_GUARD(channelListRequester->channelListResult(errorStatus, nullChannelFind, none, false));
|
||||
return nullChannelFind;
|
||||
}
|
||||
|
||||
Channel::shared_pointer CAChannelProvider::createChannel(
|
||||
epics::pvData::String const & channelName,
|
||||
ChannelRequester::shared_pointer const & channelRequester,
|
||||
|
||||
@@ -35,6 +35,8 @@ public:
|
||||
epics::pvData::String const & channelName,
|
||||
ChannelFindRequester::shared_pointer const & channelFindRequester);
|
||||
|
||||
virtual ChannelFind::shared_pointer channelList(
|
||||
ChannelListRequester::shared_pointer const & channelListRequester);
|
||||
|
||||
virtual Channel::shared_pointer createChannel(
|
||||
epics::pvData::String const & channelName,
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#endif
|
||||
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/createRequest.h>
|
||||
#include <pv/status.h>
|
||||
#include <pv/destroyable.h>
|
||||
#include <pv/monitor.h>
|
||||
@@ -113,6 +114,28 @@ namespace pvAccess {
|
||||
class epicsShareClass ChannelRequest : public epics::pvData::Destroyable, public Lockable, private epics::pvData::NoDefaultMethods {
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelRequest);
|
||||
|
||||
/**
|
||||
* Get a channel instance this request belongs to.
|
||||
* @return the channel instance.
|
||||
*/
|
||||
virtual std::tr1::shared_ptr<Channel> getChannel() = 0;
|
||||
|
||||
/**
|
||||
* Cancel any pending request.
|
||||
* Completion will be reported via request's response callback:
|
||||
* <ul>
|
||||
* <li>if cancel() request is issued after the request was already complete, request success/failure completion will be reported and cancel() request ignored.</li>
|
||||
* <li>if the request was actually canceled, cancellation completion is reported.</li>
|
||||
* </ul>
|
||||
*/
|
||||
virtual void cancel() = 0;
|
||||
|
||||
/**
|
||||
* Announce next request as last request.
|
||||
* When last request will be completed (regardless of completion status) the remote and local instance will be destroyed.
|
||||
*/
|
||||
virtual void lastRequest() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -125,27 +148,34 @@ namespace pvAccess {
|
||||
|
||||
/**
|
||||
* put to the remote array.
|
||||
* @param lastRequest Is this the last request.
|
||||
* @param putArray array to put.
|
||||
* @param offset The offset in the remote array, i.e. the PVArray returned by ChannelArrayRequester.channelArrayConnect.
|
||||
* @param count The number of elements to put.
|
||||
* @param count The number of elements to put, 0 means "entire array".
|
||||
* @param stride 1 means all the elements from offset to count, 2 means every other, 3 means every third, etc.
|
||||
*/
|
||||
virtual void putArray(bool lastRequest, int offset, int count) = 0;
|
||||
virtual void putArray(
|
||||
epics::pvData::PVArray::shared_pointer const & putArray,
|
||||
size_t offset = 0, size_t count = 0, size_t stride = 1) = 0;
|
||||
|
||||
/**
|
||||
* get from the remote array.
|
||||
* @param lastRequest Is this the last request.
|
||||
* @param offset The offset in the remote array, i.e. the PVArray returned by ChannelArrayRequester.channelArrayConnect.
|
||||
* @param count The number of elements to get.
|
||||
* @param count The number of elements to get, 0 means "till the end of an array".
|
||||
* @param stride 1 means all the elements from offset to count, 2 means every other, 3 means every third, etc.
|
||||
*/
|
||||
virtual void getArray(bool lastRequest, int offset, int count) = 0;
|
||||
virtual void getArray(size_t offset = 0, size_t count = 0, size_t stride = 1) = 0;
|
||||
|
||||
/**
|
||||
* Get the length and the capacity.
|
||||
*/
|
||||
virtual void getLength() = 0;
|
||||
|
||||
/**
|
||||
* Set the length and/or the capacity.
|
||||
* @param lastRequest Is this the last request.
|
||||
* @param length The new length. -1 means do not change.
|
||||
* @param capacity The new capacity. -1 means do not change.
|
||||
* @param length The new length.
|
||||
* @param capacity The new capacity, 0 means do "do not change the capacity".
|
||||
*/
|
||||
virtual void setLength(bool lastRequest, int length, int capacity) = 0;
|
||||
virtual void setLength(size_t length, size_t capacity = 0) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -158,10 +188,30 @@ namespace pvAccess {
|
||||
/**
|
||||
* The client and server have both completed the createChannelArray request.
|
||||
* @param status Completion status.
|
||||
* @param channelArray The channelArray interface or null if the request failed.
|
||||
* @param pvArray The PVArray that holds the data.
|
||||
* @param channelArray The channelArray interface or <code>null</code> if the request failed.
|
||||
* @param pvArray The PVArray that holds the data or <code>null</code> if the request failed.
|
||||
*/
|
||||
virtual void channelArrayConnect(
|
||||
const epics::pvData::Status& status,
|
||||
ChannelArray::shared_pointer const & channelArray,
|
||||
epics::pvData::Array::const_shared_pointer const & array) = 0;
|
||||
|
||||
/**
|
||||
* The request is done. This is always called with no locks held.
|
||||
* @param status Completion status.
|
||||
* @param channelArray The channelArray interface.
|
||||
*/
|
||||
virtual void putArrayDone(
|
||||
const epics::pvData::Status& status,
|
||||
ChannelArray::shared_pointer const & channelArray) = 0;
|
||||
|
||||
/**
|
||||
* The request is done. This is always called with no locks held.
|
||||
* @param status Completion status.
|
||||
* @param channelArray The channelArray interface.
|
||||
* @param pvArray The PVArray that holds the data or <code>null</code> if the request failed.
|
||||
*/
|
||||
virtual void getArrayDone(
|
||||
const epics::pvData::Status& status,
|
||||
ChannelArray::shared_pointer const & channelArray,
|
||||
epics::pvData::PVArray::shared_pointer const & pvArray) = 0;
|
||||
@@ -169,20 +219,23 @@ namespace pvAccess {
|
||||
/**
|
||||
* The request is done. This is always called with no locks held.
|
||||
* @param status Completion status.
|
||||
* @param channelArray The channelArray interface.
|
||||
* @param length The length of the array, 0 if the request failed.
|
||||
* @param capacity The capacity of the array, 0 if the request failed.
|
||||
*/
|
||||
virtual void putArrayDone(const epics::pvData::Status& status) = 0;
|
||||
virtual void getLengthDone(
|
||||
const epics::pvData::Status& status,
|
||||
ChannelArray::shared_pointer const & channelArray,
|
||||
size_t length, size_t capacity) = 0;
|
||||
|
||||
/**
|
||||
* The request is done. This is always called with no locks held.
|
||||
* @param status Completion status.
|
||||
* @param channelArray The channelArray interface.
|
||||
*/
|
||||
virtual void getArrayDone(const epics::pvData::Status& status) = 0;
|
||||
|
||||
/**
|
||||
* The request is done. This is always called with no locks held.
|
||||
* @param status Completion status.
|
||||
*/
|
||||
virtual void setLengthDone(const epics::pvData::Status& status) = 0;
|
||||
virtual void setLengthDone(
|
||||
const epics::pvData::Status& status,
|
||||
ChannelArray::shared_pointer const & channelArray) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -194,7 +247,7 @@ namespace pvAccess {
|
||||
POINTER_DEFINITIONS(ChannelFind);
|
||||
|
||||
virtual std::tr1::shared_ptr<ChannelProvider> getChannelProvider() = 0;
|
||||
virtual void cancelChannelFind() = 0;
|
||||
virtual void cancel() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -205,12 +258,34 @@ namespace pvAccess {
|
||||
POINTER_DEFINITIONS(ChannelFindRequester);
|
||||
|
||||
virtual ~ChannelFindRequester() {};
|
||||
|
||||
/**
|
||||
* @param status Completion status.
|
||||
*/
|
||||
virtual void channelFindResult(const epics::pvData::Status& status,ChannelFind::shared_pointer const & channelFind,bool wasFound) = 0;
|
||||
virtual void channelFindResult(
|
||||
const epics::pvData::Status& status,
|
||||
ChannelFind::shared_pointer const & channelFind,
|
||||
bool wasFound) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
class epicsShareClass ChannelListRequester {
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelListRequester);
|
||||
|
||||
virtual ~ChannelListRequester() {};
|
||||
|
||||
/**
|
||||
* @param status Completion status.
|
||||
*/
|
||||
virtual void channelListResult(
|
||||
const epics::pvData::Status& status,
|
||||
ChannelFind::shared_pointer const & channelFind,
|
||||
epics::pvData::PVStringArray::const_svector const & channelNames,
|
||||
bool hasDynamic) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Request to get data from a channel.
|
||||
@@ -221,11 +296,9 @@ namespace pvAccess {
|
||||
|
||||
/**
|
||||
* Get data from the channel.
|
||||
* This fails if the request can not be satisfied.
|
||||
* If it fails ChannelGetRequester.getDone is called before get returns.
|
||||
* @param lastRequest Is this the last request?
|
||||
* Completion status is reported by calling ChannelGetRequester.getDone() callback.
|
||||
*/
|
||||
virtual void get(bool lastRequest) = 0;
|
||||
virtual void get() = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -239,18 +312,26 @@ namespace pvAccess {
|
||||
/**
|
||||
* The client and server have both completed the createChannelGet request.
|
||||
* @param status Completion status.
|
||||
* @param channelGet The channelGet interface or null if the request failed.
|
||||
* @param pvStructure The PVStructure that holds the data.
|
||||
* @param bitSet The bitSet for that shows what data has changed.
|
||||
* @param channelGet The channelGet interface or <code>null</code> if the request failed.
|
||||
* @param structure The introspection interface of requested get structure or <code>null</code> if the request failed.
|
||||
*/
|
||||
virtual void channelGetConnect(const epics::pvData::Status& status,ChannelGet::shared_pointer const & channelGet,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvStructure,epics::pvData::BitSet::shared_pointer const & bitSet) = 0;
|
||||
virtual void channelGetConnect(
|
||||
const epics::pvData::Status& status,
|
||||
ChannelGet::shared_pointer const & channelGet,
|
||||
epics::pvData::Structure::const_shared_pointer const & structure) = 0;
|
||||
|
||||
/**
|
||||
* The request is done. This is always called with no locks held.
|
||||
* @param status Completion status.
|
||||
* @param channelGet The channelGet interface.
|
||||
* @param pvStructure The PVStructure that holds the data or <code>null</code> if the request failed.
|
||||
* @param bitSet The bitSet for that shows what data has changed or <code>null</code> if the request failed.
|
||||
*/
|
||||
virtual void getDone(const epics::pvData::Status& status) = 0;
|
||||
virtual void getDone(
|
||||
const epics::pvData::Status& status,
|
||||
ChannelGet::shared_pointer const & channelGet,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvStructure,
|
||||
epics::pvData::BitSet::shared_pointer const & bitSet) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -263,11 +344,9 @@ namespace pvAccess {
|
||||
|
||||
/**
|
||||
* Issue a process request.
|
||||
* This fails if the request can not be satisfied.
|
||||
* If it fails the channelProcessRequester.processDone is called before process returns.
|
||||
* @param lastRequest Is this the last request?
|
||||
* Completion status is reported by calling ChannelProcessRequester.processDone() callback.
|
||||
*/
|
||||
virtual void process(bool lastRequest) = 0;
|
||||
virtual void process() = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -281,33 +360,40 @@ namespace pvAccess {
|
||||
/**
|
||||
* The client and server have both completed the createChannelProcess request.
|
||||
* @param status Completion status.
|
||||
* @param channelProcess The channelProcess interface or null if the client could not become
|
||||
* @param channelProcess The channelProcess interface or <code>null</code> if the client could not become
|
||||
* the record processor.
|
||||
*/
|
||||
virtual void channelProcessConnect(const epics::pvData::Status& status,ChannelProcess::shared_pointer const & channelProcess) = 0;
|
||||
virtual void channelProcessConnect(
|
||||
const epics::pvData::Status& status,
|
||||
ChannelProcess::shared_pointer const & channelProcess) = 0;
|
||||
|
||||
/**
|
||||
* The process request is done. This is always called with no locks held.
|
||||
* @param status Completion status.
|
||||
* @param channelProcess The channelProcess interface.
|
||||
*/
|
||||
virtual void processDone(const epics::pvData::Status& status) = 0;
|
||||
virtual void processDone(
|
||||
const epics::pvData::Status& status,
|
||||
ChannelProcess::shared_pointer const & channelProcess) = 0;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Interface for a channel access put request.
|
||||
*/
|
||||
class epicsShareClass ChannelPut : public ChannelRequest {
|
||||
class epicsShareClass ChannelPut : public ChannelRequest {
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelPut);
|
||||
|
||||
/**
|
||||
* Put data to a channel.
|
||||
* This fails if the request can not be satisfied.
|
||||
* If it fails ChannelPutRequester.putDone is called before put returns.
|
||||
* @param lastRequest Is this the last request?
|
||||
* Completion status is reported by calling ChannelPutRequester.putDone() callback.
|
||||
* @param pvPutStructure The PVStructure that holds the putData.
|
||||
* @param putBitSet putPVStructure bit-set (selects what fields to put).
|
||||
*/
|
||||
virtual void put(bool lastRequest) = 0;
|
||||
virtual void put(
|
||||
epics::pvData::PVStructure::shared_pointer const & pvPutStructure,
|
||||
epics::pvData::BitSet::shared_pointer const & putBitSet) = 0;
|
||||
|
||||
/**
|
||||
* Get the current data.
|
||||
@@ -327,23 +413,34 @@ namespace pvAccess {
|
||||
* The client and server have both processed the createChannelPut request.
|
||||
* @param status Completion status.
|
||||
* @param channelPut The channelPut interface or null if the request failed.
|
||||
* @param pvStructure The PVStructure that holds the data.
|
||||
* @param bitSet The bitSet for that shows what data has changed.
|
||||
* @param structure The introspection interface of requested put/get structure or <code>null</code> if the request failed.
|
||||
*/
|
||||
virtual void channelPutConnect(const epics::pvData::Status& status,ChannelPut::shared_pointer const & channelPut,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvStructure,epics::pvData::BitSet::shared_pointer const & bitSet) = 0;
|
||||
virtual void channelPutConnect(
|
||||
const epics::pvData::Status& status,
|
||||
ChannelPut::shared_pointer const & channelPut,
|
||||
epics::pvData::Structure::const_shared_pointer const & structure) = 0;
|
||||
|
||||
/**
|
||||
* The request is done. This is always called with no locks held.
|
||||
* @param status Completion status.
|
||||
* @param channelPut The channelPut interface.
|
||||
*/
|
||||
virtual void putDone(const epics::pvData::Status& status) = 0;
|
||||
virtual void putDone(
|
||||
const epics::pvData::Status& status,
|
||||
ChannelPut::shared_pointer const & channelPut) = 0;
|
||||
|
||||
/**
|
||||
* The get request is done. This is always called with no locks held.
|
||||
* @param status Completion status.
|
||||
* @param channelPut The channelPut interface.
|
||||
* @param pvStructure The PVStructure that holds the data or <code>null</code> if the request failed.
|
||||
* @param bitSet The bitSet for that shows what data has changed or <code>null</code> if the request failed.
|
||||
*/
|
||||
virtual void getDone(const epics::pvData::Status& status) = 0;
|
||||
virtual void getDone(
|
||||
const epics::pvData::Status& status,
|
||||
ChannelPut::shared_pointer const & channelPut,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvStructure,
|
||||
epics::pvData::BitSet::shared_pointer const & bitSet) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -357,19 +454,23 @@ namespace pvAccess {
|
||||
|
||||
/**
|
||||
* Issue a put/get request. If process was requested when the ChannelPutGet was created this is a put, process, get.
|
||||
* This fails if the request can not be satisfied.
|
||||
* If it fails ChannelPutGetRequester.putDone is called before putGet returns.
|
||||
* @param lastRequest Is this the last request?
|
||||
* Completion status is reported by calling ChannelPutGetRequester.putGetDone() callback.
|
||||
* @param pvPutStructure The PVStructure that holds the putData.
|
||||
* @param putBitSet putPVStructure bit-set (selects what fields to put).
|
||||
*/
|
||||
virtual void putGet(bool lastRequest) = 0;
|
||||
virtual void putGet(
|
||||
epics::pvData::PVStructure::shared_pointer const & pvPutStructure,
|
||||
epics::pvData::BitSet::shared_pointer const & putBitSet) = 0;
|
||||
|
||||
/**
|
||||
* Get the put PVStructure. The record will not be processed.
|
||||
* Completion status is reported by calling ChannelPutGetRequester.getPutDone() callback.
|
||||
*/
|
||||
virtual void getPut() = 0;
|
||||
|
||||
/**
|
||||
* Get the get PVStructure. The record will not be processed.
|
||||
* Completion status is reported by calling ChannelPutGetRequester.getGetDone() callback.
|
||||
*/
|
||||
virtual void getGet() = 0;
|
||||
};
|
||||
@@ -387,28 +488,53 @@ namespace pvAccess {
|
||||
* The client and server have both completed the createChannelPutGet request.
|
||||
* @param status Completion status.
|
||||
* @param channelPutGet The channelPutGet interface or null if the request failed.
|
||||
* @param pvPutStructure The PVStructure that holds the putData.
|
||||
* @param pvGetStructure The PVStructure that holds the getData.
|
||||
* @param putStructure The put structure introspection data or <code>null</code> if the request failed.
|
||||
* @param getStructure The get structure introspection data or <code>null</code> if the request failed.
|
||||
*/
|
||||
virtual void channelPutGetConnect(const epics::pvData::Status& status,ChannelPutGet::shared_pointer const & channelPutGet,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvPutStructure,epics::pvData::PVStructure::shared_pointer const & pvGetStructure) = 0;
|
||||
virtual void channelPutGetConnect(
|
||||
const epics::pvData::Status& status,
|
||||
ChannelPutGet::shared_pointer const & channelPutGet,
|
||||
epics::pvData::Structure::const_shared_pointer const & putStructure,
|
||||
epics::pvData::Structure::const_shared_pointer const & getStructure) = 0;
|
||||
|
||||
/**
|
||||
* The putGet request is done. This is always called with no locks held.
|
||||
* @param status Completion status.
|
||||
* @param channelPutGet The channelPutGet interface.
|
||||
* @param pvGetStructure The PVStructure that holds the getData or <code>null</code> if the request failed.
|
||||
* @param getBitSet getPVStructure changed bit-set or <code>null</code> if the request failed.
|
||||
*/
|
||||
virtual void putGetDone(const epics::pvData::Status& status) = 0;
|
||||
virtual void putGetDone(
|
||||
const epics::pvData::Status& status,
|
||||
ChannelPutGet::shared_pointer const & channelPutGet,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvGetStructure,
|
||||
epics::pvData::BitSet::shared_pointer const & getBitSet) = 0;
|
||||
|
||||
/**
|
||||
* The getPut request is done. This is always called with no locks held.
|
||||
* @param status Completion status.
|
||||
* @param channelPutGet The channelPutGet interface.
|
||||
* @param pvPutStructure The PVStructure that holds the putData or <code>null</code> if the request failed.
|
||||
* @param putBitSet putPVStructure changed bit-set or <code>null</code> if the request failed.
|
||||
*/
|
||||
virtual void getPutDone(const epics::pvData::Status& status) = 0;
|
||||
virtual void getPutDone(
|
||||
const epics::pvData::Status& status,
|
||||
ChannelPutGet::shared_pointer const & channelPutGet,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvPutStructure,
|
||||
epics::pvData::BitSet::shared_pointer const & putBitSet) = 0;
|
||||
|
||||
/**
|
||||
* The getGet request is done. This is always called with no locks held.
|
||||
* @param status Completion status.
|
||||
* @param channelPutGet The channelPutGet interface.
|
||||
* @param pvGetStructure The PVStructure that holds the getData or <code>null</code> if the request failed.
|
||||
* @param getBitSet getPVStructure changed bit-set or <code>null</code> if the request failed.
|
||||
*/
|
||||
virtual void getGetDone(const epics::pvData::Status& status) = 0;
|
||||
virtual void getGetDone(
|
||||
const epics::pvData::Status& status,
|
||||
ChannelPutGet::shared_pointer const & channelPutGet,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvGetStructure,
|
||||
epics::pvData::BitSet::shared_pointer const & getBitSet) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -421,11 +547,10 @@ namespace pvAccess {
|
||||
|
||||
/**
|
||||
* Issue an RPC request to the channel.
|
||||
* This fails if the request can not be satisfied.
|
||||
* Completion status is reported by calling ChannelRPCRequester.requestDone() callback.
|
||||
* @param pvArgument The argument structure for an RPC request.
|
||||
* @param lastRequest Is this the last request?
|
||||
*/
|
||||
virtual void request(epics::pvData::PVStructure::shared_pointer const & pvArgument, bool lastRequest) = 0;
|
||||
virtual void request(epics::pvData::PVStructure::shared_pointer const & pvArgument) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -439,16 +564,22 @@ namespace pvAccess {
|
||||
/**
|
||||
* The client and server have both completed the createChannelGet request.
|
||||
* @param status Completion status.
|
||||
* @param channelRPC The channelRPC interface or null if the request failed.
|
||||
* @param channelRPC The channelRPC interface or <code>null</code> if the request failed.
|
||||
*/
|
||||
virtual void channelRPCConnect(const epics::pvData::Status& status,ChannelRPC::shared_pointer const & channelRPC) = 0;
|
||||
virtual void channelRPCConnect(
|
||||
const epics::pvData::Status& status,
|
||||
ChannelRPC::shared_pointer const & channelRPC) = 0;
|
||||
|
||||
/**
|
||||
* The request is done. This is always called with no locks held.
|
||||
* @param status Completion status.
|
||||
* @param pvResponse The response data for the RPC request.
|
||||
* @param channelRPC The channelRPC interface.
|
||||
* @param pvResponse The response data for the RPC request or <code>null</code> if the request failed.
|
||||
*/
|
||||
virtual void requestDone(const epics::pvData::Status& status,epics::pvData::PVStructure::shared_pointer const & pvResponse) = 0;
|
||||
virtual void requestDone(
|
||||
const epics::pvData::Status& status,
|
||||
ChannelRPC::shared_pointer const & channelRPC,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvResponse) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -464,8 +595,10 @@ namespace pvAccess {
|
||||
* @param status Completion status.
|
||||
* @param field The Structure for the request.
|
||||
*/
|
||||
// TODO naming convention
|
||||
virtual void getDone(const epics::pvData::Status& status,epics::pvData::FieldConstPtr const & field) = 0;
|
||||
virtual void getDone(
|
||||
const epics::pvData::Status& status,
|
||||
epics::pvData::FieldConstPtr const & field) = 0; // TODO naming convention
|
||||
|
||||
};
|
||||
|
||||
|
||||
@@ -711,6 +844,13 @@ namespace pvAccess {
|
||||
virtual ChannelFind::shared_pointer channelFind(epics::pvData::String const & channelName,
|
||||
ChannelFindRequester::shared_pointer const & channelFindRequester) = 0;
|
||||
|
||||
/**
|
||||
* Find channels.
|
||||
* @param channelFindRequester The epics::pvData::Requester.
|
||||
* @return An interface for the find.
|
||||
*/
|
||||
virtual ChannelFind::shared_pointer channelList(ChannelListRequester::shared_pointer const & channelListRequester) = 0;
|
||||
|
||||
/**
|
||||
* Create a channel.
|
||||
* @param channelName The name of the channel.
|
||||
@@ -769,13 +909,13 @@ namespace pvAccess {
|
||||
/**
|
||||
* Interface for locating channel providers.
|
||||
*/
|
||||
class epicsShareClass ChannelAccess : private epics::pvData::NoDefaultMethods {
|
||||
class epicsShareClass ChannelProviderRegistry : private epics::pvData::NoDefaultMethods {
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelAccess);
|
||||
POINTER_DEFINITIONS(ChannelProviderRegistry);
|
||||
|
||||
typedef std::vector<epics::pvData::String> stringVector_t;
|
||||
|
||||
virtual ~ChannelAccess() {};
|
||||
virtual ~ChannelProviderRegistry() {};
|
||||
|
||||
/**
|
||||
* Get a shared instance of the provider with the specified name.
|
||||
@@ -798,40 +938,10 @@ namespace pvAccess {
|
||||
virtual std::auto_ptr<stringVector_t> getProviderNames() = 0;
|
||||
};
|
||||
|
||||
epicsShareExtern ChannelAccess::shared_pointer getChannelAccess();
|
||||
epicsShareExtern ChannelProviderRegistry::shared_pointer getChannelProviderRegistry();
|
||||
epicsShareExtern void registerChannelProviderFactory(ChannelProviderFactory::shared_pointer const & channelProviderFactory);
|
||||
epicsShareExtern void unregisterChannelProviderFactory(ChannelProviderFactory::shared_pointer const & channelProviderFactory);
|
||||
|
||||
/**
|
||||
* Interface for creating request structure.
|
||||
*/
|
||||
class epicsShareClass CreateRequest {
|
||||
public:
|
||||
POINTER_DEFINITIONS(CreateRequest);
|
||||
static CreateRequest::shared_pointer create();
|
||||
virtual ~CreateRequest() {};
|
||||
|
||||
/**
|
||||
* Create a request structure for the create calls in Channel.
|
||||
* See the package overview documentation for details.
|
||||
* @param request The field request. See the package overview documentation for details.
|
||||
* @param requester The requester;
|
||||
* @return The request PVStructure if a valid request was given.
|
||||
* If a NULL PVStructure is returned then getMessage will return
|
||||
* the reason.
|
||||
*/
|
||||
virtual epics::pvData::PVStructure::shared_pointer createRequest(
|
||||
epics::pvData::String const & request) = 0;
|
||||
/**
|
||||
* Get the error message of createRequest returns NULL;
|
||||
* @return the error message
|
||||
*/
|
||||
epics::pvData::String getMessage() {return message;}
|
||||
protected:
|
||||
CreateRequest() {}
|
||||
epics::pvData::String message;
|
||||
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ using namespace epics::pvData;
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
static ChannelAccess::shared_pointer channelAccess;
|
||||
static ChannelProviderRegistry::shared_pointer ChannelProviderRegistry;
|
||||
|
||||
static Mutex channelProviderMutex;
|
||||
|
||||
@@ -28,7 +28,7 @@ typedef std::map<String, ChannelProviderFactory::shared_pointer> ChannelProvider
|
||||
static ChannelProviderFactoryMap channelProviders;
|
||||
|
||||
|
||||
class ChannelAccessImpl : public ChannelAccess {
|
||||
class ChannelProviderRegistryImpl : public ChannelProviderRegistry {
|
||||
public:
|
||||
|
||||
ChannelProvider::shared_pointer getProvider(String const & _providerName) {
|
||||
@@ -68,14 +68,14 @@ class ChannelAccessImpl : public ChannelAccess {
|
||||
}
|
||||
};
|
||||
|
||||
ChannelAccess::shared_pointer getChannelAccess() {
|
||||
ChannelProviderRegistry::shared_pointer getChannelProviderRegistry() {
|
||||
static Mutex mutex;
|
||||
Lock guard(mutex);
|
||||
|
||||
if(channelAccess.get()==0){
|
||||
channelAccess.reset(new ChannelAccessImpl());
|
||||
if(ChannelProviderRegistry.get()==0){
|
||||
ChannelProviderRegistry.reset(new ChannelProviderRegistryImpl());
|
||||
}
|
||||
return channelAccess;
|
||||
return ChannelProviderRegistry;
|
||||
}
|
||||
|
||||
void registerChannelProviderFactory(ChannelProviderFactory::shared_pointer const & channelProviderFactory) {
|
||||
|
||||
@@ -1,302 +0,0 @@
|
||||
/**
|
||||
* Copyright - See the COPYRIGHT that is included with this distribution.
|
||||
* pvAccessCPP is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
|
||||
#include <pv/pvData.h>
|
||||
#include <pv/lock.h>
|
||||
|
||||
#define epicsExportSharedSymbols
|
||||
#include <pv/pvAccess.h>
|
||||
|
||||
using namespace epics::pvData;
|
||||
using std::tr1::static_pointer_cast;
|
||||
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
static PVDataCreatePtr pvDataCreate = getPVDataCreate();
|
||||
|
||||
class CreateRequestImpl : public CreateRequest {
|
||||
private:
|
||||
|
||||
static void removeBlanks(String& str)
|
||||
{
|
||||
while(true) {
|
||||
String::size_type pos = str.find_first_of(' ');
|
||||
if(pos==String::npos) return;
|
||||
str.erase(pos,1);
|
||||
}
|
||||
}
|
||||
|
||||
static size_t findMatchingBrace(String& request, size_t index, int numOpen) {
|
||||
size_t openBrace = request.find('{', index+1);
|
||||
size_t closeBrace = request.find('}', index+1);
|
||||
if(openBrace == String::npos && closeBrace == std::string::npos) return std::string::npos;
|
||||
if (openBrace != String::npos && openBrace!=0) {
|
||||
if(openBrace<closeBrace) return findMatchingBrace(request,openBrace,numOpen+1);
|
||||
if(numOpen==1) return closeBrace;
|
||||
return findMatchingBrace(request,closeBrace,numOpen-1);
|
||||
}
|
||||
if(numOpen==1) return closeBrace;
|
||||
return findMatchingBrace(request,closeBrace,numOpen-1);
|
||||
}
|
||||
|
||||
static std::vector<String> split(String const & commaSeparatedList) {
|
||||
String::size_type numValues = 1;
|
||||
String::size_type index=0;
|
||||
while(true) {
|
||||
String::size_type pos = commaSeparatedList.find(',',index);
|
||||
if(pos==String::npos) break;
|
||||
numValues++;
|
||||
index = pos +1;
|
||||
}
|
||||
std::vector<String> valueList(numValues,"");
|
||||
index=0;
|
||||
for(size_t i=0; i<numValues; i++) {
|
||||
size_t pos = commaSeparatedList.find(',',index);
|
||||
String value = commaSeparatedList.substr(index,pos-index);
|
||||
valueList[i] = value;
|
||||
index = pos +1;
|
||||
}
|
||||
return valueList;
|
||||
}
|
||||
|
||||
|
||||
bool createRequestOptions(
|
||||
PVStructurePtr const & pvParent,
|
||||
String request)
|
||||
{
|
||||
removeBlanks(request);
|
||||
if(request.length()<=1) return true;
|
||||
std::vector<String> items = split(request);
|
||||
size_t nitems = items.size();
|
||||
StringArray fieldNames;
|
||||
PVFieldPtrArray pvFields;
|
||||
fieldNames.reserve(nitems);
|
||||
pvFields.reserve(nitems);
|
||||
for(size_t j=0; j<nitems; j++) {
|
||||
String item = items[j];
|
||||
size_t equals = item.find('=');
|
||||
if(equals==String::npos || equals==0) {
|
||||
message = item + " illegal option";
|
||||
return false;
|
||||
}
|
||||
String name = item.substr(0,equals);
|
||||
String value = item.substr(equals+1);
|
||||
fieldNames.push_back(name);
|
||||
PVStringPtr pvValue = static_pointer_cast<PVString>(getPVDataCreate()->createPVScalar(pvString));
|
||||
pvValue->put(value);
|
||||
pvFields.push_back(pvValue);
|
||||
}
|
||||
PVStructurePtr pvOptions = getPVDataCreate()->createPVStructure(fieldNames,pvFields);
|
||||
pvParent->appendPVField("_options",pvOptions);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool createFieldRequest(
|
||||
PVStructurePtr const & pvParent,
|
||||
String request)
|
||||
{
|
||||
static PVFieldPtrArray emptyFields;
|
||||
static StringArray emptyFieldNames;
|
||||
|
||||
removeBlanks(request);
|
||||
if(request.length()<=0) return true;
|
||||
size_t comma = request.find(',');
|
||||
if(comma==0) {
|
||||
return createFieldRequest(pvParent,request.substr(1));
|
||||
}
|
||||
size_t openBrace = request.find('{');
|
||||
size_t openBracket = request.find('[');
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(emptyFieldNames, emptyFields);
|
||||
if(comma==String::npos && openBrace==std::string::npos && openBracket==std::string::npos) {
|
||||
size_t period = request.find('.');
|
||||
if(period!=String::npos && period!=0) {
|
||||
String fieldName = request.substr(0,period);
|
||||
request = request.substr(period+1);
|
||||
pvParent->appendPVField(fieldName, pvStructure);
|
||||
return createFieldRequest(pvStructure,request);
|
||||
}
|
||||
pvParent->appendPVField(request, pvStructure);
|
||||
return true;
|
||||
}
|
||||
size_t end = comma;
|
||||
if(openBrace!=String::npos && (end>openBrace || end==std::string::npos)) end = openBrace;
|
||||
if(openBracket!=String::npos && (end>openBracket || end==std::string::npos)) end = openBracket;
|
||||
String nextFieldName = request.substr(0,end);
|
||||
if(end==comma) {
|
||||
size_t period = nextFieldName.find('.');
|
||||
if(period!=String::npos && period!=0) {
|
||||
String fieldName = nextFieldName.substr(0,period);
|
||||
PVStructurePtr xxx= pvDataCreate->createPVStructure(emptyFieldNames, emptyFields);
|
||||
String rest = nextFieldName.substr(period+1);
|
||||
createFieldRequest(xxx,rest);
|
||||
pvParent->appendPVField(fieldName, xxx);
|
||||
} else {
|
||||
pvParent->appendPVField(nextFieldName, pvStructure);
|
||||
}
|
||||
request = request.substr(end+1);
|
||||
return createFieldRequest(pvParent,request);
|
||||
}
|
||||
if(end==openBracket) {
|
||||
size_t closeBracket = request.find(']');
|
||||
if(closeBracket==String::npos || closeBracket==0) {
|
||||
message = request + " does not have matching ]";
|
||||
return false;
|
||||
}
|
||||
String options = request.substr(openBracket+1, closeBracket-openBracket-1);
|
||||
size_t period = nextFieldName.find('.');
|
||||
if(period!=String::npos && period!=0) {
|
||||
String fieldName = nextFieldName.substr(0,period);
|
||||
PVStructurePtr xxx = pvDataCreate->createPVStructure(emptyFieldNames, emptyFields);
|
||||
if(!createRequestOptions(xxx,options)) return false;
|
||||
String rest = nextFieldName.substr(period+1);
|
||||
createFieldRequest(xxx,rest);
|
||||
pvParent->appendPVField(fieldName, xxx);
|
||||
} else {
|
||||
if(!createRequestOptions(pvStructure,options)) return false;
|
||||
pvParent->appendPVField(nextFieldName, pvStructure);
|
||||
}
|
||||
request = request.substr(end+1);
|
||||
return createFieldRequest(pvParent,request);
|
||||
}
|
||||
// end== openBrace
|
||||
size_t closeBrace = findMatchingBrace(request,openBrace+1,1);
|
||||
if(closeBrace==String::npos || closeBrace==0) {
|
||||
message = request + " does not have matching }";
|
||||
return false;
|
||||
}
|
||||
String subFields = request.substr(openBrace+1, closeBrace-openBrace-1);
|
||||
if(!createFieldRequest(pvStructure,subFields)) return false;
|
||||
request = request.substr(closeBrace+1);
|
||||
size_t period = nextFieldName.find('.');
|
||||
if(period==String::npos) {
|
||||
pvParent->appendPVField(nextFieldName,pvStructure);
|
||||
return createFieldRequest(pvParent,request);
|
||||
}
|
||||
PVStructure::shared_pointer yyy = pvParent;
|
||||
while(period!=String::npos && period!=0) {
|
||||
String fieldName = nextFieldName.substr(0,period);
|
||||
PVStructurePtr xxx = pvDataCreate->createPVStructure(emptyFieldNames, emptyFields);
|
||||
yyy->appendPVField(fieldName,xxx);
|
||||
nextFieldName = nextFieldName.substr(period+1);
|
||||
period = nextFieldName.find('.');
|
||||
if(period==String::npos || period==0) {
|
||||
xxx->appendPVField(nextFieldName, pvStructure);
|
||||
break;
|
||||
}
|
||||
yyy = xxx;
|
||||
}
|
||||
return createFieldRequest(pvParent,request);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
virtual PVStructure::shared_pointer createRequest(
|
||||
String const & crequest)
|
||||
{
|
||||
String request = crequest;
|
||||
PVFieldPtrArray pvFields;
|
||||
StringArray fieldNames;
|
||||
PVStructurePtr emptyPVStructure = pvDataCreate->createPVStructure(fieldNames,pvFields);
|
||||
static PVStructure::shared_pointer nullStructure;
|
||||
|
||||
if (!request.empty()) removeBlanks(request);
|
||||
if (request.empty())
|
||||
{
|
||||
return emptyPVStructure;
|
||||
}
|
||||
size_t offsetRecord = request.find("record[");
|
||||
size_t offsetField = request.find("field(");
|
||||
size_t offsetPutField = request.find("putField(");
|
||||
size_t offsetGetField = request.find("getField(");
|
||||
PVStructurePtr pvStructure = pvDataCreate->createPVStructure(emptyPVStructure);
|
||||
if (offsetRecord != String::npos) {
|
||||
size_t offsetBegin = request.find('[', offsetRecord);
|
||||
size_t offsetEnd = request.find(']', offsetBegin);
|
||||
if(offsetEnd == String::npos) {
|
||||
message = request.substr(offsetRecord)
|
||||
+ " record[ does not have matching ]";
|
||||
return nullStructure;
|
||||
}
|
||||
PVStructurePtr pvStruct = pvDataCreate->createPVStructure(emptyPVStructure);
|
||||
if(!createRequestOptions(
|
||||
pvStruct,request.substr(offsetBegin+1,
|
||||
offsetEnd-offsetBegin-1)))
|
||||
{
|
||||
return nullStructure;
|
||||
}
|
||||
pvStructure->appendPVField("record", pvStruct);
|
||||
}
|
||||
if (offsetField != String::npos) {
|
||||
size_t offsetBegin = request.find('(', offsetField);
|
||||
size_t offsetEnd = request.find(')', offsetBegin);
|
||||
if(offsetEnd == String::npos) {
|
||||
message = request.substr(offsetField)
|
||||
+ " field( does not have matching )";
|
||||
return nullStructure;
|
||||
}
|
||||
PVStructurePtr pvStruct = pvDataCreate->createPVStructure(emptyPVStructure);
|
||||
if(!createFieldRequest(
|
||||
pvStruct,request.substr(offsetBegin+1,
|
||||
offsetEnd-offsetBegin-1)))
|
||||
{
|
||||
return nullStructure;
|
||||
}
|
||||
pvStructure->appendPVField("field", pvStruct);
|
||||
}
|
||||
if (offsetPutField != String::npos) {
|
||||
size_t offsetBegin = request.find('(', offsetPutField);
|
||||
size_t offsetEnd = request.find(')', offsetBegin);
|
||||
if(offsetEnd == String::npos) {
|
||||
message = request.substr(offsetField)
|
||||
+ " putField( does not have matching )";
|
||||
return nullStructure;
|
||||
}
|
||||
PVStructurePtr pvStruct = pvDataCreate->createPVStructure(emptyPVStructure);
|
||||
if(!createFieldRequest(
|
||||
pvStruct,request.substr(offsetBegin+1,
|
||||
offsetEnd-offsetBegin-1)))
|
||||
{
|
||||
return nullStructure;
|
||||
}
|
||||
pvStructure->appendPVField("putField", pvStruct);
|
||||
}
|
||||
if (offsetGetField != String::npos) {
|
||||
size_t offsetBegin = request.find('(', offsetGetField);
|
||||
size_t offsetEnd = request.find(')', offsetBegin);
|
||||
if(offsetEnd == String::npos) {
|
||||
message = request.substr(offsetField)
|
||||
+ " getField( does not have matching )";
|
||||
return nullStructure;
|
||||
}
|
||||
PVStructurePtr pvStruct = pvDataCreate->createPVStructure(emptyPVStructure);
|
||||
if(!createFieldRequest(
|
||||
pvStruct,request.substr(offsetBegin+1,
|
||||
offsetEnd-offsetBegin-1)))
|
||||
{
|
||||
return nullStructure;
|
||||
}
|
||||
pvStructure->appendPVField("getField", pvStruct);
|
||||
}
|
||||
if (pvStructure.get()->getStructure()->getNumberFields()==0) {
|
||||
if(!createFieldRequest(pvStructure,request)) return nullStructure;
|
||||
}
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
CreateRequest::shared_pointer CreateRequest::create()
|
||||
{
|
||||
CreateRequest::shared_pointer createRequest(new CreateRequestImpl());
|
||||
return createRequest;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -3,4 +3,3 @@
|
||||
SRC_DIRS += $(PVACCESS_SRC)/factory
|
||||
|
||||
LIBSRCS += ChannelAccessFactory.cpp
|
||||
LIBSRCS += CreateRequestFactory.cpp
|
||||
|
||||
@@ -26,7 +26,7 @@ namespace pvAccess {
|
||||
const epics::pvData::int8 PVA_MAGIC = static_cast<epics::pvData::int8>(0xCA);
|
||||
|
||||
/** PVA protocol revision (implemented by this library). */
|
||||
const epics::pvData::int8 PVA_PROTOCOL_REVISION = 0;
|
||||
const epics::pvData::int8 PVA_PROTOCOL_REVISION = 1;
|
||||
|
||||
/** PVA version signature used to report this implementation version in header. */
|
||||
const epics::pvData::int8 PVA_VERSION = PVA_PROTOCOL_REVISION;
|
||||
|
||||
@@ -25,8 +25,8 @@
|
||||
// module version
|
||||
// TODO to be generated, etc.
|
||||
#define EPICS_PVA_MAJOR_VERSION 3
|
||||
#define EPICS_PVA_MINOR_VERSION 0
|
||||
#define EPICS_PVA_MAINTENANCE_VERSION 5
|
||||
#define EPICS_PVA_MINOR_VERSION 1
|
||||
#define EPICS_PVA_MAINTENANCE_VERSION 0
|
||||
#define EPICS_PVA_DEVELOPMENT_FLAG 1
|
||||
|
||||
namespace epics {
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace epics {
|
||||
void AbstractResponseHandler::handleResponse(osiSockAddr* responseFrom,
|
||||
Transport::shared_pointer const & /*transport*/, int8 version, int8 command,
|
||||
size_t payloadSize, ByteBuffer* payloadBuffer) {
|
||||
if(_debug) {
|
||||
if(_debugLevel >= 3) { // TODO make a constant of sth (0 - off, 1 - debug, 2 - more/trace, 3 - messages)
|
||||
char ipAddrStr[48];
|
||||
ipAddrToDottedIP(&responseFrom->ia, ipAddrStr, sizeof(ipAddrStr));
|
||||
|
||||
|
||||
@@ -15,45 +15,43 @@ namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
BeaconHandler::BeaconHandler(Context::shared_pointer const & context,
|
||||
std::string const & protocol,
|
||||
const osiSockAddr* responseFrom) :
|
||||
_context(Context::weak_pointer(context)),
|
||||
_protocol(protocol),
|
||||
_responseFrom(*responseFrom),
|
||||
_mutex(),
|
||||
_serverStartupTime(0)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
BeaconHandler::BeaconHandler(const osiSockAddr* responseFrom) :
|
||||
_responseFrom(*responseFrom),
|
||||
_mutex(),
|
||||
_serverStartupTime(0)
|
||||
_serverGUID(),
|
||||
_serverChangeCount(-1),
|
||||
_first(true)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
BeaconHandler::~BeaconHandler()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void BeaconHandler::beaconNotify(osiSockAddr* /*from*/, int8 remoteTransportRevision,
|
||||
TimeStamp* timestamp, TimeStamp* startupTime, int16 sequentalID,
|
||||
TimeStamp* timestamp, GUID const & guid, int16 sequentalID,
|
||||
int16 changeCount,
|
||||
PVFieldPtr /*data*/)
|
||||
{
|
||||
bool networkChanged = updateBeacon(remoteTransportRevision, timestamp, startupTime, sequentalID);
|
||||
bool networkChanged = updateBeacon(remoteTransportRevision, timestamp, guid, sequentalID, changeCount);
|
||||
if (networkChanged)
|
||||
changedTransport();
|
||||
}
|
||||
|
||||
bool BeaconHandler::updateBeacon(int8 /*remoteTransportRevision*/, TimeStamp* /*timestamp*/,
|
||||
TimeStamp* startupTime, int16 /*sequentalID*/)
|
||||
GUID const & guid, int16 /*sequentalID*/, int16 changeCount)
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
// first beacon notification check
|
||||
if (_serverStartupTime.getSecondsPastEpoch() == 0)
|
||||
{
|
||||
_serverStartupTime = *startupTime;
|
||||
Lock guard(_mutex);
|
||||
// first beacon notification check
|
||||
if (_first)
|
||||
{
|
||||
_first = false;
|
||||
_serverGUID = guid;
|
||||
_serverChangeCount = changeCount;
|
||||
|
||||
// new server up..
|
||||
_context.lock()->newServerDetected();
|
||||
@@ -61,25 +59,35 @@ bool BeaconHandler::updateBeacon(int8 /*remoteTransportRevision*/, TimeStamp* /*
|
||||
return false;
|
||||
}
|
||||
|
||||
bool networkChange = !(_serverStartupTime == *startupTime);
|
||||
bool networkChange = (memcmp(_serverGUID.value, guid.value, sizeof(guid.value)) != 0);
|
||||
if (networkChange)
|
||||
{
|
||||
// update startup time
|
||||
_serverStartupTime = *startupTime;
|
||||
// update startup time and change count
|
||||
_serverGUID = guid;
|
||||
_serverChangeCount = changeCount;
|
||||
|
||||
_context.lock()->newServerDetected();
|
||||
|
||||
return true;
|
||||
}
|
||||
else if (_serverChangeCount != changeCount)
|
||||
{
|
||||
// update change count
|
||||
_serverChangeCount = changeCount;
|
||||
|
||||
// TODO be more specific (possible optimizations)
|
||||
_context.lock()->newServerDetected();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void BeaconHandler::changedTransport()
|
||||
{
|
||||
// TODO why only TCP, actually TCP does not need this
|
||||
auto_ptr<TransportRegistry::transportVector_t> transports =
|
||||
_context.lock()->getTransportRegistry()->get("TCP", &_responseFrom);
|
||||
_context.lock()->getTransportRegistry()->get(_protocol, &_responseFrom);
|
||||
if (!transports.get())
|
||||
return;
|
||||
|
||||
|
||||
@@ -38,36 +38,37 @@ namespace pvAccess {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param transport transport to be used to send beacons.
|
||||
* @param context PVA context.
|
||||
*/
|
||||
BeaconHandler(Context::shared_pointer const & context, const osiSockAddr* responseFrom);
|
||||
/**
|
||||
* Test Constructor (for testing)
|
||||
* @param transport transport to be used to send beacons.
|
||||
*/
|
||||
BeaconHandler(const osiSockAddr* responseFrom);
|
||||
BeaconHandler(Context::shared_pointer const & context, std::string const & protocol,
|
||||
const osiSockAddr* responseFrom);
|
||||
|
||||
virtual ~BeaconHandler();
|
||||
|
||||
/**
|
||||
* Update beacon period and do analitical checks (server restared, routing problems, etc.)
|
||||
* @param from who is notifying.
|
||||
* @param remoteTransportRevision encoded (major, minor) revision.
|
||||
* @param timestamp time when beacon was received.
|
||||
* @param startupTime server (reported) startup time.
|
||||
* @param guid server GUID.
|
||||
* @param sequentalID sequential ID.
|
||||
* @param changeCount change count.
|
||||
* @param data server status data, can be <code>NULL</code>.
|
||||
*/
|
||||
void beaconNotify(osiSockAddr* from,
|
||||
epics::pvData::int8 remoteTransportRevision,
|
||||
epics::pvData::TimeStamp* timestamp,
|
||||
epics::pvData::TimeStamp* startupTime,
|
||||
GUID const &guid,
|
||||
epics::pvData::int16 sequentalID,
|
||||
epics::pvData::int16 changeCount,
|
||||
epics::pvData::PVFieldPtr data);
|
||||
private:
|
||||
/**
|
||||
* Context instance.
|
||||
*/
|
||||
Context::weak_pointer _context;
|
||||
/**
|
||||
* The procotol (transport), "tcp" for pvAccess TCP/IP.
|
||||
*/
|
||||
std::string _protocol;
|
||||
/**
|
||||
* Remote address.
|
||||
*/
|
||||
@@ -76,21 +77,33 @@ namespace pvAccess {
|
||||
* Mutex
|
||||
*/
|
||||
epics::pvData::Mutex _mutex;
|
||||
/**
|
||||
* Server GUID.
|
||||
*/
|
||||
GUID _serverGUID;
|
||||
/**
|
||||
* Server startup timestamp.
|
||||
*/
|
||||
epics::pvData::TimeStamp _serverStartupTime;
|
||||
epics::pvData::int16 _serverChangeCount;
|
||||
/**
|
||||
* First beacon flag.
|
||||
*/
|
||||
bool _first;
|
||||
|
||||
/**
|
||||
* Update beacon.
|
||||
* @param remoteTransportRevision encoded (major, minor) revision.
|
||||
* @param timestamp time when beacon was received.
|
||||
* @param guid server GUID.
|
||||
* @param sequentalID sequential ID.
|
||||
* @param changeCount change count.
|
||||
* @return network change (server restarted) detected.
|
||||
*/
|
||||
bool updateBeacon(epics::pvData::int8 remoteTransportRevision,
|
||||
epics::pvData::TimeStamp* timestamp,
|
||||
epics::pvData::TimeStamp* startupTime,
|
||||
epics::pvData::int16 sequentalID);
|
||||
GUID const &guid,
|
||||
epics::pvData::int16 sequentalID,
|
||||
epics::pvData::int16 changeCount);
|
||||
/**
|
||||
* Changed transport (server restarted) notify.
|
||||
*/
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace pvAccess {
|
||||
int retval = ::bind(_serverSocketChannel, &_bindAddress.sa, sizeof(sockaddr));
|
||||
if(retval<0) {
|
||||
epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
|
||||
LOG(logLevelDebug, "Socket bind error: %s", strBuffer);
|
||||
LOG(logLevelDebug, "Socket bind error: %s.", strBuffer);
|
||||
if(_bindAddress.ia.sin_port!=0) {
|
||||
// failed to bind to specified bind address,
|
||||
// try to get port dynamically, but only once
|
||||
@@ -163,24 +163,24 @@ namespace pvAccess {
|
||||
if(newClient!=INVALID_SOCKET) {
|
||||
// accept succeeded
|
||||
ipAddrToDottedIP(&address.ia, ipAddrStr, sizeof(ipAddrStr));
|
||||
LOG(logLevelDebug, "Accepted connection from PVA client: %s", ipAddrStr);
|
||||
LOG(logLevelDebug, "Accepted connection from PVA client: %s.", ipAddrStr);
|
||||
|
||||
// enable TCP_NODELAY (disable Nagle's algorithm)
|
||||
int optval = 1; // true
|
||||
int retval = ::setsockopt(newClient, IPPROTO_TCP, TCP_NODELAY, (char *)&optval, sizeof(int));
|
||||
if(retval<0) {
|
||||
epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
|
||||
LOG(logLevelDebug, "Error setting TCP_NODELAY: %s", strBuffer);
|
||||
LOG(logLevelDebug, "Error setting TCP_NODELAY: %s.", strBuffer);
|
||||
}
|
||||
|
||||
// enable TCP_KEEPALIVE
|
||||
retval = ::setsockopt(newClient, SOL_SOCKET, SO_KEEPALIVE, (char *)&optval, sizeof(int));
|
||||
if(retval<0) {
|
||||
epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
|
||||
LOG(logLevelDebug, "Error setting SO_KEEPALIVE: %s", strBuffer);
|
||||
LOG(logLevelDebug, "Error setting SO_KEEPALIVE: %s.", strBuffer);
|
||||
}
|
||||
|
||||
// TODO tune buffer sizes?!
|
||||
// do NOT tune socket buffer sizes, this will disable auto-tunning
|
||||
|
||||
// get TCP send buffer size
|
||||
osiSocklen_t intLen = sizeof(int);
|
||||
@@ -188,7 +188,7 @@ namespace pvAccess {
|
||||
retval = getsockopt(newClient, SOL_SOCKET, SO_SNDBUF, (char *)&_socketSendBufferSize, &intLen);
|
||||
if(retval<0) {
|
||||
epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
|
||||
LOG(logLevelDebug, "Error getting SO_SNDBUF: %s", strBuffer);
|
||||
LOG(logLevelDebug, "Error getting SO_SNDBUF: %s.", strBuffer);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -213,7 +213,7 @@ namespace pvAccess {
|
||||
return;
|
||||
}
|
||||
|
||||
LOG(logLevelDebug, "Serving to PVA client: %s", ipAddrStr);
|
||||
LOG(logLevelDebug, "Serving to PVA client: %s.", ipAddrStr);
|
||||
|
||||
}// accept succeeded
|
||||
else
|
||||
@@ -223,7 +223,8 @@ namespace pvAccess {
|
||||
|
||||
bool BlockingTCPAcceptor::validateConnection(Transport::shared_pointer const & transport, const char* address) {
|
||||
try {
|
||||
transport->verify(0);
|
||||
// TODO constant
|
||||
transport->verify(5000);
|
||||
return true;
|
||||
} catch(...) {
|
||||
LOG(logLevelDebug, "Validation of %s failed.", address);
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace epics {
|
||||
if (socket == INVALID_SOCKET)
|
||||
{
|
||||
epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
|
||||
LOG(logLevelWarn, "Socket create error: %s", strBuffer);
|
||||
LOG(logLevelWarn, "Socket create error: %s.", strBuffer);
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
else {
|
||||
@@ -60,7 +60,7 @@ namespace epics {
|
||||
else {
|
||||
epicsSocketDestroy (socket);
|
||||
epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
|
||||
LOG(logLevelDebug, "Socket connect error: %s", strBuffer);
|
||||
LOG(logLevelDebug, "Socket connect error: %s.", strBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,7 +82,7 @@ namespace epics {
|
||||
Transport::shared_pointer transport = context->getTransportRegistry()->get("TCP", &address, priority);
|
||||
if(transport.get()) {
|
||||
LOG(logLevelDebug,
|
||||
"Reusing existing connection to PVA server: %s",
|
||||
"Reusing existing connection to PVA server: %s.",
|
||||
ipAddrStr);
|
||||
if (transport->acquire(client))
|
||||
return transport;
|
||||
@@ -95,13 +95,13 @@ namespace epics {
|
||||
transport = context->getTransportRegistry()->get("TCP", &address, priority);
|
||||
if(transport.get()) {
|
||||
LOG(logLevelDebug,
|
||||
"Reusing existing connection to PVA server: %s",
|
||||
"Reusing existing connection to PVA server: %s.",
|
||||
ipAddrStr);
|
||||
if (transport->acquire(client))
|
||||
return transport;
|
||||
}
|
||||
|
||||
LOG(logLevelDebug, "Connecting to PVA server: %s", ipAddrStr);
|
||||
LOG(logLevelDebug, "Connecting to PVA server: %s.", ipAddrStr);
|
||||
|
||||
socket = tryConnect(address, 3);
|
||||
|
||||
@@ -123,7 +123,7 @@ namespace epics {
|
||||
if(retval<0) {
|
||||
char errStr[64];
|
||||
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
|
||||
LOG(logLevelWarn, "Error setting TCP_NODELAY: %s", errStr);
|
||||
LOG(logLevelWarn, "Error setting TCP_NODELAY: %s.", errStr);
|
||||
}
|
||||
|
||||
// enable TCP_KEEPALIVE
|
||||
@@ -133,7 +133,7 @@ namespace epics {
|
||||
{
|
||||
char errStr[64];
|
||||
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
|
||||
LOG(logLevelWarn, "Error setting SO_KEEPALIVE: %s", errStr);
|
||||
LOG(logLevelWarn, "Error setting SO_KEEPALIVE: %s.", errStr);
|
||||
}
|
||||
|
||||
// TODO tune buffer sizes?! Win32 defaults are 8k, which is OK
|
||||
@@ -147,7 +147,7 @@ namespace epics {
|
||||
if(retval<0) {
|
||||
char strBuffer[64];
|
||||
epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
|
||||
LOG(logLevelDebug, "Error getting SO_SNDBUF: %s", strBuffer);
|
||||
LOG(logLevelDebug, "Error getting SO_SNDBUF: %s.", strBuffer);
|
||||
}
|
||||
|
||||
transport = detail::BlockingClientTCPTransportCodec::create(
|
||||
@@ -168,7 +168,7 @@ namespace epics {
|
||||
|
||||
// TODO send security token
|
||||
|
||||
LOG(logLevelDebug, "Connected to PVA server: %s", ipAddrStr);
|
||||
LOG(logLevelDebug, "Connected to PVA server: %s.", ipAddrStr);
|
||||
|
||||
_namedLocker.releaseSynchronizationObject(&address);
|
||||
return transport;
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
enum InetAddressType { inetAddressType_all, inetAddressType_unicast, inetAddressType_broadcast_multicast };
|
||||
|
||||
class BlockingUDPTransport : public epics::pvData::NoDefaultMethods,
|
||||
public Transport,
|
||||
public TransportSendControl,
|
||||
@@ -65,12 +67,11 @@ namespace epics {
|
||||
}
|
||||
|
||||
virtual const osiSockAddr* getRemoteAddress() const {
|
||||
// always connected
|
||||
return &_bindAddress;
|
||||
return &_remoteAddress;
|
||||
}
|
||||
|
||||
virtual epics::pvData::String getType() const {
|
||||
return epics::pvData::String("UDP");
|
||||
return epics::pvData::String("udp");
|
||||
}
|
||||
|
||||
virtual std::size_t getReceiveBufferSize() const {
|
||||
@@ -114,7 +115,7 @@ namespace epics {
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual void verified() {
|
||||
virtual void verified(epics::pvData::Status const & /*status*/) {
|
||||
// noop
|
||||
}
|
||||
|
||||
@@ -135,8 +136,9 @@ namespace epics {
|
||||
|
||||
virtual void close();
|
||||
|
||||
virtual void ensureData(std::size_t /*size*/) {
|
||||
// noop
|
||||
virtual void ensureData(std::size_t size) {
|
||||
if (_receiveBuffer->getRemaining() < size)
|
||||
throw std::underflow_error("no more data in UDP packet");
|
||||
}
|
||||
|
||||
virtual void alignData(std::size_t alignment) {
|
||||
@@ -227,7 +229,7 @@ namespace epics {
|
||||
|
||||
bool send(epics::pvData::ByteBuffer* buffer, const osiSockAddr& address);
|
||||
|
||||
bool send(epics::pvData::ByteBuffer* buffer);
|
||||
bool send(epics::pvData::ByteBuffer* buffer, InetAddressType target = inetAddressType_all);
|
||||
|
||||
/**
|
||||
* Get list of send addresses.
|
||||
@@ -245,15 +247,31 @@ namespace epics {
|
||||
return &_bindAddress;
|
||||
}
|
||||
|
||||
bool isBroadcastAddress(const osiSockAddr* address, InetAddrVector *broadcastAddresses)
|
||||
{
|
||||
if (broadcastAddresses)
|
||||
for (size_t i = 0; i < broadcastAddresses->size(); i++)
|
||||
if ((*broadcastAddresses)[i].ia.sin_addr.s_addr == address->ia.sin_addr.s_addr)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set list of send addresses.
|
||||
* @param addresses list of send addresses, non-<code>null</code>.
|
||||
*/
|
||||
void setBroadcastAddresses(InetAddrVector* addresses) {
|
||||
void setSendAddresses(InetAddrVector* addresses) {
|
||||
if (addresses)
|
||||
{
|
||||
if (!_sendAddresses) _sendAddresses = new InetAddrVector;
|
||||
*_sendAddresses = *addresses;
|
||||
|
||||
std::auto_ptr<InetAddrVector> broadcastAddresses(getBroadcastAddresses(_channel, 0));
|
||||
_isSendAddressUnicast.resize(_sendAddresses->size());
|
||||
for (std::size_t i = 0; i < _sendAddresses->size(); i++)
|
||||
_isSendAddressUnicast[i] =
|
||||
!isBroadcastAddress(&(*_sendAddresses)[i], broadcastAddresses.get()) &&
|
||||
!isMulticastAddress(&(*_sendAddresses)[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -290,11 +308,18 @@ namespace epics {
|
||||
*/
|
||||
osiSockAddr _bindAddress;
|
||||
|
||||
/**
|
||||
* Remote address.
|
||||
*/
|
||||
osiSockAddr _remoteAddress;
|
||||
|
||||
/**
|
||||
* Send addresses.
|
||||
*/
|
||||
InetAddrVector* _sendAddresses;
|
||||
|
||||
std::vector<bool> _isSendAddressUnicast;
|
||||
|
||||
/**
|
||||
* Ignore addresses.
|
||||
*/
|
||||
|
||||
@@ -45,7 +45,13 @@ namespace epics {
|
||||
}
|
||||
|
||||
/*
|
||||
IPv4 multicast addresses are defined by the leading address bits of 1110, originating from the classful network design of the early Internet when this group of addresses was designated as Class D. The Classless Inter-Domain Routing (CIDR) prefix of this group is 224.0.0.0/4. The group includes the addresses from 224.0.0.0 to 239.255.255.255. Address assignments from within this range are specified in RFC 5771, an Internet Engineering Task Force (IETF) Best Current Practice document (BCP 51).*/
|
||||
IPv4 multicast addresses are defined by the leading address bits of 1110,
|
||||
originating from the classful network design of the early Internet when this
|
||||
group of addresses was designated as Class D. The Classless Inter-Domain Routing (CIDR)
|
||||
prefix of this group is 224.0.0.0/4.
|
||||
The group includes the addresses from 224.0.0.0 to 239.255.255.255.
|
||||
Address assignments from within this range are specified in RFC 5771,
|
||||
an Internet Engineering Task Force (IETF) Best Current Practice document (BCP 51).*/
|
||||
|
||||
|
||||
// set SO_REUSEADDR or SO_REUSEPORT, OS dependant
|
||||
|
||||
@@ -53,22 +53,17 @@ inline int sendto(int s, const char *buf, size_t len, int flags, const struct so
|
||||
{
|
||||
PVACCESS_REFCOUNT_MONITOR_CONSTRUCT(blockingUDPTransport);
|
||||
|
||||
// set receive timeout so that we do not have problems at shutdown (recvfrom would block)
|
||||
struct timeval timeout;
|
||||
memset(&timeout, 0, sizeof(struct timeval));
|
||||
timeout.tv_sec = 1;
|
||||
timeout.tv_usec = 0;
|
||||
osiSocklen_t sockLen = sizeof(sockaddr);
|
||||
// read the actual socket info
|
||||
int retval = ::getsockname(_channel, &_remoteAddress.sa, &sockLen);
|
||||
if(retval<0) {
|
||||
// error obtaining remote address, fallback to bindAddress
|
||||
_remoteAddress = _bindAddress;
|
||||
|
||||
if (unlikely(::setsockopt (_channel, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout)) < 0))
|
||||
{
|
||||
char errStr[64];
|
||||
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
|
||||
LOG(logLevelError,
|
||||
"Failed to set SO_RCVTIMEO for UDP socket %s: %s.",
|
||||
inetAddressToString(_bindAddress).c_str(), errStr);
|
||||
char strBuffer[64];
|
||||
epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
|
||||
LOG(logLevelDebug, "getsockname error: %s", strBuffer);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
BlockingUDPTransport::~BlockingUDPTransport() {
|
||||
@@ -84,9 +79,13 @@ inline int sendto(int s, const char *buf, size_t len, int flags, const struct so
|
||||
|
||||
void BlockingUDPTransport::start() {
|
||||
|
||||
String threadName = "UDP-receive "+inetAddressToString(_bindAddress);
|
||||
LOG(logLevelDebug, "Starting thread: %s",threadName.c_str());
|
||||
|
||||
String threadName = "UDP-receive " + inetAddressToString(_bindAddress);
|
||||
|
||||
if (IS_LOGGABLE(logLevelTrace))
|
||||
{
|
||||
LOG(logLevelTrace, "Starting thread: %s.", threadName.c_str());
|
||||
}
|
||||
|
||||
_threadId = epicsThreadCreate(threadName.c_str(),
|
||||
epicsThreadPriorityMedium,
|
||||
epicsThreadGetStackSize(epicsThreadStackSmall),
|
||||
@@ -102,39 +101,44 @@ inline int sendto(int s, const char *buf, size_t len, int flags, const struct so
|
||||
Lock guard(_mutex);
|
||||
if(_closed.get()) return;
|
||||
_closed.set();
|
||||
|
||||
}
|
||||
|
||||
if (IS_LOGGABLE(logLevelDebug))
|
||||
{
|
||||
LOG(logLevelDebug,
|
||||
"UDP socket %s closed.",
|
||||
inetAddressToString(_bindAddress).c_str());
|
||||
|
||||
epicsSocketSystemCallInterruptMechanismQueryInfo info =
|
||||
epicsSocketSystemCallInterruptMechanismQuery ();
|
||||
switch ( info ) {
|
||||
case esscimqi_socketCloseRequired:
|
||||
epicsSocketDestroy ( _channel );
|
||||
break;
|
||||
case esscimqi_socketBothShutdownRequired:
|
||||
{
|
||||
int status = ::shutdown ( _channel, SHUT_RDWR );
|
||||
if ( status ) {
|
||||
char sockErrBuf[64];
|
||||
epicsSocketConvertErrnoToString (
|
||||
sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
LOG(logLevelDebug,
|
||||
"UDP socket %s failed to shutdown: %s.",
|
||||
inetAddressToString(_bindAddress).c_str(), sockErrBuf);
|
||||
}
|
||||
epicsSocketDestroy ( _channel );
|
||||
}
|
||||
break;
|
||||
case esscimqi_socketSigAlarmRequired:
|
||||
// TODO (not supported anymore anyway)
|
||||
default:
|
||||
epicsSocketDestroy(_channel);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO send yourself a packet
|
||||
epicsSocketSystemCallInterruptMechanismQueryInfo info =
|
||||
epicsSocketSystemCallInterruptMechanismQuery ();
|
||||
switch ( info )
|
||||
{
|
||||
case esscimqi_socketCloseRequired:
|
||||
epicsSocketDestroy ( _channel );
|
||||
break;
|
||||
case esscimqi_socketBothShutdownRequired:
|
||||
{
|
||||
/*int status =*/ ::shutdown ( _channel, SHUT_RDWR );
|
||||
/*
|
||||
if ( status ) {
|
||||
char sockErrBuf[64];
|
||||
epicsSocketConvertErrnoToString (
|
||||
sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
LOG(logLevelDebug,
|
||||
"UDP socket %s failed to shutdown: %s.",
|
||||
inetAddressToString(_bindAddress).c_str(), sockErrBuf);
|
||||
}
|
||||
*/
|
||||
epicsSocketDestroy ( _channel );
|
||||
}
|
||||
break;
|
||||
case esscimqi_socketSigAlarmRequired:
|
||||
// not supported anymore anyway
|
||||
default:
|
||||
epicsSocketDestroy(_channel);
|
||||
}
|
||||
|
||||
|
||||
// wait for send thread to exit cleanly
|
||||
if (waitForThreadToComplete)
|
||||
@@ -255,7 +259,7 @@ inline int sendto(int s, const char *buf, size_t len, int flags, const struct so
|
||||
{
|
||||
char errStr[64];
|
||||
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
|
||||
LOG(logLevelError, "Socket recvfrom error: %s", errStr);
|
||||
LOG(logLevelError, "Socket recvfrom error: %s.", errStr);
|
||||
}
|
||||
|
||||
close(false);
|
||||
@@ -268,12 +272,11 @@ inline int sendto(int s, const char *buf, size_t len, int flags, const struct so
|
||||
close(false);
|
||||
}
|
||||
|
||||
String threadName = "UDP-receive "+inetAddressToString(_bindAddress);
|
||||
/*
|
||||
char threadName[40];
|
||||
epicsThreadGetName(_threadId, threadName, 40);
|
||||
*/
|
||||
LOG(logLevelDebug, "Thread '%s' exiting", threadName.c_str());
|
||||
if (IS_LOGGABLE(logLevelTrace))
|
||||
{
|
||||
String threadName = "UDP-receive "+inetAddressToString(_bindAddress);
|
||||
LOG(logLevelTrace, "Thread '%s' exiting.", threadName.c_str());
|
||||
}
|
||||
|
||||
_shutdownEvent.signal();
|
||||
}
|
||||
@@ -337,20 +340,30 @@ inline int sendto(int s, const char *buf, size_t len, int flags, const struct so
|
||||
{
|
||||
char errStr[64];
|
||||
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
|
||||
LOG(logLevelDebug, "Socket sendto error: %s", errStr);
|
||||
LOG(logLevelDebug, "Socket sendto error: %s.", errStr);
|
||||
return false;
|
||||
}
|
||||
|
||||
// all sent
|
||||
buffer->setPosition(buffer->getLimit());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BlockingUDPTransport::send(ByteBuffer* buffer) {
|
||||
bool BlockingUDPTransport::send(ByteBuffer* buffer, InetAddressType target) {
|
||||
if(!_sendAddresses) return false;
|
||||
|
||||
buffer->flip();
|
||||
|
||||
bool allOK = true;
|
||||
for(size_t i = 0; i<_sendAddresses->size(); i++) {
|
||||
|
||||
// filter
|
||||
if (target != inetAddressType_all)
|
||||
if ((target == inetAddressType_unicast && !_isSendAddressUnicast[i]) ||
|
||||
(target == inetAddressType_broadcast_multicast && _isSendAddressUnicast[i]))
|
||||
continue;
|
||||
|
||||
int retval = sendto(_channel, buffer->getArray(),
|
||||
buffer->getLimit(), 0, &((*_sendAddresses)[i].sa),
|
||||
sizeof(sockaddr));
|
||||
@@ -358,11 +371,14 @@ inline int sendto(int s, const char *buf, size_t len, int flags, const struct so
|
||||
{
|
||||
char errStr[64];
|
||||
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
|
||||
LOG(logLevelDebug, "Socket sendto error: %s", errStr);
|
||||
LOG(logLevelDebug, "Socket sendto error: %s.", errStr);
|
||||
allOK = false;
|
||||
}
|
||||
}
|
||||
|
||||
// all sent
|
||||
buffer->setPosition(buffer->getLimit());
|
||||
|
||||
return allOK;
|
||||
}
|
||||
|
||||
@@ -379,7 +395,7 @@ inline int sendto(int s, const char *buf, size_t len, int flags, const struct so
|
||||
{
|
||||
char errStr[64];
|
||||
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
|
||||
LOG(logLevelError, "Socket getsockopt SO_RCVBUF error: %s", errStr);
|
||||
LOG(logLevelError, "Socket getsockopt SO_RCVBUF error: %s.", errStr);
|
||||
}
|
||||
|
||||
return (size_t)sockBufSize;
|
||||
|
||||
@@ -133,7 +133,7 @@ namespace epics {
|
||||
if (magicCode != PVA_MAGIC)
|
||||
{
|
||||
LOG(logLevelError,
|
||||
"Invalid header received from the client at %s:%d: %s,"
|
||||
"Invalid header received from the client at %s:%d: %s.,"
|
||||
" disconnecting...",
|
||||
__FILE__, __LINE__, inetAddressToString(*getLastReadBufferSocketAddress()).c_str());
|
||||
invalidDataStreamHandler();
|
||||
@@ -155,7 +155,13 @@ namespace epics {
|
||||
if (!readToBuffer(PVA_MESSAGE_HEADER_SIZE, false)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
hexDump("Header", (const int8*)_socketBuffer->getArray(),
|
||||
_socketBuffer->getPosition(), PVA_MESSAGE_HEADER_SIZE);
|
||||
|
||||
*/
|
||||
|
||||
// read header fields
|
||||
processHeader();
|
||||
bool isControl = ((_flags & 0x01) == 0x01);
|
||||
@@ -174,7 +180,7 @@ namespace epics {
|
||||
continue;
|
||||
|
||||
LOG(logLevelWarn,
|
||||
"Not-a-frst segmented message received in normal mode"
|
||||
"Not-a-first segmented message received in normal mode"
|
||||
" from the client at %s:%d: %s, disconnecting...",
|
||||
__FILE__, __LINE__, inetAddressToString(*getLastReadBufferSocketAddress()).c_str());
|
||||
invalidDataStreamHandler();
|
||||
@@ -402,7 +408,7 @@ namespace epics {
|
||||
msg << "requested for buffer size " << size
|
||||
<< ", but maximum " << MAX_ENSURE_DATA_SIZE << " is allowed.";
|
||||
LOG(logLevelWarn,
|
||||
"%s at %s:%d,", msg.str().c_str(), __FILE__, __LINE__);
|
||||
"%s at %s:%d.,", msg.str().c_str(), __FILE__, __LINE__);
|
||||
std::string s = msg.str();
|
||||
throw std::invalid_argument(s);
|
||||
}
|
||||
@@ -688,7 +694,7 @@ namespace epics {
|
||||
size << ", but only " << _maxSendPayloadSize << " available.";
|
||||
std::string s = msg.str();
|
||||
LOG(logLevelWarn,
|
||||
"%s at %s:%d,", msg.str().c_str(), __FILE__, __LINE__);
|
||||
"%s at %s:%d.,", msg.str().c_str(), __FILE__, __LINE__);
|
||||
throw std::invalid_argument(s);
|
||||
}
|
||||
|
||||
@@ -892,7 +898,7 @@ namespace epics {
|
||||
std::ostringstream msg;
|
||||
msg << "an exception caught while processing a send message: "
|
||||
<< e.what();
|
||||
LOG(logLevelDebug, "%s at %s:%d",
|
||||
LOG(logLevelWarn, "%s at %s:%d.",
|
||||
msg.str().c_str(), __FILE__, __LINE__);
|
||||
|
||||
try {
|
||||
@@ -1165,15 +1171,13 @@ namespace epics {
|
||||
{
|
||||
try {
|
||||
bac->processRead();
|
||||
} catch (connection_closed_exception &cce) {
|
||||
// noop
|
||||
} catch (std::exception &e) {
|
||||
LOG(logLevelWarn,
|
||||
"an exception caught while in sendThread at %s:%d: %s",
|
||||
__FILE__, __LINE__, e.what());
|
||||
} catch (...) {
|
||||
LOG(logLevelError,
|
||||
"unknown exception caught while in sendThread at %s:%d",
|
||||
LOG(logLevelWarn,
|
||||
"unknown exception caught while in sendThread at %s:%d.",
|
||||
__FILE__, __LINE__);
|
||||
}
|
||||
}
|
||||
@@ -1195,14 +1199,19 @@ namespace epics {
|
||||
try {
|
||||
bac->processWrite();
|
||||
} catch (connection_closed_exception &cce) {
|
||||
// noop
|
||||
// noop
|
||||
/*
|
||||
LOG(logLevelDebug,
|
||||
"connection closed by remote host while in sendThread at %s:%d: %s",
|
||||
__FILE__, __LINE__, e.what());
|
||||
*/
|
||||
} catch (std::exception &e) {
|
||||
LOG(logLevelWarn,
|
||||
"an exception caught while in sendThread at %s:%d: %s",
|
||||
__FILE__, __LINE__, e.what());
|
||||
} catch (...) {
|
||||
LOG(logLevelError,
|
||||
"unknown exception caught while in sendThread at %s:%d",
|
||||
LOG(logLevelWarn,
|
||||
"unknown exception caught while in sendThread at %s:%d.",
|
||||
__FILE__, __LINE__);
|
||||
}
|
||||
}
|
||||
@@ -1250,37 +1259,47 @@ namespace epics {
|
||||
char errStr[64];
|
||||
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
|
||||
LOG(logLevelError,
|
||||
"Error fetching socket remote address: %s",
|
||||
"Error fetching socket remote address: %s.",
|
||||
errStr);
|
||||
}
|
||||
|
||||
// set receive timeout so that we do not have problems at
|
||||
//shutdown (recvfrom would block)
|
||||
struct timeval timeout;
|
||||
memset(&timeout, 0, sizeof(struct timeval));
|
||||
timeout.tv_sec = 1;
|
||||
timeout.tv_usec = 0;
|
||||
|
||||
// TODO remove this and implement use epicsSocketSystemCallInterruptMechanismQuery
|
||||
if (unlikely(::setsockopt (_channel, SOL_SOCKET, SO_RCVTIMEO,
|
||||
(char*)&timeout, sizeof(timeout)) < 0))
|
||||
{
|
||||
char errStr[64];
|
||||
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
|
||||
LOG(logLevelError,
|
||||
"Failed to set SO_RCVTIMEO for TDP socket %s: %s.",
|
||||
inetAddressToString(_socketAddress).c_str(), errStr);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// must be called only once, when there will be no operation on socket (e.g. just before tx/rx thread exists)
|
||||
void BlockingSocketAbstractCodec::internalDestroy() {
|
||||
|
||||
if(_channel != INVALID_SOCKET) {
|
||||
epicsSocketDestroy(_channel);
|
||||
_channel = INVALID_SOCKET;
|
||||
}
|
||||
if(_channel != INVALID_SOCKET) {
|
||||
|
||||
epicsSocketSystemCallInterruptMechanismQueryInfo info =
|
||||
epicsSocketSystemCallInterruptMechanismQuery ();
|
||||
switch ( info )
|
||||
{
|
||||
case esscimqi_socketCloseRequired:
|
||||
epicsSocketDestroy ( _channel );
|
||||
break;
|
||||
case esscimqi_socketBothShutdownRequired:
|
||||
{
|
||||
/*int status =*/ ::shutdown ( _channel, SHUT_RDWR );
|
||||
/*
|
||||
if ( status ) {
|
||||
char sockErrBuf[64];
|
||||
epicsSocketConvertErrnoToString (
|
||||
sockErrBuf, sizeof ( sockErrBuf ) );
|
||||
LOG(logLevelDebug,
|
||||
"TCP socket to %s failed to shutdown: %s.",
|
||||
inetAddressToString(_socketAddress).c_str(), sockErrBuf);
|
||||
}
|
||||
*/
|
||||
epicsSocketDestroy ( _channel );
|
||||
}
|
||||
break;
|
||||
case esscimqi_socketSigAlarmRequired:
|
||||
// not supported anymore anyway
|
||||
default:
|
||||
epicsSocketDestroy(_channel);
|
||||
}
|
||||
|
||||
_channel = INVALID_SOCKET;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1393,6 +1412,38 @@ namespace epics {
|
||||
}
|
||||
|
||||
|
||||
void BlockingTCPTransportCodec::internalClose(bool force) {
|
||||
BlockingSocketAbstractCodec::internalClose(force);
|
||||
if (IS_LOGGABLE(logLevelDebug))
|
||||
{
|
||||
LOG(logLevelDebug,
|
||||
"TCP socket to %s closed.",
|
||||
inetAddressToString(_socketAddress).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool BlockingTCPTransportCodec::verify(epics::pvData::int32 timeoutMs) {
|
||||
return _verifiedEvent.wait(timeoutMs/1000.0);
|
||||
}
|
||||
|
||||
void BlockingTCPTransportCodec::verified(epics::pvData::Status const & status) {
|
||||
epics::pvData::Lock lock(_verifiedMutex);
|
||||
|
||||
if (IS_LOGGABLE(logLevelDebug) && !status.isOK())
|
||||
{
|
||||
char ipAddrStr[48];
|
||||
ipAddrToDottedIP(&_socketAddress.ia, ipAddrStr, sizeof(ipAddrStr));
|
||||
LOG(logLevelDebug, "Failed to verify connection to %s: %s.", ipAddrStr, status.getMessage().c_str());
|
||||
// TODO stack dump
|
||||
}
|
||||
|
||||
_verified = status.isSuccess();
|
||||
_verifiedEvent.signal();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1407,7 +1458,7 @@ namespace epics {
|
||||
int32_t receiveBufferSize) :
|
||||
BlockingTCPTransportCodec(context, channel, responseHandler,
|
||||
sendBufferSize, receiveBufferSize, PVA_DEFAULT_PRIORITY),
|
||||
_lastChannelSID(0)
|
||||
_lastChannelSID(0), _verifyOrVerified(false)
|
||||
{
|
||||
|
||||
// NOTE: priority not yet known, default priority is used to
|
||||
@@ -1473,33 +1524,59 @@ namespace epics {
|
||||
void BlockingServerTCPTransportCodec::send(ByteBuffer* buffer,
|
||||
TransportSendControl* control) {
|
||||
|
||||
//
|
||||
// set byte order control message
|
||||
//
|
||||
if (!_verifyOrVerified)
|
||||
{
|
||||
_verifyOrVerified = true;
|
||||
|
||||
ensureBuffer(PVA_MESSAGE_HEADER_SIZE);
|
||||
buffer->putByte(PVA_MAGIC);
|
||||
buffer->putByte(PVA_VERSION);
|
||||
buffer->putByte(
|
||||
0x01 | ((EPICS_BYTE_ORDER == EPICS_ENDIAN_BIG)
|
||||
? 0x80 : 0x00)); // control + big endian
|
||||
buffer->putByte(2); // set byte order
|
||||
buffer->putInt(0);
|
||||
//
|
||||
// set byte order control message
|
||||
//
|
||||
|
||||
ensureBuffer(PVA_MESSAGE_HEADER_SIZE);
|
||||
buffer->putByte(PVA_MAGIC);
|
||||
buffer->putByte(PVA_VERSION);
|
||||
buffer->putByte(
|
||||
0x01 | ((EPICS_BYTE_ORDER == EPICS_ENDIAN_BIG)
|
||||
? 0x80 : 0x00)); // control + big endian
|
||||
buffer->putByte(2); // set byte order
|
||||
buffer->putInt(0);
|
||||
|
||||
|
||||
//
|
||||
// send verification message
|
||||
//
|
||||
control->startMessage(CMD_CONNECTION_VALIDATION, 2*sizeof(int32));
|
||||
//
|
||||
// send verification message
|
||||
//
|
||||
control->startMessage(CMD_CONNECTION_VALIDATION, 4+2);
|
||||
|
||||
// receive buffer size
|
||||
buffer->putInt(static_cast<int32>(getReceiveBufferSize()));
|
||||
// receive buffer size
|
||||
buffer->putInt(static_cast<int32>(getReceiveBufferSize()));
|
||||
|
||||
// socket receive buffer size
|
||||
buffer->putInt(static_cast<int32>(getSocketReceiveBufferSize()));
|
||||
// server introspection registy max size
|
||||
// TODO
|
||||
buffer->putShort(0x7FFF);
|
||||
|
||||
// send immediately
|
||||
control->flush(true);
|
||||
// list of authNZ plugin names
|
||||
// TODO
|
||||
buffer->putByte(0);
|
||||
|
||||
// send immediately
|
||||
control->flush(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
//
|
||||
// send verified message
|
||||
//
|
||||
control->startMessage(CMD_CONNECTION_VALIDATED, 0);
|
||||
|
||||
{
|
||||
Lock lock(_verificationStatusMutex);
|
||||
_verificationStatus.serialize(buffer, control);
|
||||
}
|
||||
|
||||
// send immediately
|
||||
control->flush(true);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void BlockingServerTCPTransportCodec::destroyAllChannels() {
|
||||
@@ -1549,8 +1626,7 @@ namespace epics {
|
||||
sendBufferSize, receiveBufferSize, priority),
|
||||
_connectionTimeout(beaconInterval*1000),
|
||||
_unresponsiveTransport(false),
|
||||
_verifyOrEcho(true),
|
||||
_verified(false)
|
||||
_verifyOrEcho(true)
|
||||
{
|
||||
// initialize owners list, send queue
|
||||
acquire(client);
|
||||
@@ -1694,7 +1770,7 @@ namespace epics {
|
||||
{
|
||||
char ipAddrStr[48];
|
||||
ipAddrToDottedIP(&_socketAddress.ia, ipAddrStr, sizeof(ipAddrStr));
|
||||
LOG(logLevelDebug, "Releasing transport to %s.", ipAddrStr);
|
||||
LOG(logLevelDebug, "Releasing TCP transport to %s.", ipAddrStr);
|
||||
}
|
||||
|
||||
_owners.erase(clientID);
|
||||
@@ -1711,16 +1787,6 @@ namespace epics {
|
||||
if(_unresponsiveTransport) responsiveTransport();
|
||||
}
|
||||
|
||||
bool BlockingClientTCPTransportCodec::verify(epics::pvData::int32 timeoutMs) {
|
||||
return _verifiedEvent.wait(timeoutMs/1000.0);
|
||||
}
|
||||
|
||||
void BlockingClientTCPTransportCodec::verified() {
|
||||
epics::pvData::Lock lock(_verifiedMutex);
|
||||
_verified = true;
|
||||
_verifiedEvent.signal();
|
||||
}
|
||||
|
||||
void BlockingClientTCPTransportCodec::responsiveTransport() {
|
||||
Lock lock(_mutex);
|
||||
if(_unresponsiveTransport) {
|
||||
@@ -1755,25 +1821,30 @@ namespace epics {
|
||||
void BlockingClientTCPTransportCodec::send(ByteBuffer* buffer,
|
||||
TransportSendControl* control) {
|
||||
if(_verifyOrEcho) {
|
||||
_verifyOrEcho = false;
|
||||
|
||||
/*
|
||||
* send verification response message
|
||||
*/
|
||||
|
||||
control->startMessage(CMD_CONNECTION_VALIDATION, 2*sizeof(int32)+sizeof(int16));
|
||||
control->startMessage(CMD_CONNECTION_VALIDATION, 4+2+2);
|
||||
|
||||
// receive buffer size
|
||||
buffer->putInt(static_cast<int32>(getReceiveBufferSize()));
|
||||
|
||||
// socket receive buffer size
|
||||
buffer->putInt(static_cast<int32>(getSocketReceiveBufferSize()));
|
||||
// max introspection registry size
|
||||
// TODO
|
||||
buffer->putShort(0x7FFF);
|
||||
|
||||
// connection priority
|
||||
// QoS (aka connection priority)
|
||||
buffer->putShort(getPriority());
|
||||
|
||||
// authNZ plugin name
|
||||
// TODO
|
||||
SerializeHelper::serializeString("", buffer, control);
|
||||
|
||||
// send immediately
|
||||
control->flush(true);
|
||||
|
||||
_verifyOrEcho = false;
|
||||
}
|
||||
else {
|
||||
control->startMessage(CMD_ECHO, 0);
|
||||
|
||||
@@ -418,7 +418,7 @@ namespace epics {
|
||||
public:
|
||||
|
||||
epics::pvData::String getType() const {
|
||||
return epics::pvData::String("TCP");
|
||||
return epics::pvData::String("tcp");
|
||||
}
|
||||
|
||||
|
||||
@@ -514,6 +514,10 @@ namespace epics {
|
||||
start();
|
||||
}
|
||||
|
||||
bool verify(epics::pvData::int32 timeoutMs);
|
||||
|
||||
void verified(epics::pvData::Status const & status);
|
||||
|
||||
protected:
|
||||
|
||||
BlockingTCPTransportCodec(
|
||||
@@ -527,10 +531,13 @@ namespace epics {
|
||||
BlockingSocketAbstractCodec(channel, sendBufferSize, receiveBufferSize),
|
||||
_context(context), _responseHandler(responseHandler),
|
||||
_remoteTransportReceiveBufferSize(MAX_TCP_RECV),
|
||||
_remoteTransportRevision(0), _priority(priority)
|
||||
_remoteTransportRevision(0), _priority(priority),
|
||||
_verified(false)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void internalClose(bool force);
|
||||
|
||||
Context::shared_pointer _context;
|
||||
|
||||
IntrospectionRegistry _incomingIR;
|
||||
@@ -542,6 +549,10 @@ namespace epics {
|
||||
size_t _remoteTransportReceiveBufferSize;
|
||||
epics::pvData::int8 _remoteTransportRevision;
|
||||
epics::pvData::int16 _priority;
|
||||
|
||||
bool _verified;
|
||||
epics::pvData::Mutex _verifiedMutex;
|
||||
epics::pvData::Event _verifiedEvent;
|
||||
};
|
||||
|
||||
|
||||
@@ -615,15 +626,24 @@ namespace epics {
|
||||
// noop
|
||||
}
|
||||
|
||||
bool verify(epics::pvData::int32 /*timeoutMs*/) {
|
||||
TransportSender::shared_pointer transportSender =
|
||||
std::tr1::dynamic_pointer_cast<TransportSender>(shared_from_this());
|
||||
bool verify(epics::pvData::int32 timeoutMs) {
|
||||
|
||||
TransportSender::shared_pointer transportSender =
|
||||
std::tr1::dynamic_pointer_cast<TransportSender>(shared_from_this());
|
||||
enqueueSendRequest(transportSender);
|
||||
verified();
|
||||
return true;
|
||||
|
||||
bool verifiedStatus = BlockingTCPTransportCodec::verify(timeoutMs);
|
||||
|
||||
enqueueSendRequest(transportSender);
|
||||
|
||||
return verifiedStatus;
|
||||
}
|
||||
|
||||
void verified() {
|
||||
void verified(epics::pvData::Status const & status) {
|
||||
_verificationStatusMutex.lock();
|
||||
_verificationStatus = status;
|
||||
_verificationStatusMutex.unlock();
|
||||
BlockingTCPTransportCodec::verified(status);
|
||||
}
|
||||
|
||||
void aliveNotification() {
|
||||
@@ -654,6 +674,11 @@ namespace epics {
|
||||
|
||||
epics::pvData::Mutex _channelsMutex;
|
||||
|
||||
epics::pvData::Status _verificationStatus;
|
||||
epics::pvData::Mutex _verificationStatusMutex;
|
||||
|
||||
bool _verifyOrVerified;
|
||||
|
||||
};
|
||||
|
||||
class epicsShareClass BlockingClientTCPTransportCodec :
|
||||
@@ -725,10 +750,6 @@ namespace epics {
|
||||
// noop
|
||||
}
|
||||
|
||||
bool verify(epics::pvData::int32 timeoutMs);
|
||||
|
||||
void verified();
|
||||
|
||||
void aliveNotification();
|
||||
|
||||
void send(epics::pvData::ByteBuffer* buffer,
|
||||
@@ -780,13 +801,7 @@ namespace epics {
|
||||
*/
|
||||
void responsiveTransport();
|
||||
|
||||
|
||||
epics::pvData::Mutex _mutex;
|
||||
|
||||
bool _verified;
|
||||
epics::pvData::Mutex _verifiedMutex;
|
||||
epics::pvData::Event _verifiedEvent;
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
@@ -41,6 +41,11 @@ namespace epics {
|
||||
#define PVACCESS_REFCOUNT_MONITOR_DESTRUCT(name)
|
||||
|
||||
class TransportRegistry;
|
||||
|
||||
/**
|
||||
* Globally unique ID.
|
||||
*/
|
||||
typedef struct { char value[12]; } GUID;
|
||||
|
||||
enum QoS {
|
||||
/**
|
||||
@@ -89,22 +94,23 @@ namespace epics {
|
||||
CMD_ECHO = 2,
|
||||
CMD_SEARCH = 3,
|
||||
CMD_SEARCH_RESPONSE = 4,
|
||||
CMD_INTROSPECTION_SEARCH = 5,
|
||||
CMD_INTROSPECTION_SEARCH_RESPONSE = 6,
|
||||
CMD_AUTHNZ = 5,
|
||||
CMD_ACL_CHANGE = 6,
|
||||
CMD_CREATE_CHANNEL = 7,
|
||||
CMD_DESTROY_CHANNEL = 8,
|
||||
CMD_RESERVED0 = 9,
|
||||
CMD_CONNECTION_VALIDATED = 9,
|
||||
CMD_GET = 10,
|
||||
CMD_PUT = 11,
|
||||
CMD_PUT_GET = 12,
|
||||
CMD_MONITOR = 13,
|
||||
CMD_ARRAY = 14,
|
||||
CMD_CANCEL_REQUEST = 15,
|
||||
CMD_DESTROY_REQUEST = 15,
|
||||
CMD_PROCESS = 16,
|
||||
CMD_GET_FIELD = 17,
|
||||
CMD_MESSAGE = 18,
|
||||
CMD_MULTIPLE_DATA = 19,
|
||||
CMD_RPC = 20
|
||||
CMD_RPC = 20,
|
||||
CMD_CANCEL_REQUEST = 21
|
||||
};
|
||||
|
||||
enum ControlCommands {
|
||||
@@ -257,8 +263,9 @@ namespace epics {
|
||||
|
||||
/**
|
||||
* Notify transport that it is has been verified.
|
||||
* @param status vefification status;
|
||||
*/
|
||||
virtual void verified() = 0;
|
||||
virtual void verified(epics::pvData::Status const & status) = 0;
|
||||
|
||||
/**
|
||||
* Waits (if needed) until transport is verified, i.e. verified() method is being called.
|
||||
@@ -351,7 +358,7 @@ namespace epics {
|
||||
*/
|
||||
AbstractResponseHandler(Context* context, epics::pvData::String description) :
|
||||
_description(description),
|
||||
_debug(context->getConfiguration()->getPropertyAsBoolean(PVACCESS_DEBUG, false)) {
|
||||
_debugLevel(context->getConfiguration()->getPropertyAsInteger(PVACCESS_DEBUG, 0)) {
|
||||
}
|
||||
|
||||
virtual ~AbstractResponseHandler() {}
|
||||
@@ -369,7 +376,7 @@ namespace epics {
|
||||
/**
|
||||
* Debug flag.
|
||||
*/
|
||||
bool _debug;
|
||||
epics::pvData::int32 _debugLevel;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -20,8 +20,9 @@ using namespace epics::pvData;
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
const int SimpleChannelSearchManagerImpl::DATA_COUNT_POSITION = PVA_MESSAGE_HEADER_SIZE + sizeof(int32)/sizeof(int8) + 1;
|
||||
const int SimpleChannelSearchManagerImpl::PAYLOAD_POSITION = sizeof(int16)/sizeof(int8) + 2;
|
||||
const int SimpleChannelSearchManagerImpl::DATA_COUNT_POSITION = PVA_MESSAGE_HEADER_SIZE + 4+1+3+16+2+1+4;
|
||||
const int SimpleChannelSearchManagerImpl::CAST_POSITION = PVA_MESSAGE_HEADER_SIZE + 4;
|
||||
const int SimpleChannelSearchManagerImpl::PAYLOAD_POSITION = 4;
|
||||
|
||||
// 225ms +/- 25ms random
|
||||
const double SimpleChannelSearchManagerImpl::ATOMIC_PERIOD = 0.225;
|
||||
@@ -46,6 +47,7 @@ SimpleChannelSearchManagerImpl::create(Context::shared_pointer const & context)
|
||||
|
||||
SimpleChannelSearchManagerImpl::SimpleChannelSearchManagerImpl(Context::shared_pointer const & context) :
|
||||
m_context(context),
|
||||
m_responseAddress(*context->getSearchTransport()->getRemoteAddress()),
|
||||
m_canceled(),
|
||||
m_sequenceNumber(0),
|
||||
m_sendBuffer(MAX_UDP_UNFRAGMENTED_SEND),
|
||||
@@ -56,6 +58,7 @@ SimpleChannelSearchManagerImpl::SimpleChannelSearchManagerImpl(Context::shared_p
|
||||
m_userValueMutex(),
|
||||
m_mutex()
|
||||
{
|
||||
|
||||
// initialize send buffer
|
||||
initializeSendBuffer();
|
||||
|
||||
@@ -177,15 +180,25 @@ void SimpleChannelSearchManagerImpl::initializeSendBuffer()
|
||||
m_sendBuffer.putByte(PVA_VERSION);
|
||||
m_sendBuffer.putByte((EPICS_BYTE_ORDER == EPICS_ENDIAN_BIG) ? 0x80 : 0x00); // data + 7-bit endianess
|
||||
m_sendBuffer.putByte((int8_t)3); // search
|
||||
m_sendBuffer.putInt(sizeof(int32_t)/sizeof(int8_t) + 1); // "zero" payload
|
||||
m_sendBuffer.putInt(4+1+3+16+2+1); // "zero" payload
|
||||
m_sendBuffer.putInt(m_sequenceNumber);
|
||||
|
||||
/*
|
||||
final boolean REQUIRE_REPLY = false;
|
||||
sendBuffer.put(REQUIRE_REPLY ? (byte)QoS.REPLY_REQUIRED.getMaskValue() : (byte)QoS.DEFAULT.getMaskValue());
|
||||
*/
|
||||
// multicast vs unicast mask
|
||||
m_sendBuffer.putByte((int8_t)0);
|
||||
|
||||
m_sendBuffer.putByte((int8_t)QOS_DEFAULT);
|
||||
// reserved part
|
||||
m_sendBuffer.putByte((int8_t)0);
|
||||
m_sendBuffer.putShort((int16_t)0);
|
||||
|
||||
// NOTE: is it possible (very likely) that address is any local address ::ffff:0.0.0.0
|
||||
encodeAsIPv6Address(&m_sendBuffer, &m_responseAddress);
|
||||
m_sendBuffer.putShort((int16_t)ntohs(m_responseAddress.ia.sin_port));
|
||||
|
||||
// TODO now only TCP is supported
|
||||
// note: this affects DATA_COUNT_POSITION
|
||||
m_sendBuffer.putByte((int8_t)1);
|
||||
// TODO "tcp" constant
|
||||
SerializeHelper::serializeString("tcp", &m_sendBuffer, &m_mockTransportSendControl);
|
||||
m_sendBuffer.putShort((int16_t)0); // count
|
||||
}
|
||||
|
||||
@@ -195,8 +208,14 @@ void SimpleChannelSearchManagerImpl::flushSendBuffer()
|
||||
|
||||
Transport::shared_pointer tt = m_context.lock()->getSearchTransport();
|
||||
BlockingUDPTransport::shared_pointer ut = std::tr1::static_pointer_cast<BlockingUDPTransport>(tt);
|
||||
ut->send(&m_sendBuffer); // TODO
|
||||
initializeSendBuffer();
|
||||
|
||||
m_sendBuffer.putByte(CAST_POSITION, (int8_t)0x80); // unicast, no reply required
|
||||
ut->send(&m_sendBuffer, inetAddressType_unicast);
|
||||
|
||||
m_sendBuffer.putByte(CAST_POSITION, (int8_t)0x00); // b/m-cast, no reply required
|
||||
ut->send(&m_sendBuffer, inetAddressType_broadcast_multicast);
|
||||
|
||||
initializeSendBuffer();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -133,6 +133,11 @@ class SimpleChannelSearchManagerImpl :
|
||||
*/
|
||||
Context::weak_pointer m_context;
|
||||
|
||||
/**
|
||||
* Response address.
|
||||
*/
|
||||
osiSockAddr m_responseAddress;
|
||||
|
||||
/**
|
||||
* Canceled flag.
|
||||
*/
|
||||
@@ -179,6 +184,7 @@ class SimpleChannelSearchManagerImpl :
|
||||
epics::pvData::Mutex m_mutex;
|
||||
|
||||
static const int DATA_COUNT_POSITION;
|
||||
static const int CAST_POSITION;
|
||||
static const int PAYLOAD_POSITION;
|
||||
|
||||
static const double ATOMIC_PERIOD;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -121,7 +121,7 @@ namespace epics {
|
||||
|
||||
virtual void newServerDetected() = 0;
|
||||
|
||||
virtual std::tr1::shared_ptr<BeaconHandler> getBeaconHandler(osiSockAddr* responseFrom) = 0;
|
||||
virtual std::tr1::shared_ptr<BeaconHandler> getBeaconHandler(std::string const & protocol, osiSockAddr* responseFrom) = 0;
|
||||
|
||||
virtual void configure(epics::pvData::PVStructure::shared_pointer configuration) = 0;
|
||||
virtual void flush() = 0;
|
||||
|
||||
@@ -73,7 +73,7 @@ class ChannelRPCRequesterImpl : public ChannelRPCRequester
|
||||
std::cerr << "[" << getRequesterName() << "] message(" << message << ", " << getMessageTypeName(messageType) << ")" << std::endl;
|
||||
}
|
||||
|
||||
virtual void channelRPCConnect(const epics::pvData::Status& status,ChannelRPC::shared_pointer const & channelRPC)
|
||||
virtual void channelRPCConnect(const epics::pvData::Status& status, ChannelRPC::shared_pointer const & channelRPC)
|
||||
{
|
||||
if (status.isSuccess())
|
||||
{
|
||||
@@ -97,7 +97,8 @@ class ChannelRPCRequesterImpl : public ChannelRPCRequester
|
||||
}
|
||||
}
|
||||
|
||||
virtual void requestDone(const epics::pvData::Status &status, epics::pvData::PVStructure::shared_pointer const &pvResponse)
|
||||
virtual void requestDone(const epics::pvData::Status &status, ChannelRPC::shared_pointer const & /*channelRPC*/,
|
||||
epics::pvData::PVStructure::shared_pointer const &pvResponse)
|
||||
{
|
||||
if (status.isSuccess())
|
||||
{
|
||||
@@ -213,7 +214,7 @@ private:
|
||||
void init()
|
||||
{
|
||||
using namespace std::tr1;
|
||||
m_provider = getChannelAccess()->getProvider("pva");
|
||||
m_provider = getChannelProviderRegistry()->getProvider("pva");
|
||||
|
||||
shared_ptr<ChannelRequesterImpl> channelRequesterImpl(new ChannelRequesterImpl());
|
||||
m_channelRequesterImpl = channelRequesterImpl;
|
||||
@@ -250,7 +251,8 @@ PVStructure::shared_pointer RPCClientImpl::request(PVStructure::shared_pointer p
|
||||
|
||||
if (rpcRequesterImpl->waitUntilConnected(timeOut))
|
||||
{
|
||||
channelRPC->request(pvRequest, true);
|
||||
channelRPC->lastRequest();
|
||||
channelRPC->request(pvRequest);
|
||||
allOK &= rpcRequesterImpl->waitUntilRPC(timeOut);
|
||||
response = rpcRequesterImpl->response;
|
||||
}
|
||||
|
||||
@@ -14,18 +14,25 @@ using namespace epics::pvData;
|
||||
namespace epics { namespace pvAccess {
|
||||
|
||||
|
||||
class ChannelRPCServiceImpl : public ChannelRPC
|
||||
class ChannelRPCServiceImpl :
|
||||
public ChannelRPC,
|
||||
public std::tr1::enable_shared_from_this<ChannelRPC>
|
||||
{
|
||||
private:
|
||||
Channel::shared_pointer m_channel;
|
||||
ChannelRPCRequester::shared_pointer m_channelRPCRequester;
|
||||
RPCService::shared_pointer m_rpcService;
|
||||
AtomicBoolean m_lastRequest;
|
||||
|
||||
public:
|
||||
ChannelRPCServiceImpl(
|
||||
Channel::shared_pointer const & channel,
|
||||
ChannelRPCRequester::shared_pointer const & channelRPCRequester,
|
||||
RPCService::shared_pointer const & rpcService) :
|
||||
m_channel(channel),
|
||||
m_channelRPCRequester(channelRPCRequester),
|
||||
m_rpcService(rpcService)
|
||||
m_rpcService(rpcService),
|
||||
m_lastRequest()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -34,7 +41,7 @@ class ChannelRPCServiceImpl : public ChannelRPC
|
||||
destroy();
|
||||
}
|
||||
|
||||
void processRequest(epics::pvData::PVStructure::shared_pointer const & pvArgument, bool lastRequest)
|
||||
void processRequest(epics::pvData::PVStructure::shared_pointer const & pvArgument)
|
||||
{
|
||||
epics::pvData::PVStructure::shared_pointer result;
|
||||
Status status = Status::Ok;
|
||||
@@ -66,16 +73,31 @@ class ChannelRPCServiceImpl : public ChannelRPC
|
||||
status = Status(Status::STATUSTYPE_FATAL, "RPCService.request(PVStructure) returned null.");
|
||||
}
|
||||
|
||||
m_channelRPCRequester->requestDone(status, result);
|
||||
m_channelRPCRequester->requestDone(status, shared_from_this(), result);
|
||||
|
||||
if (lastRequest)
|
||||
if (m_lastRequest.get())
|
||||
destroy();
|
||||
|
||||
}
|
||||
|
||||
virtual void request(epics::pvData::PVStructure::shared_pointer const & pvArgument, bool lastRequest)
|
||||
virtual void request(epics::pvData::PVStructure::shared_pointer const & pvArgument)
|
||||
{
|
||||
processRequest(pvArgument, lastRequest);
|
||||
processRequest(pvArgument);
|
||||
}
|
||||
|
||||
void lastRequest()
|
||||
{
|
||||
m_lastRequest.set();
|
||||
}
|
||||
|
||||
virtual Channel::shared_pointer getChannel()
|
||||
{
|
||||
return m_channel;
|
||||
}
|
||||
|
||||
virtual void cancel()
|
||||
{
|
||||
// noop
|
||||
}
|
||||
|
||||
virtual void destroy()
|
||||
@@ -98,7 +120,8 @@ class ChannelRPCServiceImpl : public ChannelRPC
|
||||
|
||||
|
||||
class RPCChannel :
|
||||
public virtual Channel
|
||||
public virtual Channel,
|
||||
public std::tr1::enable_shared_from_this<Channel>
|
||||
{
|
||||
private:
|
||||
|
||||
@@ -192,7 +215,7 @@ public:
|
||||
{
|
||||
ChannelGet::shared_pointer nullPtr;
|
||||
channelGetRequester->channelGetConnect(notSupportedStatus, nullPtr,
|
||||
epics::pvData::PVStructure::shared_pointer(), epics::pvData::BitSet::shared_pointer());
|
||||
epics::pvData::Structure::const_shared_pointer());
|
||||
return nullPtr;
|
||||
}
|
||||
|
||||
@@ -202,7 +225,7 @@ public:
|
||||
{
|
||||
ChannelPut::shared_pointer nullPtr;
|
||||
channelPutRequester->channelPutConnect(notSupportedStatus, nullPtr,
|
||||
epics::pvData::PVStructure::shared_pointer(), epics::pvData::BitSet::shared_pointer());
|
||||
epics::pvData::Structure::const_shared_pointer());
|
||||
return nullPtr;
|
||||
}
|
||||
|
||||
@@ -212,7 +235,7 @@ public:
|
||||
epics::pvData::PVStructure::shared_pointer const & /*pvRequest*/)
|
||||
{
|
||||
ChannelPutGet::shared_pointer nullPtr;
|
||||
epics::pvData::PVStructure::shared_pointer nullStructure;
|
||||
epics::pvData::Structure::const_shared_pointer nullStructure;
|
||||
channelPutGetRequester->channelPutGetConnect(notSupportedStatus, nullPtr, nullStructure, nullStructure);
|
||||
return nullPtr;
|
||||
}
|
||||
@@ -233,7 +256,9 @@ public:
|
||||
return nullPtr;
|
||||
}
|
||||
|
||||
ChannelRPC::shared_pointer channelRPCImpl(new ChannelRPCServiceImpl(channelRPCRequester, m_rpcService));
|
||||
ChannelRPC::shared_pointer channelRPCImpl(
|
||||
new ChannelRPCServiceImpl(shared_from_this(), channelRPCRequester, m_rpcService)
|
||||
);
|
||||
channelRPCRequester->channelRPCConnect(Status::Ok, channelRPCImpl);
|
||||
return channelRPCImpl;
|
||||
}
|
||||
@@ -252,7 +277,7 @@ public:
|
||||
epics::pvData::PVStructure::shared_pointer const & /*pvRequest*/)
|
||||
{
|
||||
ChannelArray::shared_pointer nullPtr;
|
||||
channelArrayRequester->channelArrayConnect(notSupportedStatus, nullPtr, epics::pvData::PVArray::shared_pointer());
|
||||
channelArrayRequester->channelArrayConnect(notSupportedStatus, nullPtr, epics::pvData::Array::const_shared_pointer());
|
||||
return nullPtr;
|
||||
}
|
||||
|
||||
@@ -291,6 +316,13 @@ public:
|
||||
Status RPCChannel::notSupportedStatus(Status::STATUSTYPE_ERROR, "only channelRPC requests are supported by this channel");
|
||||
Status RPCChannel::destroyedStatus(Status::STATUSTYPE_ERROR, "channel destroyed");
|
||||
|
||||
Channel::shared_pointer createRPCChannel(ChannelProvider::shared_pointer const & provider,
|
||||
epics::pvData::String const & channelName,
|
||||
ChannelRequester::shared_pointer const & channelRequester,
|
||||
RPCService::shared_pointer const & rpcService)
|
||||
{
|
||||
return Channel::shared_pointer(new RPCChannel(provider, channelName, channelRequester, rpcService));
|
||||
}
|
||||
|
||||
|
||||
class RPCChannelProvider :
|
||||
@@ -319,7 +351,7 @@ public:
|
||||
return shared_from_this();
|
||||
}
|
||||
|
||||
virtual void cancelChannelFind() {}
|
||||
virtual void cancel() {}
|
||||
|
||||
virtual void destroy() {}
|
||||
|
||||
@@ -337,7 +369,28 @@ public:
|
||||
}
|
||||
|
||||
|
||||
virtual Channel::shared_pointer createChannel(
|
||||
virtual ChannelFind::shared_pointer channelList(
|
||||
ChannelListRequester::shared_pointer const & channelListRequester)
|
||||
{
|
||||
if (!channelListRequester.get())
|
||||
throw std::runtime_error("null requester");
|
||||
|
||||
PVStringArray::svector channelNames;
|
||||
{
|
||||
Lock guard(m_mutex);
|
||||
channelNames.reserve(m_services.size());
|
||||
for (RPCServiceMap::const_iterator iter = m_services.begin();
|
||||
iter != m_services.end();
|
||||
iter++)
|
||||
channelNames.push_back(iter->first);
|
||||
}
|
||||
|
||||
ChannelFind::shared_pointer thisPtr(shared_from_this());
|
||||
channelListRequester->channelListResult(Status::Ok, thisPtr, freeze(channelNames), false);
|
||||
return thisPtr;
|
||||
}
|
||||
|
||||
virtual Channel::shared_pointer createChannel(
|
||||
epics::pvData::String const & channelName,
|
||||
ChannelRequester::shared_pointer const & channelRequester,
|
||||
short /*priority*/)
|
||||
@@ -438,7 +491,7 @@ RPCServer::RPCServer()
|
||||
m_serverContext = ServerContextImpl::create();
|
||||
m_serverContext->setChannelProviderName(m_channelProviderImpl->getProviderName());
|
||||
|
||||
m_serverContext->initialize(getChannelAccess());
|
||||
m_serverContext->initialize(getChannelProviderRegistry());
|
||||
}
|
||||
|
||||
RPCServer::~RPCServer()
|
||||
@@ -458,6 +511,37 @@ void RPCServer::run(int seconds)
|
||||
m_serverContext->run(seconds);
|
||||
}
|
||||
|
||||
struct ThreadRunnerParam {
|
||||
RPCServer::shared_pointer server;
|
||||
int timeToRun;
|
||||
};
|
||||
|
||||
static void threadRunner(void* usr)
|
||||
{
|
||||
ThreadRunnerParam* pusr = static_cast<ThreadRunnerParam*>(usr);
|
||||
ThreadRunnerParam param = *pusr;
|
||||
delete pusr;
|
||||
|
||||
param.server->run(param.timeToRun);
|
||||
}
|
||||
|
||||
/// Method requires usage of std::tr1::shared_ptr<RPCServer>. This instance must be
|
||||
/// owned by a shared_ptr instance.
|
||||
void RPCServer::runInNewThread(int seconds)
|
||||
{
|
||||
std::auto_ptr<ThreadRunnerParam> param(new ThreadRunnerParam());
|
||||
param->server = shared_from_this();
|
||||
param->timeToRun = seconds;
|
||||
|
||||
epicsThreadCreate("RPCServer thread",
|
||||
epicsThreadPriorityMedium,
|
||||
epicsThreadGetStackSize(epicsThreadStackSmall),
|
||||
threadRunner, param.get());
|
||||
|
||||
// let the thread delete 'param'
|
||||
param.release();
|
||||
}
|
||||
|
||||
void RPCServer::destroy()
|
||||
{
|
||||
m_serverContext->destroy();
|
||||
|
||||
@@ -27,7 +27,9 @@
|
||||
|
||||
namespace epics { namespace pvAccess {
|
||||
|
||||
class epicsShareClass RPCServer {
|
||||
class epicsShareClass RPCServer :
|
||||
public std::tr1::enable_shared_from_this<RPCServer>
|
||||
{
|
||||
private:
|
||||
|
||||
ServerContextImpl::shared_pointer m_serverContext;
|
||||
@@ -49,6 +51,10 @@ class epicsShareClass RPCServer {
|
||||
|
||||
void run(int seconds = 0);
|
||||
|
||||
/// Method requires usage of std::tr1::shared_ptr<RPCServer>. This instance must be
|
||||
/// owned by a shared_ptr instance.
|
||||
void runInNewThread(int seconds = 0);
|
||||
|
||||
void destroy();
|
||||
|
||||
/**
|
||||
@@ -58,6 +64,10 @@ class epicsShareClass RPCServer {
|
||||
|
||||
};
|
||||
|
||||
epicsShareExtern Channel::shared_pointer createRPCChannel(ChannelProvider::shared_pointer const & provider,
|
||||
epics::pvData::String const & channelName,
|
||||
ChannelRequester::shared_pointer const & channelRequester,
|
||||
RPCService::shared_pointer const & rpcService);
|
||||
|
||||
}}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ const Status BaseChannelRequester::noReadACLStatus = Status(Status::STATUSTYPE_E
|
||||
const Status BaseChannelRequester::noWriteACLStatus = Status(Status::STATUSTYPE_ERROR, "no write access");
|
||||
const Status BaseChannelRequester::noProcessACLStatus = Status(Status::STATUSTYPE_ERROR, "no process access");
|
||||
const Status BaseChannelRequester::otherRequestPendingStatus = Status(Status::STATUSTYPE_ERROR, "other request pending");
|
||||
const Status BaseChannelRequester::notAChannelRequestStatus = Status(Status::STATUSTYPE_ERROR, "not a channel request");
|
||||
|
||||
const int32 BaseChannelRequester::NULL_REQUEST = -1;
|
||||
|
||||
|
||||
@@ -48,6 +48,7 @@ public:
|
||||
static const epics::pvData::Status noWriteACLStatus;
|
||||
static const epics::pvData::Status noProcessACLStatus;
|
||||
static const epics::pvData::Status otherRequestPendingStatus;
|
||||
static const epics::pvData::Status notAChannelRequestStatus;
|
||||
protected:
|
||||
const pvAccessID _ioid;
|
||||
Transport::shared_pointer _transport;
|
||||
|
||||
@@ -25,10 +25,12 @@ const float BeaconEmitter::EPICS_PVA_MIN_BEACON_PERIOD = 1.0;
|
||||
const float BeaconEmitter::EPICS_PVA_MIN_BEACON_COUNT_LIMIT = 3.0;
|
||||
|
||||
//BeaconEmitter::BeaconEmitter(Transport::shared_pointer const & transport, ServerContextImpl::shared_pointer const & context) :
|
||||
BeaconEmitter::BeaconEmitter(Transport::shared_pointer const & transport, std::tr1::shared_ptr<ServerContextImpl>& context) :
|
||||
BeaconEmitter::BeaconEmitter(std::string const & protocol,
|
||||
Transport::shared_pointer const & transport, std::tr1::shared_ptr<ServerContextImpl>& context) :
|
||||
_protocol(protocol),
|
||||
_transport(transport),
|
||||
_beaconSequenceID(0),
|
||||
_startupTime(),
|
||||
_guid(context->getGUID()),
|
||||
_fastBeaconPeriod(std::max(context->getBeaconPeriod(), EPICS_PVA_MIN_BEACON_PERIOD)),
|
||||
_slowBeaconPeriod(std::max(180.0, _fastBeaconPeriod)), // TODO configurable
|
||||
_beaconCountLimit((int16)std::max(10.0f, EPICS_PVA_MIN_BEACON_COUNT_LIMIT)), // TODO configurable
|
||||
@@ -37,22 +39,6 @@ BeaconEmitter::BeaconEmitter(Transport::shared_pointer const & transport, std::t
|
||||
_serverStatusProvider(context->getBeaconServerStatusProvider()),
|
||||
_timer(context->getTimer())
|
||||
{
|
||||
_startupTime.getCurrent();
|
||||
}
|
||||
|
||||
BeaconEmitter::BeaconEmitter(Transport::shared_pointer const & transport, const osiSockAddr& serverAddress) :
|
||||
_transport(transport),
|
||||
_beaconSequenceID(0),
|
||||
_startupTime(),
|
||||
_fastBeaconPeriod(EPICS_PVA_MIN_BEACON_PERIOD),
|
||||
_slowBeaconPeriod(180.0),
|
||||
_beaconCountLimit(10),
|
||||
_serverAddress(serverAddress),
|
||||
_serverPort(serverAddress.ia.sin_port),
|
||||
_serverStatusProvider(),
|
||||
_timer(new Timer("pvAccess-server timer", lowPriority))
|
||||
{
|
||||
_startupTime.getCurrent();
|
||||
}
|
||||
|
||||
BeaconEmitter::~BeaconEmitter()
|
||||
@@ -89,16 +75,20 @@ void BeaconEmitter::send(ByteBuffer* buffer, TransportSendControl* control)
|
||||
}
|
||||
|
||||
// send beacon
|
||||
control->startMessage((int8)0, (sizeof(int16)+2*sizeof(int32)+128+sizeof(int16))/sizeof(int8));
|
||||
control->startMessage((int8)0, 12+2+2+16+2);
|
||||
|
||||
buffer->put(_guid.value, 0, sizeof(_guid.value));
|
||||
buffer->putShort(_beaconSequenceID);
|
||||
buffer->putLong((int64)_startupTime.getSecondsPastEpoch());
|
||||
buffer->putInt((int32)_startupTime.getNanoSeconds());
|
||||
|
||||
// TODO for now fixed changeCount
|
||||
buffer->putShort(0);
|
||||
|
||||
// NOTE: is it possible (very likely) that address is any local address ::ffff:0.0.0.0
|
||||
encodeAsIPv6Address(buffer, &_serverAddress);
|
||||
buffer->putShort((int16)_serverPort);
|
||||
|
||||
SerializeHelper::serializeString(_protocol, buffer, control);
|
||||
|
||||
if (serverStatus)
|
||||
{
|
||||
// introspection interface + data
|
||||
|
||||
@@ -47,18 +47,15 @@ namespace epics { namespace pvAccess {
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param protocol a protocol (transport) name to report.
|
||||
* @param transport transport to be used to send beacons.
|
||||
* @param context PVA context.
|
||||
*/
|
||||
// BeaconEmitter(Transport::shared_pointer const & transport, ServerContextImpl::shared_pointer const & context);
|
||||
BeaconEmitter(Transport::shared_pointer const & transport, std::tr1::shared_ptr<ServerContextImpl>& context);
|
||||
// BeaconEmitter(std::sting const & protocol,
|
||||
// Transport::shared_pointer const & transport, ServerContextImpl::shared_pointer const & context);
|
||||
BeaconEmitter(std::string const & protocol,
|
||||
Transport::shared_pointer const & transport, std::tr1::shared_ptr<ServerContextImpl>& context);
|
||||
|
||||
/**
|
||||
* Test Constructor (ohne context)
|
||||
* @param transport transport to be used to send beacons.
|
||||
*/
|
||||
BeaconEmitter(Transport::shared_pointer const & transport, const osiSockAddr& serverAddress);
|
||||
|
||||
virtual ~BeaconEmitter();
|
||||
|
||||
void lock();
|
||||
@@ -97,6 +94,11 @@ namespace epics { namespace pvAccess {
|
||||
*/
|
||||
static const float EPICS_PVA_MIN_BEACON_COUNT_LIMIT;
|
||||
|
||||
/**
|
||||
* Protocol.
|
||||
*/
|
||||
std::string _protocol;
|
||||
|
||||
/**
|
||||
* Transport.
|
||||
*/
|
||||
@@ -108,9 +110,9 @@ namespace epics { namespace pvAccess {
|
||||
epics::pvData::int16 _beaconSequenceID;
|
||||
|
||||
/**
|
||||
* Startup timestamp (when clients detect a change, they will consider server restarted).
|
||||
* Server GUID.
|
||||
*/
|
||||
epics::pvData::TimeStamp _startupTime;
|
||||
GUID _guid;
|
||||
|
||||
/**
|
||||
* Fast (at startup) beacon period (in sec).
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -133,22 +133,6 @@ namespace pvAccess {
|
||||
osiSockAddr _echoFrom;
|
||||
};
|
||||
|
||||
/**
|
||||
* Introspection search request handler.
|
||||
*/
|
||||
class ServerIntrospectionSearchHandler : public AbstractServerResponseHandler
|
||||
{
|
||||
public:
|
||||
ServerIntrospectionSearchHandler(ServerContextImpl::shared_pointer const & context) :
|
||||
AbstractServerResponseHandler(context, "Search request") {
|
||||
}
|
||||
virtual ~ServerIntrospectionSearchHandler() {}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport::shared_pointer const & transport, epics::pvData::int8 version, epics::pvData::int8 command,
|
||||
std::size_t payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
/**
|
||||
* Search channel request handler.
|
||||
@@ -159,7 +143,9 @@ namespace pvAccess {
|
||||
public:
|
||||
// TODO
|
||||
static std::map<epics::pvData::String, std::tr1::weak_ptr<ChannelProvider> > s_channelNameToProvider;
|
||||
|
||||
|
||||
static std::string SUPPORTED_PROTOCOL;
|
||||
|
||||
ServerSearchHandler(ServerContextImpl::shared_pointer const & context);
|
||||
virtual ~ServerSearchHandler(){}
|
||||
|
||||
@@ -168,7 +154,7 @@ namespace pvAccess {
|
||||
std::size_t payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
|
||||
private:
|
||||
std::vector<ChannelProvider::shared_pointer> _providers;
|
||||
std::vector<ChannelProvider::shared_pointer> _providers;
|
||||
};
|
||||
|
||||
|
||||
@@ -181,22 +167,25 @@ namespace pvAccess {
|
||||
ServerChannelFindRequesterImpl(ServerContextImpl::shared_pointer const & context, epics::pvData::int32 expectedResponseCount);
|
||||
virtual ~ServerChannelFindRequesterImpl(){}
|
||||
void clear();
|
||||
ServerChannelFindRequesterImpl* set(epics::pvData::String _name, epics::pvData::int32 searchSequenceId, epics::pvData::int32 cid, osiSockAddr* sendTo, bool responseRequired);
|
||||
ServerChannelFindRequesterImpl* set(epics::pvData::String _name, epics::pvData::int32 searchSequenceId,
|
||||
epics::pvData::int32 cid, osiSockAddr const & sendTo, bool responseRequired, bool serverSearch);
|
||||
void channelFindResult(const epics::pvData::Status& status, ChannelFind::shared_pointer const & channelFind, bool wasFound);
|
||||
void lock();
|
||||
void unlock();
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control);
|
||||
private:
|
||||
GUID _guid;
|
||||
epics::pvData::String _name;
|
||||
epics::pvData::int32 _searchSequenceId;
|
||||
epics::pvData::int32 _cid;
|
||||
osiSockAddr* _sendTo;
|
||||
osiSockAddr _sendTo;
|
||||
bool _responseRequired;
|
||||
bool _wasFound;
|
||||
ServerContextImpl::shared_pointer _context;
|
||||
epics::pvData::Mutex _mutex;
|
||||
epics::pvData::int32 _expectedResponseCount;
|
||||
epics::pvData::int32 _responseCount;
|
||||
bool _serverSearch;
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
@@ -217,6 +206,8 @@ namespace pvAccess {
|
||||
std::size_t payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
|
||||
private:
|
||||
static epics::pvData::String SERVER_CHANNEL_NAME;
|
||||
|
||||
void disconnect(Transport::shared_pointer const & transport);
|
||||
std::vector<ChannelProvider::shared_pointer> _providers;
|
||||
};
|
||||
@@ -226,13 +217,14 @@ namespace pvAccess {
|
||||
public TransportSender,
|
||||
public std::tr1::enable_shared_from_this<ServerChannelRequesterImpl>
|
||||
{
|
||||
friend class ServerCreateChannelHandler;
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<ServerChannelRequesterImpl> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ServerChannelRequesterImpl> const_shared_pointer;
|
||||
protected:
|
||||
ServerChannelRequesterImpl(Transport::shared_pointer const & transport, const epics::pvData::String channelName, const pvAccessID cid);
|
||||
public:
|
||||
virtual ~ServerChannelRequesterImpl() {}
|
||||
virtual ~ServerChannelRequesterImpl() {}
|
||||
static ChannelRequester::shared_pointer create(ChannelProvider::shared_pointer const & provider, Transport::shared_pointer const & transport, const epics::pvData::String channelName, const pvAccessID cid);
|
||||
void channelCreated(const epics::pvData::Status& status, Channel::shared_pointer const & channel);
|
||||
void channelStateChange(Channel::shared_pointer const & c, const Channel::ConnectionState isConnected);
|
||||
@@ -333,8 +325,10 @@ namespace pvAccess {
|
||||
epics::pvData::PVStructure::shared_pointer const & pvRequest);
|
||||
virtual ~ServerChannelGetRequesterImpl() {}
|
||||
void channelGetConnect(const epics::pvData::Status& status, ChannelGet::shared_pointer const & channelGet,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvStructure, epics::pvData::BitSet::shared_pointer const & bitSet);
|
||||
void getDone(const epics::pvData::Status& status);
|
||||
epics::pvData::Structure::const_shared_pointer const & structure);
|
||||
void getDone(const epics::pvData::Status& status, ChannelGet::shared_pointer const & channelGet,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvStructure,
|
||||
epics::pvData::BitSet::shared_pointer const & bitSet);
|
||||
void destroy();
|
||||
|
||||
ChannelGet::shared_pointer getChannelGet();
|
||||
@@ -344,8 +338,9 @@ namespace pvAccess {
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control);
|
||||
private:
|
||||
ChannelGet::shared_pointer _channelGet;
|
||||
epics::pvData::BitSet::shared_pointer _bitSet;
|
||||
epics::pvData::Structure::const_shared_pointer _structure;
|
||||
epics::pvData::PVStructure::shared_pointer _pvStructure;
|
||||
epics::pvData::BitSet::shared_pointer _bitSet;
|
||||
epics::pvData::Status _status;
|
||||
};
|
||||
|
||||
@@ -387,21 +382,30 @@ namespace pvAccess {
|
||||
Transport::shared_pointer const & transport,epics::pvData::PVStructure::shared_pointer const & pvRequest);
|
||||
|
||||
virtual ~ServerChannelPutRequesterImpl() {}
|
||||
void channelPutConnect(const epics::pvData::Status& status, ChannelPut::shared_pointer const & channelPut, epics::pvData::PVStructure::shared_pointer const & pvStructure, epics::pvData::BitSet::shared_pointer const & bitSet);
|
||||
void putDone(const epics::pvData::Status& status);
|
||||
void getDone(const epics::pvData::Status& status);
|
||||
void channelPutConnect(const epics::pvData::Status& status, ChannelPut::shared_pointer const & channelPut, epics::pvData::Structure::const_shared_pointer const & structure);
|
||||
void putDone(const epics::pvData::Status& status, ChannelPut::shared_pointer const & channelPut);
|
||||
void getDone(const epics::pvData::Status& status, ChannelPut::shared_pointer const & channelPut, epics::pvData::PVStructure::shared_pointer const & pvStructure, epics::pvData::BitSet::shared_pointer const & bitSet);
|
||||
void lock();
|
||||
void unlock();
|
||||
void destroy();
|
||||
|
||||
ChannelPut::shared_pointer getChannelPut();
|
||||
epics::pvData::BitSet::shared_pointer getBitSet();
|
||||
epics::pvData::PVStructure::shared_pointer getPVStructure();
|
||||
epics::pvData::BitSet::shared_pointer getPutBitSet();
|
||||
epics::pvData::PVStructure::shared_pointer getPutPVStructure();
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control);
|
||||
private:
|
||||
ChannelPut::shared_pointer _channelPut;
|
||||
|
||||
epics::pvData::Structure::const_shared_pointer _structure;
|
||||
|
||||
// reference store (for get)
|
||||
epics::pvData::BitSet::shared_pointer _bitSet;
|
||||
epics::pvData::PVStructure::shared_pointer _pvStructure;
|
||||
|
||||
// data store (for put)
|
||||
epics::pvData::BitSet::shared_pointer _putBitSet;
|
||||
epics::pvData::PVStructure::shared_pointer _putPVStructure;
|
||||
|
||||
epics::pvData::Status _status;
|
||||
};
|
||||
|
||||
@@ -442,21 +446,43 @@ namespace pvAccess {
|
||||
Transport::shared_pointer const & transport,epics::pvData::PVStructure::shared_pointer const & pvRequest);
|
||||
virtual ~ServerChannelPutGetRequesterImpl() {}
|
||||
|
||||
void channelPutGetConnect(const epics::pvData::Status& status, ChannelPutGet::shared_pointer const & channelPutGet, epics::pvData::PVStructure::shared_pointer const & pvPutStructure, epics::pvData::PVStructure::shared_pointer const & pvGetStructure);
|
||||
void getGetDone(const epics::pvData::Status& status);
|
||||
void getPutDone(const epics::pvData::Status& status);
|
||||
void putGetDone(const epics::pvData::Status& status);
|
||||
void channelPutGetConnect(const epics::pvData::Status& status, ChannelPutGet::shared_pointer const & channelPutGet,
|
||||
epics::pvData::Structure::const_shared_pointer const & putStructure,
|
||||
epics::pvData::Structure::const_shared_pointer const & getStructure);
|
||||
void getGetDone(const epics::pvData::Status& status, ChannelPutGet::shared_pointer const & channelPutGet,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvStructure,
|
||||
epics::pvData::BitSet::shared_pointer const & bitSet);
|
||||
void getPutDone(const epics::pvData::Status& status, ChannelPutGet::shared_pointer const & channelPutGet,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvStructure,
|
||||
epics::pvData::BitSet::shared_pointer const & bitSet);
|
||||
void putGetDone(const epics::pvData::Status& status, ChannelPutGet::shared_pointer const & channelPutGet,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvStructure,
|
||||
epics::pvData::BitSet::shared_pointer const & bitSet);
|
||||
void lock();
|
||||
void unlock();
|
||||
void destroy();
|
||||
|
||||
ChannelPutGet::shared_pointer getChannelPutGet();
|
||||
epics::pvData::PVStructure::shared_pointer getPVPutStructure();
|
||||
|
||||
epics::pvData::PVStructure::shared_pointer getPutGetPVStructure();
|
||||
epics::pvData::BitSet::shared_pointer getPutGetBitSet();
|
||||
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control);
|
||||
private:
|
||||
ChannelPutGet::shared_pointer _channelPutGet;
|
||||
epics::pvData::Structure::const_shared_pointer _putStructure;
|
||||
epics::pvData::Structure::const_shared_pointer _getStructure;
|
||||
|
||||
// reference store
|
||||
epics::pvData::PVStructure::shared_pointer _pvPutStructure;
|
||||
epics::pvData::BitSet::shared_pointer _pvPutBitSet;
|
||||
epics::pvData::PVStructure::shared_pointer _pvGetStructure;
|
||||
epics::pvData::BitSet::shared_pointer _pvGetBitSet;
|
||||
|
||||
// data container (for put-get)
|
||||
epics::pvData::PVStructure::shared_pointer _pvPutGetStructure;
|
||||
epics::pvData::BitSet::shared_pointer _pvPutGetBitSet;
|
||||
|
||||
epics::pvData::Status _status;
|
||||
};
|
||||
|
||||
@@ -552,10 +578,13 @@ namespace pvAccess {
|
||||
Transport::shared_pointer const & transport,epics::pvData::PVStructure::shared_pointer const & pvRequest);
|
||||
virtual ~ServerChannelArrayRequesterImpl() {}
|
||||
|
||||
void channelArrayConnect(const epics::pvData::Status& status, ChannelArray::shared_pointer const & channelArray, epics::pvData::PVArray::shared_pointer const & pvArray);
|
||||
void getArrayDone(const epics::pvData::Status& status);
|
||||
void putArrayDone(const epics::pvData::Status& status);
|
||||
void setLengthDone(const epics::pvData::Status& status);
|
||||
void channelArrayConnect(const epics::pvData::Status& status, ChannelArray::shared_pointer const & channelArray, epics::pvData::Array::const_shared_pointer const & array);
|
||||
void getArrayDone(const epics::pvData::Status& status, ChannelArray::shared_pointer const & channelArray,
|
||||
epics::pvData::PVArray::shared_pointer const & pvArray);
|
||||
void putArrayDone(const epics::pvData::Status& status, ChannelArray::shared_pointer const & channelArray);
|
||||
void setLengthDone(const epics::pvData::Status& status, ChannelArray::shared_pointer const & channelArray);
|
||||
void getLengthDone(const epics::pvData::Status& status, ChannelArray::shared_pointer const & channelArray,
|
||||
std::size_t length, std::size_t capacity);
|
||||
void lock();
|
||||
void unlock();
|
||||
void destroy();
|
||||
@@ -567,10 +596,40 @@ namespace pvAccess {
|
||||
|
||||
private:
|
||||
ChannelArray::shared_pointer _channelArray;
|
||||
epics::pvData::Array::const_shared_pointer _array;
|
||||
|
||||
// reference store
|
||||
epics::pvData::PVArray::shared_pointer _pvArray;
|
||||
|
||||
// data container
|
||||
epics::pvData::PVArray::shared_pointer _pvPutArray;
|
||||
|
||||
std::size_t _length;
|
||||
std::size_t _capacity;
|
||||
epics::pvData::Status _status;
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
/**
|
||||
* Destroy request handler.
|
||||
*/
|
||||
class ServerDestroyRequestHandler : public AbstractServerResponseHandler
|
||||
{
|
||||
public:
|
||||
ServerDestroyRequestHandler(ServerContextImpl::shared_pointer const & context) :
|
||||
AbstractServerResponseHandler(context, "Destroy request") {
|
||||
}
|
||||
virtual ~ServerDestroyRequestHandler() {}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport::shared_pointer const & transport, epics::pvData::int8 version, epics::pvData::int8 command,
|
||||
std::size_t payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
private:
|
||||
|
||||
void failureResponse(Transport::shared_pointer const & transport, pvAccessID ioid, const epics::pvData::Status& errorStatus);
|
||||
};
|
||||
|
||||
|
||||
/****************************************************************************************/
|
||||
/**
|
||||
* Cancel request handler.
|
||||
@@ -578,17 +637,17 @@ namespace pvAccess {
|
||||
class ServerCancelRequestHandler : public AbstractServerResponseHandler
|
||||
{
|
||||
public:
|
||||
ServerCancelRequestHandler(ServerContextImpl::shared_pointer const & context) :
|
||||
AbstractServerResponseHandler(context, "Cancel request") {
|
||||
}
|
||||
ServerCancelRequestHandler(ServerContextImpl::shared_pointer const & context) :
|
||||
AbstractServerResponseHandler(context, "Cancel request") {
|
||||
}
|
||||
virtual ~ServerCancelRequestHandler() {}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport::shared_pointer const & transport, epics::pvData::int8 version, epics::pvData::int8 command,
|
||||
std::size_t payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport::shared_pointer const & transport, epics::pvData::int8 version, epics::pvData::int8 command,
|
||||
std::size_t payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
private:
|
||||
|
||||
void failureResponse(Transport::shared_pointer const & transport, pvAccessID ioid, const epics::pvData::Status& errorStatus);
|
||||
void failureResponse(Transport::shared_pointer const & transport, pvAccessID ioid, const epics::pvData::Status& errorStatus);
|
||||
};
|
||||
|
||||
|
||||
@@ -630,7 +689,7 @@ namespace pvAccess {
|
||||
virtual ~ServerChannelProcessRequesterImpl() {}
|
||||
|
||||
void channelProcessConnect(const epics::pvData::Status& status, ChannelProcess::shared_pointer const & channelProcess);
|
||||
void processDone(const epics::pvData::Status& status);
|
||||
void processDone(const epics::pvData::Status& status, ChannelProcess::shared_pointer const & channelProcess);
|
||||
void lock();
|
||||
void unlock();
|
||||
void destroy();
|
||||
@@ -756,7 +815,7 @@ namespace pvAccess {
|
||||
virtual ~ServerChannelRPCRequesterImpl() {}
|
||||
|
||||
void channelRPCConnect(const epics::pvData::Status& status, ChannelRPC::shared_pointer const & channelRPC);
|
||||
void requestDone(const epics::pvData::Status& status, epics::pvData::PVStructure::shared_pointer const & pvResponse);
|
||||
void requestDone(const epics::pvData::Status& status, ChannelRPC::shared_pointer const & channelRPC, epics::pvData::PVStructure::shared_pointer const & pvResponse);
|
||||
void lock();
|
||||
void unlock();
|
||||
void destroy();
|
||||
|
||||
@@ -36,7 +36,7 @@ ServerContextImpl::ServerContextImpl():
|
||||
_beaconEmitter(),
|
||||
_acceptor(),
|
||||
_transportRegistry(),
|
||||
_channelAccess(),
|
||||
_channelProviderRegistry(),
|
||||
_channelProviderNames(PVACCESS_DEFAULT_PROVIDER),
|
||||
_channelProviders(),
|
||||
_beaconServerStatusProvider()
|
||||
@@ -46,6 +46,7 @@ ServerContextImpl::ServerContextImpl():
|
||||
epicsSignalInstallSigAlarmIgnore ();
|
||||
epicsSignalInstallSigPipeIgnore ();
|
||||
|
||||
generateGUID();
|
||||
initializeLogger();
|
||||
loadConfiguration();
|
||||
}
|
||||
@@ -61,14 +62,30 @@ ServerContextImpl::~ServerContextImpl()
|
||||
dispose();
|
||||
}
|
||||
|
||||
const GUID& ServerContextImpl::getGUID()
|
||||
{
|
||||
return _guid;
|
||||
}
|
||||
|
||||
const Version& ServerContextImpl::getVersion()
|
||||
{
|
||||
return ServerContextImpl::VERSION;
|
||||
}
|
||||
|
||||
void ServerContextImpl::generateGUID()
|
||||
{
|
||||
// TODO use UUID
|
||||
epics::pvData::TimeStamp startupTime;
|
||||
startupTime.getCurrent();
|
||||
|
||||
ByteBuffer buffer(_guid.value, sizeof(_guid.value));
|
||||
buffer.putLong(startupTime.getSecondsPastEpoch());
|
||||
buffer.putInt(startupTime.getNanoSeconds());
|
||||
}
|
||||
|
||||
void ServerContextImpl::initializeLogger()
|
||||
{
|
||||
//createFileLogger("serverContextImpl.log");
|
||||
//createFileLogger("serverContextImpl.log");
|
||||
}
|
||||
|
||||
struct noop_deleter
|
||||
@@ -98,6 +115,11 @@ void ServerContextImpl::loadConfiguration()
|
||||
{
|
||||
Configuration::shared_pointer config = getConfiguration();
|
||||
|
||||
// TODO for now just a simple switch
|
||||
int32 debugLevel = config->getPropertyAsInteger(PVACCESS_DEBUG, 0);
|
||||
if (debugLevel > 0)
|
||||
SET_LOG_LEVEL(logLevelDebug);
|
||||
|
||||
_beaconAddressList = config->getPropertyAsString("EPICS_PVA_ADDR_LIST", _beaconAddressList);
|
||||
_beaconAddressList = config->getPropertyAsString("EPICS_PVAS_BEACON_ADDR_LIST", _beaconAddressList);
|
||||
|
||||
@@ -126,12 +148,12 @@ bool ServerContextImpl::isChannelProviderNamePreconfigured()
|
||||
return config->hasProperty("EPICS_PVA_PROVIDER_NAMES") || config->hasProperty("EPICS_PVAS_PROVIDER_NAMES");
|
||||
}
|
||||
|
||||
void ServerContextImpl::initialize(ChannelAccess::shared_pointer const & channelAccess)
|
||||
void ServerContextImpl::initialize(ChannelProviderRegistry::shared_pointer const & channelProviderRegistry)
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
if (channelAccess == NULL)
|
||||
if (channelProviderRegistry == NULL)
|
||||
{
|
||||
THROW_BASE_EXCEPTION("non null channelAccess expected");
|
||||
THROW_BASE_EXCEPTION("non null channelProviderRegistry expected");
|
||||
}
|
||||
|
||||
if (_state == DESTROYED)
|
||||
@@ -143,7 +165,7 @@ void ServerContextImpl::initialize(ChannelAccess::shared_pointer const & channel
|
||||
THROW_BASE_EXCEPTION("Context already initialized.");
|
||||
}
|
||||
|
||||
_channelAccess = channelAccess;
|
||||
_channelProviderRegistry = channelProviderRegistry;
|
||||
|
||||
|
||||
// user all providers
|
||||
@@ -151,10 +173,10 @@ void ServerContextImpl::initialize(ChannelAccess::shared_pointer const & channel
|
||||
{
|
||||
_channelProviderNames.resize(0); // VxWorks 5.5 omits clear()
|
||||
|
||||
std::auto_ptr<ChannelAccess::stringVector_t> names = _channelAccess->getProviderNames();
|
||||
for (ChannelAccess::stringVector_t::iterator iter = names->begin(); iter != names->end(); iter++)
|
||||
std::auto_ptr<ChannelProviderRegistry::stringVector_t> names = _channelProviderRegistry->getProviderNames();
|
||||
for (ChannelProviderRegistry::stringVector_t::iterator iter = names->begin(); iter != names->end(); iter++)
|
||||
{
|
||||
ChannelProvider::shared_pointer channelProvider = _channelAccess->getProvider(*iter);
|
||||
ChannelProvider::shared_pointer channelProvider = _channelProviderRegistry->getProvider(*iter);
|
||||
if (channelProvider)
|
||||
{
|
||||
_channelProviders.push_back(channelProvider);
|
||||
@@ -173,13 +195,13 @@ void ServerContextImpl::initialize(ChannelAccess::shared_pointer const & channel
|
||||
std::string providerName;
|
||||
while (std::getline(ss, providerName, ' '))
|
||||
{
|
||||
ChannelProvider::shared_pointer channelProvider = _channelAccess->getProvider(providerName);
|
||||
ChannelProvider::shared_pointer channelProvider = _channelProviderRegistry->getProvider(providerName);
|
||||
if (channelProvider)
|
||||
_channelProviders.push_back(channelProvider);
|
||||
}
|
||||
}
|
||||
|
||||
//_channelProvider = _channelAccess->getProvider(_channelProviderNames);
|
||||
//_channelProvider = _channelProviderRegistry->getProvider(_channelProviderNames);
|
||||
if (_channelProviders.size() == 0)
|
||||
{
|
||||
std::string msg = "None of the specified channel providers are available: " + _channelProviderNames + ".";
|
||||
@@ -212,7 +234,8 @@ void ServerContextImpl::internalInitialize()
|
||||
// setup broadcast UDP transport
|
||||
initializeBroadcastTransport();
|
||||
|
||||
_beaconEmitter.reset(new BeaconEmitter(_broadcastTransport, thisServerContext));
|
||||
// TODO introduce a constant
|
||||
_beaconEmitter.reset(new BeaconEmitter("tcp", _broadcastTransport, thisServerContext));
|
||||
}
|
||||
|
||||
void ServerContextImpl::initializeBroadcastTransport()
|
||||
@@ -243,7 +266,7 @@ void ServerContextImpl::initializeBroadcastTransport()
|
||||
nullTransportClient, responseHandler,
|
||||
listenLocalAddress, PVA_PROTOCOL_REVISION,
|
||||
PVA_DEFAULT_PRIORITY));
|
||||
_broadcastTransport->setBroadcastAddresses(broadcastAddresses.get());
|
||||
_broadcastTransport->setSendAddresses(broadcastAddresses.get());
|
||||
|
||||
// set ignore address list
|
||||
if (!_ignoreAddressList.empty())
|
||||
@@ -268,7 +291,7 @@ void ServerContextImpl::initializeBroadcastTransport()
|
||||
auto_ptr<InetAddrVector> list(getSocketAddressList(_beaconAddressList, _broadcastPort, appendList));
|
||||
if (list.get() != NULL && list->size() > 0)
|
||||
{
|
||||
_broadcastTransport->setBroadcastAddresses(list.get());
|
||||
_broadcastTransport->setSendAddresses(list.get());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -545,9 +568,9 @@ BlockingUDPTransport::shared_pointer ServerContextImpl::getBroadcastTransport()
|
||||
return _broadcastTransport;
|
||||
}
|
||||
|
||||
ChannelAccess::shared_pointer ServerContextImpl::getChannelAccess()
|
||||
ChannelProviderRegistry::shared_pointer ServerContextImpl::getChannelProviderRegistry()
|
||||
{
|
||||
return _channelAccess;
|
||||
return _channelProviderRegistry;
|
||||
}
|
||||
|
||||
std::string ServerContextImpl::getChannelProviderName()
|
||||
@@ -621,8 +644,8 @@ ServerContext::shared_pointer startPVAServer(String const & providerNames, int t
|
||||
if (!ctx->isChannelProviderNamePreconfigured())
|
||||
ctx->setChannelProviderName(providerNames);
|
||||
|
||||
ChannelAccess::shared_pointer channelAccess = getChannelAccess();
|
||||
ctx->initialize(channelAccess);
|
||||
ChannelProviderRegistry::shared_pointer channelProviderRegistry = getChannelProviderRegistry();
|
||||
ctx->initialize(channelProviderRegistry);
|
||||
|
||||
if (printInfo)
|
||||
ctx->printInfo();
|
||||
|
||||
@@ -35,6 +35,13 @@ public:
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ServerContext() {};
|
||||
|
||||
/**
|
||||
* Returns GUID (12-byte array).
|
||||
* @return GUID.
|
||||
*/
|
||||
virtual const GUID& getGUID() = 0;
|
||||
|
||||
/**
|
||||
* Get context implementation version.
|
||||
* @return version of the context implementation.
|
||||
@@ -42,10 +49,10 @@ public:
|
||||
virtual const Version& getVersion() = 0;
|
||||
|
||||
/**
|
||||
* Set <code>ChannelAccess</code> implementation and initialize server.
|
||||
* @param channelAccess implementation of channel access to be served.
|
||||
* Set <code>ChannelProviderRegistry</code> implementation and initialize server.
|
||||
* @param channelProviderRegistry channel providers registry to be used.
|
||||
*/
|
||||
virtual void initialize(ChannelAccess::shared_pointer const & channelAccess) = 0;
|
||||
virtual void initialize(ChannelProviderRegistry::shared_pointer const & channelProviderRegistry) = 0;
|
||||
|
||||
/**
|
||||
* Run server (process events).
|
||||
@@ -115,8 +122,9 @@ public:
|
||||
virtual ~ServerContextImpl();
|
||||
|
||||
//**************** derived from ServerContext ****************//
|
||||
const GUID& getGUID();
|
||||
const Version& getVersion();
|
||||
void initialize(ChannelAccess::shared_pointer const & channelAccess);
|
||||
void initialize(ChannelProviderRegistry::shared_pointer const & channelProviderRegistry);
|
||||
void run(epics::pvData::int32 seconds);
|
||||
void shutdown();
|
||||
void destroy();
|
||||
@@ -253,10 +261,10 @@ public:
|
||||
BlockingUDPTransport::shared_pointer getBroadcastTransport();
|
||||
|
||||
/**
|
||||
* Get channel access implementation.
|
||||
* @return channel access implementation.
|
||||
* Get channel provider registry implementation used by this instance.
|
||||
* @return channel provider registry used by this instance.
|
||||
*/
|
||||
ChannelAccess::shared_pointer getChannelAccess();
|
||||
ChannelProviderRegistry::shared_pointer getChannelProviderRegistry();
|
||||
|
||||
/**
|
||||
* Get channel provider name.
|
||||
@@ -283,6 +291,12 @@ public:
|
||||
bool isChannelProviderNamePreconfigured();
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Server GUID.
|
||||
*/
|
||||
GUID _guid;
|
||||
|
||||
/**
|
||||
* Initialization status.
|
||||
*/
|
||||
@@ -354,7 +368,7 @@ private:
|
||||
/**
|
||||
* Channel access.
|
||||
*/
|
||||
ChannelAccess::shared_pointer _channelAccess;
|
||||
ChannelProviderRegistry::shared_pointer _channelProviderRegistry;
|
||||
|
||||
/**
|
||||
* Channel provider name.
|
||||
@@ -381,6 +395,11 @@ private:
|
||||
*/
|
||||
BeaconServerStatusProvider::shared_pointer _beaconServerStatusProvider;
|
||||
|
||||
/**
|
||||
* Generate GUID.
|
||||
*/
|
||||
void generateGUID();
|
||||
|
||||
/**
|
||||
* Initialize logger.
|
||||
*/
|
||||
|
||||
@@ -64,6 +64,12 @@ void encodeAsIPv6Address(ByteBuffer* buffer, const osiSockAddr* address) {
|
||||
buffer->putByte((int8)(ipv4Addr&0xFF));
|
||||
}
|
||||
|
||||
bool isMulticastAddress(const osiSockAddr* address) {
|
||||
uint32_t ipv4Addr = ntohl(address->ia.sin_addr.s_addr);
|
||||
uint8_t msB = (uint8_t)((ipv4Addr>>24)&0xFF);
|
||||
return msB >= 224 && msB <= 239;
|
||||
}
|
||||
|
||||
osiSockAddr* intToIPv4Address(int32 addr) {
|
||||
osiSockAddr* ret = new osiSockAddr;
|
||||
ret->ia.sin_family = AF_INET;
|
||||
@@ -121,15 +127,15 @@ InetAddrVector* getSocketAddressList(String list, int defaultPort,
|
||||
while((subEnd = list.find(' ', subStart))!=String::npos) {
|
||||
String address = list.substr(subStart, (subEnd-subStart));
|
||||
osiSockAddr addr;
|
||||
aToIPAddr(address.c_str(), defaultPort, &addr.ia);
|
||||
iav->push_back(addr);
|
||||
if (aToIPAddr(address.c_str(), defaultPort, &addr.ia) == 0)
|
||||
iav->push_back(addr);
|
||||
subStart = list.find_first_not_of(" \t\r\n\v", subEnd);
|
||||
}
|
||||
|
||||
if(subStart!=String::npos&&list.length()>0) {
|
||||
osiSockAddr addr;
|
||||
aToIPAddr(list.substr(subStart).c_str(), defaultPort, &addr.ia);
|
||||
iav->push_back(addr);
|
||||
if (aToIPAddr(list.substr(subStart).c_str(), defaultPort, &addr.ia) == 0)
|
||||
iav->push_back(addr);
|
||||
}
|
||||
|
||||
if(appendList!=NULL) {
|
||||
|
||||
@@ -49,6 +49,13 @@ namespace pvAccess {
|
||||
*/
|
||||
epicsShareFunc void encodeAsIPv6Address(epics::pvData::ByteBuffer* buffer, const osiSockAddr* address);
|
||||
|
||||
/**
|
||||
* Check if an IPv4 address is a multicast address.
|
||||
* @param address IPv4 address to check.
|
||||
* @return true if the adress is a multicast address.
|
||||
*/
|
||||
epicsShareFunc bool isMulticastAddress(const osiSockAddr* address);
|
||||
|
||||
/**
|
||||
* Convert an integer into an IPv4 INET address.
|
||||
* @param addr integer representation of a given address.
|
||||
|
||||
@@ -54,7 +54,7 @@ public:
|
||||
return m_provider.lock();
|
||||
};
|
||||
|
||||
virtual void cancelChannelFind() {}
|
||||
virtual void cancel() {}
|
||||
|
||||
private:
|
||||
ChannelProvider::weak_pointer m_provider;
|
||||
|
||||
@@ -6,10 +6,6 @@ include $(TOP)/configure/CONFIG
|
||||
testChannelAccessFactory_SRCS = testChannelAccessFactory.cpp
|
||||
testChannelAccessFactory_LIBS = pvAccess pvData Com
|
||||
|
||||
PROD_HOST += testCreateRequest
|
||||
testCreateRequest_SRCS = testCreateRequest.cpp
|
||||
testCreateRequest_LIBS = pvAccess pvData pvMB Com
|
||||
|
||||
#PROD_HOST += testMockClient
|
||||
testMockClient_SRCS = testMockClient.cpp MockClientImpl.cpp
|
||||
testMockClient_LIBS = pvAccess pvData Com
|
||||
|
||||
@@ -556,7 +556,7 @@ class MockChannelFind : public ChannelFind
|
||||
return m_provider;
|
||||
};
|
||||
|
||||
virtual void cancelChannelFind()
|
||||
virtual void cancel()
|
||||
{
|
||||
throw std::runtime_error("not supported");
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ public:
|
||||
void testChannelAccessFactory() {
|
||||
printf("testChannelAccessFactory... ");
|
||||
|
||||
ChannelAccess* ca = getChannelAccess();
|
||||
ChannelAccess* ca = getChannelProviderRegistry();
|
||||
assert(ca);
|
||||
|
||||
// empty
|
||||
|
||||
@@ -1,132 +0,0 @@
|
||||
/* testCreateRequest.cpp */
|
||||
/* Author: Matej Sekoranja Date: 2010.12.27 */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <pv/pvAccess.h>
|
||||
#include <iostream>
|
||||
|
||||
#include <epicsAssert.h>
|
||||
#include <epicsExit.h>
|
||||
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
|
||||
|
||||
void testCreateRequest() {
|
||||
printf("testCreateRequest... \n");
|
||||
CreateRequest::shared_pointer createRequest = CreateRequest::create();
|
||||
|
||||
String out;
|
||||
String request = "";
|
||||
std::cout << std::endl << String("request") <<std::endl << request <<std::endl;
|
||||
PVStructurePtr pvRequest = createRequest->createRequest(request);
|
||||
assert(pvRequest.get());
|
||||
out.clear(); pvRequest->toString(&out); std::cout << out << std::endl;
|
||||
|
||||
request = "record[process=true] field(alarm , timeStamp) putField( synput:a,synput:b,stnput:c)";
|
||||
std::cout << std::endl << String("request") <<std::endl << request <<std::endl;
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
assert(pvRequest.get());
|
||||
out.clear(); pvRequest->toString(&out); std::cout << out << std::endl;
|
||||
|
||||
|
||||
request = "alarm,timeStamp,power.value";
|
||||
std::cout << std::endl << String("request") <<std::endl << request <<std::endl;
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
assert(pvRequest.get());
|
||||
out.clear(); pvRequest->toString(&out); std::cout << out << std::endl;
|
||||
|
||||
request = "record[process=true]field(alarm,timeStamp,power.value)";
|
||||
std::cout << std::endl << String("request") <<std::endl << request <<std::endl;
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
assert(pvRequest.get());
|
||||
out.clear(); pvRequest->toString(&out); std::cout << out << std::endl;
|
||||
|
||||
request = "record[process=true]field(alarm,timeStamp[algorithm=onChange,causeMonitor=false],power{value,alarm})";
|
||||
std::cout << String("request") <<std::endl << request <<std::endl;
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
assert(pvRequest.get());
|
||||
out.clear(); pvRequest->toString(&out); std::cout << out << std::endl;
|
||||
|
||||
request = "record[process=true,xxx=yyy]field(alarm,timeStamp[shareData=true],power.value)";
|
||||
std::cout << String("request") <<std::endl << request <<std::endl;
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
assert(pvRequest.get());
|
||||
out.clear(); pvRequest->toString(&out); std::cout << out << std::endl;
|
||||
|
||||
request = String("record[process=true,xxx=yyy]")
|
||||
+ "putField(power.value)"
|
||||
+ "getField(alarm,timeStamp,power{value,alarm},"
|
||||
+ "current{value,alarm},voltage{value,alarm})";
|
||||
std::cout << String("request") <<std::endl << request <<std::endl;
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
assert(pvRequest.get());
|
||||
out.clear(); pvRequest->toString(&out); std::cout << out << std::endl;
|
||||
|
||||
request = String("field(alarm,timeStamp,supply{")
|
||||
+ "0{voltage.value,current.value,power.value},"
|
||||
+ "1{voltage.value,current.value,power.value}"
|
||||
+ "})";
|
||||
std::cout << String("request") <<std::endl << request <<std::endl;
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
assert(pvRequest.get());
|
||||
out.clear(); pvRequest->toString(&out); std::cout << out << std::endl;
|
||||
|
||||
request = String("record[process=true,xxx=yyy]")
|
||||
+ "putField(power.value)"
|
||||
+ "getField(alarm,timeStamp,power{value,alarm},"
|
||||
+ "current{value,alarm},voltage{value,alarm},"
|
||||
+ "ps0{alarm,timeStamp,power{value,alarm},current{value,alarm},voltage{value,alarm}},"
|
||||
+ "ps1{alarm,timeStamp,power{value,alarm},current{value,alarm},voltage{value,alarm}}"
|
||||
+ ")";
|
||||
std::cout << String("request") <<std::endl << request <<std::endl;
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
assert(pvRequest.get());
|
||||
out.clear(); pvRequest->toString(&out); std::cout << out << std::endl;
|
||||
|
||||
request = "a{b{c{d}}}";
|
||||
std::cout << String("request") <<std::endl << request <<std::endl;
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
assert(pvRequest.get());
|
||||
out.clear(); pvRequest->toString(&out); std::cout << out << std::endl;
|
||||
|
||||
request = "record[process=true,xxx=yyy]field(alarm,timeStamp[shareData=true],power.value";
|
||||
std::cout << String("request") <<std::endl << request <<std::endl;
|
||||
std::cout << std::endl << "Error Expected for next call!!" << std::endl;
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
assert(pvRequest.get()==NULL);
|
||||
std::cout << "reason " << createRequest->getMessage() << std::endl;
|
||||
request = String("record[process=true,xxx=yyy]")
|
||||
+ "putField(power.value)"
|
||||
+ "getField(alarm,timeStamp,power{value,alarm},"
|
||||
+ "current{value,alarm},voltage{value,alarm},"
|
||||
+ "ps0{alarm,timeStamp,power{value,alarm},current{value,alarm},voltage{value,alarm}},"
|
||||
+ "ps1{alarm,timeStamp,power{value,alarm},current{value,alarm},voltage{value,alarm}"
|
||||
+ ")";
|
||||
std::cout << String("request") <<std::endl << request <<std::endl;
|
||||
std::cout << std::endl << "Error Expected for next call!!" << std::endl;
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
assert(pvRequest.get()==NULL);
|
||||
std::cout << "reason " << createRequest->getMessage() << std::endl;
|
||||
request = "record[process=true,power.value";
|
||||
std::cout << String("request") <<std::endl << request <<std::endl;
|
||||
std::cout << std::endl << "Error Expected for next call!!" << std::endl;
|
||||
pvRequest = createRequest->createRequest(request);
|
||||
assert(pvRequest.get()==NULL);
|
||||
std::cout << "reason " << createRequest->getMessage() << std::endl;
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
testCreateRequest();
|
||||
|
||||
//std::cout << "-----------------------------------------------------------------------" << std::endl;
|
||||
//epicsExitCallAtExits();
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -43,9 +43,9 @@ std::string ChannelAccessIFTest::TEST_ARRAY_CHANNEL_NAME = "testArray1";
|
||||
int ChannelAccessIFTest::runAllTest() {
|
||||
|
||||
#ifdef ENABLE_STRESS_TESTS
|
||||
testPlan(158);
|
||||
testPlan(159);
|
||||
#else
|
||||
testPlan(152);
|
||||
testPlan(154);
|
||||
#endif
|
||||
|
||||
test_implementation();
|
||||
@@ -673,6 +673,13 @@ void ChannelAccessIFTest::test_channelPutNoProcess() {
|
||||
return;
|
||||
}
|
||||
|
||||
// first do a get to get pvStrcuture
|
||||
bool succStatus = channelPutReq->syncGet(getTimeoutSec());
|
||||
if (!succStatus) {
|
||||
testFail("%s: sync get failed ", CURRENT_FUNCTION);
|
||||
return;
|
||||
}
|
||||
|
||||
std::tr1::shared_ptr<PVDouble> value = channelPutReq->getPVStructure()->getDoubleField("value");
|
||||
if (!value.get()) {
|
||||
testFail("%s: getting double value field failed ", CURRENT_FUNCTION);
|
||||
@@ -684,7 +691,7 @@ void ChannelAccessIFTest::test_channelPutNoProcess() {
|
||||
value->put(initVal);
|
||||
channelPutReq->getBitSet()->set(value->getFieldOffset());
|
||||
|
||||
bool succStatus = channelPutReq->syncPut(false, getTimeoutSec());
|
||||
/*bool*/ succStatus = channelPutReq->syncPut(false, getTimeoutSec());
|
||||
if (!succStatus) {
|
||||
testFail("%s: sync put failed ", CURRENT_FUNCTION);
|
||||
return;
|
||||
@@ -805,6 +812,13 @@ void ChannelAccessIFTest::test_channelPutIntProcessInternal(Channel::shared_poin
|
||||
return;
|
||||
}
|
||||
|
||||
// first do a get to get pvStructure
|
||||
bool succStatus = channelPutReq->syncGet(getTimeoutSec());
|
||||
if (!succStatus) {
|
||||
testFail("%s: sync get failed ", testMethodName.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
std::tr1::shared_ptr<PVInt> value = channelPutReq->getPVStructure()->getIntField("value");
|
||||
if (!value.get()) {
|
||||
testFail("%s: getting int value field failed ", testMethodName.c_str());
|
||||
@@ -816,7 +830,7 @@ void ChannelAccessIFTest::test_channelPutIntProcessInternal(Channel::shared_poin
|
||||
value->put(initVal);
|
||||
channelPutReq->getBitSet()->set(value->getFieldOffset());
|
||||
|
||||
bool succStatus = channelPutReq->syncPut(false, getTimeoutSec());
|
||||
/*bool*/ succStatus = channelPutReq->syncPut(false, getTimeoutSec());
|
||||
if (!succStatus) {
|
||||
testFail("%s: sync put failed ", testMethodName.c_str());
|
||||
return;
|
||||
@@ -1185,6 +1199,20 @@ void ChannelAccessIFTest::test_channelPutGetNoProcess_putGet() {
|
||||
return;
|
||||
}
|
||||
|
||||
// first get a pvStructure
|
||||
bool succStatus = channelPutGetReq->syncGetPut(getTimeoutSec());
|
||||
if (!succStatus) {
|
||||
testFail("%s: syncGetPut failed ", CURRENT_FUNCTION);
|
||||
return;
|
||||
}
|
||||
|
||||
// first get a pvStructure
|
||||
succStatus = channelPutGetReq->syncGetGet(getTimeoutSec());
|
||||
if (!succStatus) {
|
||||
testFail("%s: syncGetGet failed ", CURRENT_FUNCTION);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
std::tr1::shared_ptr<PVDouble> putValue = channelPutGetReq->getPVPutStructure()->getDoubleField("value");
|
||||
if (!putValue.get()) {
|
||||
@@ -1201,7 +1229,7 @@ void ChannelAccessIFTest::test_channelPutGetNoProcess_putGet() {
|
||||
return;
|
||||
}
|
||||
|
||||
bool succStatus = channelPutGetReq->syncPutGet(false, getTimeoutSec());
|
||||
/*bool*/ succStatus = channelPutGetReq->syncPutGet(false, getTimeoutSec());
|
||||
if (!succStatus) {
|
||||
testFail("%s: syncPutGet failed ", CURRENT_FUNCTION);
|
||||
return;
|
||||
@@ -1250,6 +1278,20 @@ void ChannelAccessIFTest::test_channelPutGetNoProcess_getPut() {
|
||||
return;
|
||||
}
|
||||
|
||||
// first get a pvStructure
|
||||
bool succStatus = channelPutGetReq->syncGetPut(getTimeoutSec());
|
||||
if (!succStatus) {
|
||||
testFail("%s: syncGetPut failed ", CURRENT_FUNCTION);
|
||||
return;
|
||||
}
|
||||
|
||||
// first get a pvStructure
|
||||
succStatus = channelPutGetReq->syncGetGet(getTimeoutSec());
|
||||
if (!succStatus) {
|
||||
testFail("%s: syncGetGet failed ", CURRENT_FUNCTION);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
std::tr1::shared_ptr<PVDouble> putValue = channelPutGetReq->getPVPutStructure()->getDoubleField("value");
|
||||
if (!putValue.get()) {
|
||||
@@ -1268,7 +1310,7 @@ void ChannelAccessIFTest::test_channelPutGetNoProcess_getPut() {
|
||||
|
||||
testDiag("%s: first put the initial pvPutStructure into the record", CURRENT_FUNCTION);
|
||||
|
||||
bool succStatus = channelPutGetReq->syncPutGet(false, getTimeoutSec());
|
||||
/*bool*/ succStatus = channelPutGetReq->syncPutGet(false, getTimeoutSec());
|
||||
if (!succStatus) {
|
||||
testFail("%s: syncPutGet failed ", CURRENT_FUNCTION);
|
||||
return;
|
||||
@@ -1313,6 +1355,20 @@ void ChannelAccessIFTest::test_channelPutGetNoProcess_getGet() {
|
||||
return;
|
||||
}
|
||||
|
||||
// first get a pvStructure
|
||||
bool succStatus = channelPutGetReq->syncGetPut(getTimeoutSec());
|
||||
if (!succStatus) {
|
||||
testFail("%s: syncGetPut failed ", CURRENT_FUNCTION);
|
||||
return;
|
||||
}
|
||||
|
||||
// first get a pvStructure
|
||||
succStatus = channelPutGetReq->syncGetGet(getTimeoutSec());
|
||||
if (!succStatus) {
|
||||
testFail("%s: syncGetGet failed ", CURRENT_FUNCTION);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
std::tr1::shared_ptr<PVDouble> putValue = channelPutGetReq->getPVPutStructure()->getDoubleField("value");
|
||||
if (!putValue.get()) {
|
||||
@@ -1331,7 +1387,7 @@ void ChannelAccessIFTest::test_channelPutGetNoProcess_getGet() {
|
||||
|
||||
testDiag("%s: first put the initial pvPutStructure into the record", CURRENT_FUNCTION);
|
||||
|
||||
bool succStatus = channelPutGetReq->syncPutGet(false, getTimeoutSec());
|
||||
/*bool*/ succStatus = channelPutGetReq->syncPutGet(false, getTimeoutSec());
|
||||
if (!succStatus) {
|
||||
testFail("%s: syncPutGet failed ", CURRENT_FUNCTION);
|
||||
return;
|
||||
@@ -1375,8 +1431,23 @@ void ChannelAccessIFTest::test_channelPutGetNoProcess_destroy() {
|
||||
testFail("%s: creating a channel putget failed ", CURRENT_FUNCTION);
|
||||
return;
|
||||
}
|
||||
|
||||
// first get a pvStructure
|
||||
bool succStatus = channelPutGetReq->syncGetPut(getTimeoutSec());
|
||||
if (!succStatus) {
|
||||
testFail("%s: syncGetPut failed ", CURRENT_FUNCTION);
|
||||
return;
|
||||
}
|
||||
|
||||
// first get a pvStructure
|
||||
succStatus = channelPutGetReq->syncGetGet(getTimeoutSec());
|
||||
if (!succStatus) {
|
||||
testFail("%s: syncGetGet failed ", CURRENT_FUNCTION);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
bool succStatus = channelPutGetReq->syncPutGet(true, getTimeoutSec());
|
||||
/*bool*/ succStatus = channelPutGetReq->syncPutGet(true, getTimeoutSec());
|
||||
if (!succStatus) {
|
||||
testFail("%s: syncPutGet failed ", CURRENT_FUNCTION);
|
||||
return;
|
||||
@@ -1420,6 +1491,20 @@ void ChannelAccessIFTest::test_channelPutGetIntProcess() {
|
||||
return;
|
||||
}
|
||||
|
||||
// first get a pvStructure
|
||||
bool succStatus = channelPutGetReq->syncGetPut(getTimeoutSec());
|
||||
if (!succStatus) {
|
||||
testFail("%s: syncGetPut failed ", CURRENT_FUNCTION);
|
||||
return;
|
||||
}
|
||||
|
||||
// first get a pvStructure
|
||||
succStatus = channelPutGetReq->syncGetGet(getTimeoutSec());
|
||||
if (!succStatus) {
|
||||
testFail("%s: syncGetGet failed ", CURRENT_FUNCTION);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
std::tr1::shared_ptr<PVInt> putValue = channelPutGetReq->getPVPutStructure()->getIntField("value");
|
||||
if (!putValue.get()) {
|
||||
@@ -1443,7 +1528,7 @@ void ChannelAccessIFTest::test_channelPutGetIntProcess() {
|
||||
|
||||
TimeStamp timeStamp;
|
||||
|
||||
bool succStatus = channelPutGetReq->syncGetGet(getTimeoutSec());
|
||||
/*bool*/ succStatus = channelPutGetReq->syncGetGet(getTimeoutSec());
|
||||
if (!succStatus) {
|
||||
testFail("%s: syncGetGet failed ", CURRENT_FUNCTION);
|
||||
return;
|
||||
@@ -1747,9 +1832,16 @@ void ChannelAccessIFTest::test_channelArray() {
|
||||
return;
|
||||
}
|
||||
|
||||
// first get to get pvArray
|
||||
bool succStatus = arrayReq->syncGet(false, 0, 0, getTimeoutSec());
|
||||
if (!succStatus) {
|
||||
testFail("%s: an array syncGet failed (0) ", CURRENT_FUNCTION);
|
||||
return;
|
||||
}
|
||||
|
||||
PVDoubleArrayPtr array = static_pointer_cast<PVDoubleArray>(arrayReq->getArray());
|
||||
|
||||
bool succStatus = arrayReq->syncGet(false, 0, 2, getTimeoutSec());
|
||||
/*bool*/ succStatus = arrayReq->syncGet(false, 0, 2, getTimeoutSec());
|
||||
if (!succStatus) {
|
||||
testFail("%s: an array syncGet failed (1) ", CURRENT_FUNCTION);
|
||||
return;
|
||||
@@ -1766,13 +1858,13 @@ void ChannelAccessIFTest::test_channelArray() {
|
||||
|
||||
array->replace(freeze(newdata));
|
||||
|
||||
succStatus = arrayReq->syncPut(false, 0, -1, getTimeoutSec());
|
||||
succStatus = arrayReq->syncPut(false, 0, 0, getTimeoutSec());
|
||||
if (!succStatus) {
|
||||
testFail("%s: an array syncPut failed (2) ", CURRENT_FUNCTION);
|
||||
return;
|
||||
}
|
||||
|
||||
succStatus = arrayReq->syncGet(false, 0, -1, getTimeoutSec());
|
||||
succStatus = arrayReq->syncGet(false, 0, 0, getTimeoutSec());
|
||||
if (!succStatus) {
|
||||
testFail("%s: an array syncGet failed (3) ", CURRENT_FUNCTION);
|
||||
return;
|
||||
@@ -1812,13 +1904,13 @@ void ChannelAccessIFTest::test_channelArray() {
|
||||
//testOk(data1[2] == 2.2 , "%s: check 2: %f", CURRENT_FUNCTION, data1[2]);
|
||||
|
||||
|
||||
succStatus = arrayReq->syncSetLength(false, 3, -1, getTimeoutSec());
|
||||
succStatus = arrayReq->syncSetLength(false, 3, 0, getTimeoutSec());
|
||||
if (!succStatus) {
|
||||
testFail("%s: an array setLength failed ", CURRENT_FUNCTION);
|
||||
return;
|
||||
}
|
||||
|
||||
succStatus = arrayReq->syncGet(false, 0, -1, getTimeoutSec());
|
||||
succStatus = arrayReq->syncGet(false, 0, 0, getTimeoutSec());
|
||||
if (!succStatus) {
|
||||
testFail("%s: an array syncGet failed (7) ", CURRENT_FUNCTION);
|
||||
return;
|
||||
@@ -1833,14 +1925,15 @@ void ChannelAccessIFTest::test_channelArray() {
|
||||
testOk(data2[1] == 2.2 , "%s: 2.check 1: %f", CURRENT_FUNCTION, data2[1]);
|
||||
testOk(data2[2] == 3.3, "%s: 2.check 2: %f", CURRENT_FUNCTION, data2[2]);
|
||||
|
||||
size_t currentLength = 3;
|
||||
size_t newCap = 2;
|
||||
succStatus = arrayReq->syncSetLength(false, -1, newCap, getTimeoutSec());
|
||||
succStatus = arrayReq->syncSetLength(false, currentLength, newCap, getTimeoutSec());
|
||||
if (!succStatus) {
|
||||
testFail("%s: an array setLength failed (2) ", CURRENT_FUNCTION);
|
||||
return;
|
||||
}
|
||||
|
||||
succStatus = arrayReq->syncGet(false, 0, -1, getTimeoutSec());
|
||||
succStatus = arrayReq->syncGet(false, 0, 0, getTimeoutSec());
|
||||
if (!succStatus) {
|
||||
testFail("%s: an array syncGet failed (8) ", CURRENT_FUNCTION);
|
||||
return;
|
||||
@@ -1862,7 +1955,7 @@ void ChannelAccessIFTest::test_channelArray() {
|
||||
return;
|
||||
}
|
||||
|
||||
succStatus = arrayReq->syncGet(false, 0, -1, getTimeoutSec());
|
||||
succStatus = arrayReq->syncGet(false, 0, 0, getTimeoutSec());
|
||||
if (!succStatus) {
|
||||
testFail("%s: an array syncGet failed (9) ", CURRENT_FUNCTION);
|
||||
return;
|
||||
@@ -1892,6 +1985,21 @@ void ChannelAccessIFTest::test_channelArray() {
|
||||
}
|
||||
*/
|
||||
|
||||
// test setLength with capacity 0 (no change) and getLength
|
||||
size_t newLen = bigCapacity/2;
|
||||
succStatus = arrayReq->syncSetLength(false, newLen, bigCapacity, getTimeoutSec());
|
||||
if (!succStatus) {
|
||||
testFail("%s: an array setLength failed (4) ", CURRENT_FUNCTION);
|
||||
return;
|
||||
}
|
||||
succStatus = arrayReq->syncGetLength(false, getTimeoutSec());
|
||||
if (!succStatus) {
|
||||
testFail("%s: an array getLength failed", CURRENT_FUNCTION);
|
||||
return;
|
||||
}
|
||||
testOk(arrayReq->getLength() == newLen, "%s: retrieved length should be %zu", CURRENT_FUNCTION, newLen);
|
||||
testOk(arrayReq->getCapacity() == bigCapacity, "%s: retrieved capacity should be %zu", CURRENT_FUNCTION, bigCapacity);
|
||||
|
||||
|
||||
channel->destroy();
|
||||
}
|
||||
|
||||
@@ -10,25 +10,44 @@
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
|
||||
static StructureConstPtr resultStructure =
|
||||
getFieldCreate()->createFieldBuilder()->
|
||||
add("c", pvDouble)->
|
||||
createStructure();
|
||||
static Structure::const_shared_pointer resultStructure =
|
||||
getFieldCreate()->createFieldBuilder()->
|
||||
add("c", pvDouble)->
|
||||
createStructure();
|
||||
|
||||
class SumServiceImpl :
|
||||
public RPCService
|
||||
{
|
||||
PVStructure::shared_pointer request(PVStructure::shared_pointer const & args)
|
||||
PVStructure::shared_pointer request(PVStructure::shared_pointer const & pvArguments)
|
||||
throw (RPCRequestException)
|
||||
{
|
||||
PVString::shared_pointer fa = args->getSubField<PVString>("a");
|
||||
PVString::shared_pointer fb = args->getSubField<PVString>("b");
|
||||
if (!fa || !fb)
|
||||
throw RPCRequestException(Status::STATUSTYPE_ERROR, "'string a' and 'string b' fields required");
|
||||
|
||||
double a = atof(fa->get().c_str());
|
||||
double b = atof(fb->get().c_str());
|
||||
// NTURI support
|
||||
PVStructure::shared_pointer args(
|
||||
(pvArguments->getStructure()->getID() == "uri:ev4:nt/2012/pwd:NTURI") ?
|
||||
pvArguments->getStructureField("query") :
|
||||
pvArguments
|
||||
);
|
||||
|
||||
// get fields and check their existence
|
||||
PVScalar::shared_pointer af = args->getSubField<PVScalar>("a");
|
||||
PVScalar::shared_pointer bf = args->getSubField<PVScalar>("b");
|
||||
if (!af || !bf)
|
||||
throw RPCRequestException(Status::STATUSTYPE_ERROR, "scalar 'a' and 'b' fields are required");
|
||||
|
||||
// get the numbers (and convert if neccessary)
|
||||
double a, b;
|
||||
try
|
||||
{
|
||||
a = af->getAs<double>();
|
||||
b = bf->getAs<double>();
|
||||
}
|
||||
catch (std::exception &e)
|
||||
{
|
||||
throw RPCRequestException(Status::STATUSTYPE_ERROR,
|
||||
std::string("failed to convert arguments to double: ") + e.what());
|
||||
}
|
||||
|
||||
// create return structure and set data
|
||||
PVStructure::shared_pointer result = getPVDataCreate()->createPVStructure(resultStructure);
|
||||
result->getSubField<PVDouble>("c")->put(a+b);
|
||||
return result;
|
||||
|
||||
@@ -321,7 +321,9 @@ class SyncChannelGetRequesterImpl : public ChannelGetRequester, public SyncBaseR
|
||||
|
||||
bool syncGet(bool lastRequest, long timeOut) {
|
||||
resetEvent();
|
||||
m_channelGet->get(lastRequest);
|
||||
if (lastRequest)
|
||||
m_channelGet->lastRequest();
|
||||
m_channelGet->get();
|
||||
return waitUntilGetDone(timeOut);
|
||||
}
|
||||
|
||||
@@ -366,8 +368,7 @@ class SyncChannelGetRequesterImpl : public ChannelGetRequester, public SyncBaseR
|
||||
|
||||
virtual void channelGetConnect(
|
||||
const epics::pvData::Status& status,ChannelGet::shared_pointer const & channelGet,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvStructure,
|
||||
epics::pvData::BitSet::shared_pointer const & bitSet)
|
||||
epics::pvData::Structure::const_shared_pointer const & /*structure*/)
|
||||
{
|
||||
if (m_debug)
|
||||
std::cout << getRequesterName() << "." << "channelGetConnect(" << status.toString() << ")" << std::endl;
|
||||
@@ -377,10 +378,8 @@ class SyncChannelGetRequesterImpl : public ChannelGetRequester, public SyncBaseR
|
||||
{
|
||||
Lock lock(m_pointerMutex);
|
||||
m_channelGet = channelGet;
|
||||
m_pvStructure = pvStructure;
|
||||
m_bitSet = bitSet;
|
||||
}
|
||||
channelGet->get(false);
|
||||
channelGet->get();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -389,11 +388,21 @@ class SyncChannelGetRequesterImpl : public ChannelGetRequester, public SyncBaseR
|
||||
}
|
||||
|
||||
|
||||
virtual void getDone(const epics::pvData::Status& status)
|
||||
virtual void getDone(const epics::pvData::Status& status,
|
||||
ChannelGet::shared_pointer const & channelGet,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvStructure,
|
||||
epics::pvData::BitSet::shared_pointer const & bitSet)
|
||||
{
|
||||
if (m_debug)
|
||||
std::cout << getRequesterName() << "." << "getDone(" << status.toString() << ")" << std::endl;
|
||||
|
||||
{
|
||||
Lock lock(m_pointerMutex);
|
||||
m_channelGet = channelGet;
|
||||
m_pvStructure = pvStructure;
|
||||
m_bitSet = bitSet;
|
||||
}
|
||||
|
||||
setGetStatus(status.isSuccess());
|
||||
signalEvent();
|
||||
}
|
||||
@@ -419,6 +428,7 @@ class SyncChannelPutRequesterImpl : public ChannelPutRequester, public SyncBaseR
|
||||
SyncBaseRequester(debug), m_channelName(channelName) {}
|
||||
|
||||
|
||||
// requires to do a get first
|
||||
bool syncPut(bool lastRequest, long timeOut)
|
||||
{
|
||||
|
||||
@@ -427,7 +437,9 @@ class SyncChannelPutRequesterImpl : public ChannelPutRequester, public SyncBaseR
|
||||
}
|
||||
|
||||
resetEvent();
|
||||
m_channelPut->put(lastRequest);
|
||||
if (lastRequest)
|
||||
m_channelPut->lastRequest();
|
||||
m_channelPut->put(getPVStructure(), getBitSet());
|
||||
return waitUntilPutDone(timeOut);
|
||||
}
|
||||
|
||||
@@ -480,8 +492,7 @@ class SyncChannelPutRequesterImpl : public ChannelPutRequester, public SyncBaseR
|
||||
|
||||
virtual void channelPutConnect(const epics::pvData::Status& status,
|
||||
ChannelPut::shared_pointer const & channelPut,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvStructure,
|
||||
epics::pvData::BitSet::shared_pointer const & bitSet)
|
||||
epics::pvData::Structure::const_shared_pointer const & /*structure*/)
|
||||
{
|
||||
|
||||
if (m_debug)
|
||||
@@ -493,8 +504,6 @@ class SyncChannelPutRequesterImpl : public ChannelPutRequester, public SyncBaseR
|
||||
{
|
||||
Lock lock(m_pointerMutex);
|
||||
m_channelPut = channelPut;
|
||||
m_pvStructure = pvStructure;
|
||||
m_bitSet = bitSet;
|
||||
}
|
||||
setConnectedStatus(true);
|
||||
}
|
||||
@@ -507,21 +516,37 @@ class SyncChannelPutRequesterImpl : public ChannelPutRequester, public SyncBaseR
|
||||
}
|
||||
|
||||
|
||||
virtual void getDone(const epics::pvData::Status& status)
|
||||
virtual void getDone(const epics::pvData::Status& status,
|
||||
ChannelPut::shared_pointer const & channelPut,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvStructure,
|
||||
epics::pvData::BitSet::shared_pointer const & bitSet)
|
||||
{
|
||||
if (m_debug)
|
||||
std::cout << getRequesterName() << "." << "getDone(" << status.toString() << ")" << std::endl;
|
||||
|
||||
{
|
||||
Lock lock(m_pointerMutex);
|
||||
m_channelPut = channelPut;
|
||||
m_pvStructure = pvStructure;
|
||||
m_bitSet = bitSet;
|
||||
}
|
||||
|
||||
setGetStatus(status.isSuccess());
|
||||
signalEvent();
|
||||
}
|
||||
|
||||
|
||||
virtual void putDone(const epics::pvData::Status& status)
|
||||
virtual void putDone(const epics::pvData::Status& status,
|
||||
ChannelPut::shared_pointer const & channelPut)
|
||||
{
|
||||
if (m_debug)
|
||||
std::cout << getRequesterName() << "." << "putDone(" << status.toString() << ")" << std::endl;
|
||||
|
||||
{
|
||||
Lock lock(m_pointerMutex);
|
||||
m_channelPut = channelPut;
|
||||
}
|
||||
|
||||
setPutStatus(status.isSuccess());
|
||||
signalEvent();
|
||||
}
|
||||
@@ -609,7 +634,9 @@ class SyncChannelProcessRequesterImpl : public ChannelProcessRequester, public S
|
||||
}
|
||||
|
||||
resetEvent();
|
||||
m_channelProcess->process(lastRequest);
|
||||
if (lastRequest)
|
||||
m_channelProcess->lastRequest();
|
||||
m_channelProcess->process();
|
||||
return waitUntilProcessDone(timeOut);
|
||||
}
|
||||
|
||||
@@ -657,11 +684,17 @@ class SyncChannelProcessRequesterImpl : public ChannelProcessRequester, public S
|
||||
}
|
||||
|
||||
|
||||
virtual void processDone(const epics::pvData::Status& status)
|
||||
virtual void processDone(const epics::pvData::Status& status,
|
||||
ChannelProcess::shared_pointer const & channelProcess)
|
||||
{
|
||||
if (m_debug)
|
||||
std::cout << getRequesterName() << "." << "processDone(" << status.toString() << ")" << std::endl;
|
||||
|
||||
{
|
||||
Lock lock(m_pointerMutex);
|
||||
m_channelProcess = channelProcess;
|
||||
}
|
||||
|
||||
setProcessStatus(status.isSuccess());
|
||||
signalEvent();
|
||||
}
|
||||
@@ -699,6 +732,7 @@ class SyncChannelPutGetRequesterImpl : public ChannelPutGetRequester, public Syn
|
||||
}
|
||||
|
||||
|
||||
// requires getput is called first
|
||||
bool syncPutGet(bool lastRequest, double timeOut) {
|
||||
|
||||
if(!getConnectedStatus()) {
|
||||
@@ -706,7 +740,9 @@ class SyncChannelPutGetRequesterImpl : public ChannelPutGetRequester, public Syn
|
||||
}
|
||||
|
||||
resetEvent();
|
||||
m_channelPutGet->putGet(lastRequest);
|
||||
if (lastRequest)
|
||||
m_channelPutGet->lastRequest();
|
||||
m_channelPutGet->putGet(getPVPutStructure(), getPVPutBitSet());
|
||||
return waitUntilPutGetDone(timeOut);
|
||||
}
|
||||
|
||||
@@ -729,6 +765,12 @@ class SyncChannelPutGetRequesterImpl : public ChannelPutGetRequester, public Syn
|
||||
return m_putData;
|
||||
}
|
||||
|
||||
BitSet::shared_pointer getPVPutBitSet()
|
||||
{
|
||||
Lock lock(m_pointerMutex);
|
||||
return m_putBitSet;
|
||||
}
|
||||
|
||||
|
||||
PVStructure::shared_pointer getPVGetStructure()
|
||||
{
|
||||
@@ -736,6 +778,11 @@ class SyncChannelPutGetRequesterImpl : public ChannelPutGetRequester, public Syn
|
||||
return m_getData;
|
||||
}
|
||||
|
||||
BitSet::shared_pointer getPVGetBitSet()
|
||||
{
|
||||
Lock lock(m_pointerMutex);
|
||||
return m_getBitSet;
|
||||
}
|
||||
|
||||
ChannelPutGet::shared_pointer getChannelPutGet()
|
||||
{
|
||||
@@ -760,8 +807,8 @@ class SyncChannelPutGetRequesterImpl : public ChannelPutGetRequester, public Syn
|
||||
|
||||
virtual void channelPutGetConnect(const epics::pvData::Status& status,
|
||||
ChannelPutGet::shared_pointer const & channelPutGet,
|
||||
epics::pvData::PVStructure::shared_pointer const & putData,
|
||||
epics::pvData::PVStructure::shared_pointer const & getData)
|
||||
epics::pvData::Structure::const_shared_pointer const & /*putStructure*/,
|
||||
epics::pvData::Structure::const_shared_pointer const & /*getStructure*/)
|
||||
{
|
||||
if (m_debug)
|
||||
std::cout << getRequesterName() << "." << "channelGetPutConnect("
|
||||
@@ -772,8 +819,8 @@ class SyncChannelPutGetRequesterImpl : public ChannelPutGetRequester, public Syn
|
||||
{
|
||||
Lock lock(m_pointerMutex);
|
||||
m_channelPutGet = channelPutGet;
|
||||
m_putData = putData;
|
||||
m_getData = getData;
|
||||
//m_putStructure = putStructure;
|
||||
//m_getStructure = getStructure;
|
||||
}
|
||||
setConnectedStatus(true);
|
||||
}
|
||||
@@ -786,13 +833,21 @@ class SyncChannelPutGetRequesterImpl : public ChannelPutGetRequester, public Syn
|
||||
}
|
||||
|
||||
|
||||
virtual void getGetDone(const epics::pvData::Status& status)
|
||||
virtual void getGetDone(const epics::pvData::Status& status,
|
||||
ChannelPutGet::shared_pointer const & channelPutGet,
|
||||
epics::pvData::PVStructure::shared_pointer const & getData,
|
||||
epics::pvData::BitSet::shared_pointer const & getBitSet)
|
||||
{
|
||||
if (m_debug)
|
||||
std::cout << getRequesterName() << "." << "getGetDone(" << status.toString() << ")" << std::endl;
|
||||
|
||||
{
|
||||
Lock lock(m_pointerMutex);
|
||||
|
||||
m_channelPutGet = channelPutGet;
|
||||
m_getData = getData;
|
||||
m_getBitSet = getBitSet;
|
||||
|
||||
m_getGetStatus = status.isSuccess();
|
||||
}
|
||||
|
||||
@@ -800,13 +855,21 @@ class SyncChannelPutGetRequesterImpl : public ChannelPutGetRequester, public Syn
|
||||
}
|
||||
|
||||
|
||||
virtual void getPutDone(const epics::pvData::Status& status)
|
||||
virtual void getPutDone(const epics::pvData::Status& status,
|
||||
ChannelPutGet::shared_pointer const & channelPutGet,
|
||||
epics::pvData::PVStructure::shared_pointer const & putData,
|
||||
epics::pvData::BitSet::shared_pointer const & putBitSet)
|
||||
{
|
||||
if (m_debug)
|
||||
std::cout << getRequesterName() << "." << "getPutDone(" << status.toString() << ")" << std::endl;
|
||||
|
||||
{
|
||||
Lock lock(m_pointerMutex);
|
||||
|
||||
m_channelPutGet = channelPutGet;
|
||||
m_putData = putData;
|
||||
m_putBitSet = putBitSet;
|
||||
|
||||
m_getPutStatus = status.isSuccess();
|
||||
}
|
||||
|
||||
@@ -814,13 +877,21 @@ class SyncChannelPutGetRequesterImpl : public ChannelPutGetRequester, public Syn
|
||||
}
|
||||
|
||||
|
||||
virtual void putGetDone(const epics::pvData::Status& status)
|
||||
virtual void putGetDone(const epics::pvData::Status& status,
|
||||
ChannelPutGet::shared_pointer const & channelPutGet,
|
||||
epics::pvData::PVStructure::shared_pointer const & getData,
|
||||
epics::pvData::BitSet::shared_pointer const & getBitSet)
|
||||
{
|
||||
if (m_debug)
|
||||
std::cout << getRequesterName() << "." << "putGetDone(" << status.toString() << ")" << std::endl;
|
||||
|
||||
{
|
||||
Lock lock(m_pointerMutex);
|
||||
|
||||
m_channelPutGet = channelPutGet;
|
||||
m_getData = getData;
|
||||
m_getBitSet = getBitSet;
|
||||
|
||||
m_putGetStatus = status.isSuccess();
|
||||
}
|
||||
|
||||
@@ -873,7 +944,9 @@ class SyncChannelPutGetRequesterImpl : public ChannelPutGetRequester, public Syn
|
||||
Mutex m_pointerMutex;
|
||||
ChannelPutGet::shared_pointer m_channelPutGet;
|
||||
epics::pvData::PVStructure::shared_pointer m_putData;
|
||||
epics::pvData::BitSet::shared_pointer m_putBitSet;
|
||||
epics::pvData::PVStructure::shared_pointer m_getData;
|
||||
epics::pvData::BitSet::shared_pointer m_getBitSet;
|
||||
};
|
||||
|
||||
|
||||
@@ -896,7 +969,9 @@ class SyncChannelRPCRequesterImpl : public ChannelRPCRequester, public SyncBaseR
|
||||
}
|
||||
|
||||
resetEvent();
|
||||
m_channelRPC->request(pvArguments, lastRequest);
|
||||
if (lastRequest)
|
||||
m_channelRPC->lastRequest();
|
||||
m_channelRPC->request(pvArguments);
|
||||
return waitUntilRPC(timeOut);
|
||||
}
|
||||
|
||||
@@ -955,6 +1030,7 @@ class SyncChannelRPCRequesterImpl : public ChannelRPCRequester, public SyncBaseR
|
||||
|
||||
|
||||
virtual void requestDone (const epics::pvData::Status &status,
|
||||
ChannelRPC::shared_pointer const & channelRPC,
|
||||
epics::pvData::PVStructure::shared_pointer const &pvResponse)
|
||||
{
|
||||
|
||||
@@ -962,14 +1038,10 @@ class SyncChannelRPCRequesterImpl : public ChannelRPCRequester, public SyncBaseR
|
||||
std::cout << getRequesterName() << "." << "requestDone("
|
||||
<< status.toString() << ")" << std::endl;
|
||||
|
||||
if (status.isSuccess())
|
||||
{
|
||||
Lock lock(m_pointerMutex);
|
||||
m_channelRPC = channelRPC;
|
||||
m_lastResponse = pvResponse;
|
||||
}
|
||||
|
||||
{
|
||||
Lock lock(m_pointerMutex);
|
||||
m_done = status.isSuccess();
|
||||
}
|
||||
|
||||
@@ -1156,7 +1228,8 @@ class SyncChannelArrayRequesterImpl : public ChannelArrayRequester, public SyncB
|
||||
m_lengthArrayStatus(false) {}
|
||||
|
||||
|
||||
bool syncPut(bool lastRequest, int offset, int count, long timeOut)
|
||||
// note you need to do a get first
|
||||
bool syncPut(bool lastRequest, size_t offset, size_t count, long timeOut)
|
||||
{
|
||||
|
||||
if (!getConnectedStatus()) {
|
||||
@@ -1164,12 +1237,15 @@ class SyncChannelArrayRequesterImpl : public ChannelArrayRequester, public SyncB
|
||||
}
|
||||
|
||||
resetEvent();
|
||||
m_channelArray->putArray(lastRequest, offset, count);
|
||||
if (lastRequest)
|
||||
m_channelArray->lastRequest();
|
||||
// TODO stride !!!
|
||||
m_channelArray->putArray(getArray(), offset, count, 1);
|
||||
return waitUntilPutArrayDone(timeOut);
|
||||
}
|
||||
|
||||
|
||||
bool syncGet(bool lastRequest, int offset, int count, long timeOut)
|
||||
bool syncGet(bool lastRequest, size_t offset, size_t count, long timeOut)
|
||||
{
|
||||
|
||||
if (!getConnectedStatus()) {
|
||||
@@ -1177,12 +1253,15 @@ class SyncChannelArrayRequesterImpl : public ChannelArrayRequester, public SyncB
|
||||
}
|
||||
|
||||
resetEvent();
|
||||
m_channelArray->getArray(lastRequest, offset, count);
|
||||
if (lastRequest)
|
||||
m_channelArray->lastRequest();
|
||||
// TODO stride !!!
|
||||
m_channelArray->getArray(offset, count, 1);
|
||||
return waitUntilGetArrayDone(timeOut);
|
||||
}
|
||||
|
||||
|
||||
bool syncSetLength(bool lastRequest, int length, int capacity, long timeOut)
|
||||
bool syncSetLength(bool lastRequest, size_t length, size_t capacity, long timeOut)
|
||||
{
|
||||
|
||||
if (!getConnectedStatus()) {
|
||||
@@ -1190,7 +1269,23 @@ class SyncChannelArrayRequesterImpl : public ChannelArrayRequester, public SyncB
|
||||
}
|
||||
|
||||
resetEvent();
|
||||
m_channelArray->setLength(lastRequest, length, capacity);
|
||||
if (lastRequest)
|
||||
m_channelArray->lastRequest();
|
||||
m_channelArray->setLength(length, capacity);
|
||||
return waitUntilSetLengthDone(timeOut);
|
||||
}
|
||||
|
||||
bool syncGetLength(bool lastRequest, long timeOut)
|
||||
{
|
||||
|
||||
if (!getConnectedStatus()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
resetEvent();
|
||||
if (lastRequest)
|
||||
m_channelArray->lastRequest();
|
||||
m_channelArray->getLength();
|
||||
return waitUntilSetLengthDone(timeOut);
|
||||
}
|
||||
|
||||
@@ -1225,7 +1320,7 @@ class SyncChannelArrayRequesterImpl : public ChannelArrayRequester, public SyncB
|
||||
|
||||
virtual void channelArrayConnect(const epics::pvData::Status& status,
|
||||
ChannelArray::shared_pointer const & channelArray,
|
||||
epics::pvData::PVArray::shared_pointer const & pvArray)
|
||||
epics::pvData::Array::const_shared_pointer const & /*array*/)
|
||||
{
|
||||
if (m_debug)
|
||||
std::cout << getRequesterName() << ".channelArrayConnect(" << status.toString() << ")" << std::endl;
|
||||
@@ -1234,7 +1329,6 @@ class SyncChannelArrayRequesterImpl : public ChannelArrayRequester, public SyncB
|
||||
{
|
||||
Lock lock(m_pointerMutex);
|
||||
m_channelArray = channelArray;
|
||||
m_pvArray = pvArray;
|
||||
}
|
||||
|
||||
setConnectedStatus(true);
|
||||
@@ -1248,38 +1342,78 @@ class SyncChannelArrayRequesterImpl : public ChannelArrayRequester, public SyncB
|
||||
}
|
||||
|
||||
|
||||
virtual void getArrayDone(const epics::pvData::Status& status)
|
||||
virtual void getArrayDone(const epics::pvData::Status& status,
|
||||
ChannelArray::shared_pointer const & channelArray,
|
||||
epics::pvData::PVArray::shared_pointer const & pvArray)
|
||||
{
|
||||
if (m_debug)
|
||||
std::cout << getRequesterName() << ".getArrayDone(" << status.toString() << ")" << std::endl;
|
||||
|
||||
Lock lock(m_pointerMutex);
|
||||
|
||||
m_channelArray = channelArray;
|
||||
m_pvArray = pvArray;
|
||||
|
||||
m_getArrayStatus = status.isSuccess();
|
||||
signalEvent();
|
||||
}
|
||||
|
||||
|
||||
virtual void putArrayDone(const epics::pvData::Status& status)
|
||||
virtual void putArrayDone(const epics::pvData::Status& status,
|
||||
ChannelArray::shared_pointer const & channelArray)
|
||||
{
|
||||
if (m_debug)
|
||||
std::cout << getRequesterName() << ".putArrayDone(" << status.toString() << ")" << std::endl;
|
||||
|
||||
Lock lock(m_pointerMutex);
|
||||
|
||||
m_channelArray = channelArray;
|
||||
|
||||
m_putArrayStatus = status.isSuccess();
|
||||
signalEvent();
|
||||
}
|
||||
|
||||
|
||||
virtual void setLengthDone(const epics::pvData::Status& status)
|
||||
virtual void setLengthDone(const epics::pvData::Status& status,
|
||||
ChannelArray::shared_pointer const & channelArray)
|
||||
{
|
||||
if (m_debug)
|
||||
std::cout << getRequesterName() << ".setLengthDone(" << status.toString() << ")" << std::endl;
|
||||
|
||||
Lock lock(m_pointerMutex);
|
||||
|
||||
m_channelArray = channelArray;
|
||||
|
||||
m_lengthArrayStatus = status.isSuccess();
|
||||
signalEvent();
|
||||
}
|
||||
|
||||
virtual void getLengthDone(const epics::pvData::Status& status,
|
||||
ChannelArray::shared_pointer const & channelArray,
|
||||
size_t length, size_t capacity)
|
||||
{
|
||||
if (m_debug)
|
||||
std::cout << getRequesterName() << ".getLengthDone(" << status.toString() << ")" << std::endl;
|
||||
|
||||
Lock lock(m_pointerMutex);
|
||||
|
||||
m_channelArray = channelArray;
|
||||
m_length = length;
|
||||
m_capacity = capacity;
|
||||
|
||||
m_lengthArrayStatus = status.isSuccess();
|
||||
signalEvent();
|
||||
}
|
||||
|
||||
size_t getLength()
|
||||
{
|
||||
return m_length;
|
||||
}
|
||||
|
||||
size_t getCapacity()
|
||||
{
|
||||
return m_capacity;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
@@ -1343,6 +1477,8 @@ class SyncChannelArrayRequesterImpl : public ChannelArrayRequester, public SyncB
|
||||
Mutex m_pointerMutex;
|
||||
ChannelArray::shared_pointer m_channelArray;
|
||||
epics::pvData::PVArray::shared_pointer m_pvArray;
|
||||
size_t m_length;
|
||||
size_t m_capacity;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -61,7 +61,7 @@ class ChannelAccessIFRemoteTest: public ChannelAccessIFTest {
|
||||
|
||||
|
||||
virtual ChannelProvider::shared_pointer getChannelProvider() {
|
||||
return getChannelAccess()->getProvider(
|
||||
return getChannelProviderRegistry()->getProvider(
|
||||
"pva");
|
||||
}
|
||||
|
||||
|
||||
@@ -5,6 +5,10 @@
|
||||
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <stdio.h>
|
||||
#include <epicsStdlib.h>
|
||||
#include <epicsGetopt.h>
|
||||
#include <epicsExit.h>
|
||||
#include <pv/clientContextImpl.h>
|
||||
#include <pv/clientFactory.h>
|
||||
@@ -15,13 +19,15 @@ using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
using namespace std;
|
||||
|
||||
#define N_CHANNELS 1000
|
||||
#define N_CHANNELS_DEFAULT 1000
|
||||
#define N_RUNS_DEFAULT 1
|
||||
|
||||
class ChannelRequesterImpl : public ChannelRequester
|
||||
{
|
||||
public:
|
||||
ChannelRequesterImpl(Event& event) : count(0), g_event(event) {}
|
||||
ChannelRequesterImpl(size_t channels, Event& event) : total(channels), count(0), g_event(event) {}
|
||||
private:
|
||||
size_t total;
|
||||
int count;
|
||||
Event& g_event;
|
||||
|
||||
@@ -50,7 +56,7 @@ private:
|
||||
if (connectionState == Channel::CONNECTED)
|
||||
{
|
||||
cout << c->getChannelName() << " CONNECTED: " << (count+1) << endl;
|
||||
if (++count == N_CHANNELS)
|
||||
if (static_cast<size_t>(++count) == total)
|
||||
g_event.signal();
|
||||
}
|
||||
else if (connectionState == Channel::DISCONNECTED)
|
||||
@@ -64,29 +70,83 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
int main()
|
||||
void usage (void)
|
||||
{
|
||||
fprintf (stderr, "\nUsage: testChannelConnect [options]\n\n"
|
||||
" -h: Help: Print this message\n"
|
||||
"options:\n"
|
||||
" -i <iterations>: number of iterations per each run (< 0 means forever), default is '%d'\n"
|
||||
" -c <channels>: number of channels, default is '%d'\n\n"
|
||||
, N_RUNS_DEFAULT, N_CHANNELS_DEFAULT);
|
||||
}
|
||||
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
size_t nChannels = N_CHANNELS_DEFAULT;
|
||||
int runs = N_RUNS_DEFAULT;
|
||||
|
||||
int opt; // getopt() current option
|
||||
setvbuf(stdout,NULL,_IOLBF,BUFSIZ); // Set stdout to line buffering
|
||||
|
||||
while ((opt = getopt(argc, argv, ":hr:w:i:c:s:l:bf:v")) != -1) {
|
||||
switch (opt) {
|
||||
case 'h': // Print usage
|
||||
usage();
|
||||
return 0;
|
||||
case 'i': // iterations
|
||||
runs = atoi(optarg);
|
||||
break;
|
||||
case 'c': // channels
|
||||
{
|
||||
int tmp = atoi(optarg);
|
||||
if (tmp < 0) tmp = 1;
|
||||
// note: possible overflow (size_t is not always unsigned int)
|
||||
nChannels = static_cast<size_t>(tmp);
|
||||
break;
|
||||
}
|
||||
case '?':
|
||||
fprintf(stderr,
|
||||
"Unrecognized option: '-%c'. ('testChannelConnect -h' for help.)\n",
|
||||
optopt);
|
||||
return 1;
|
||||
case ':':
|
||||
fprintf(stderr,
|
||||
"Option '-%c' requires an argument. ('testChannelConnect -h' for help.)\n",
|
||||
optopt);
|
||||
return 1;
|
||||
default :
|
||||
usage();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
Event g_event;
|
||||
|
||||
ClientFactory::start();
|
||||
ChannelProvider::shared_pointer provider = getChannelAccess()->getProvider("pva");
|
||||
ChannelRequester::shared_pointer channelRequester(new ChannelRequesterImpl(g_event));
|
||||
ChannelProvider::shared_pointer provider = getChannelProviderRegistry()->getProvider("pva");
|
||||
|
||||
Channel::shared_pointer channels[N_CHANNELS];
|
||||
char buf[16];
|
||||
for (int i = 0; i < N_CHANNELS; i++)
|
||||
int run = 0;
|
||||
|
||||
while (runs < 0 || run++ < runs)
|
||||
{
|
||||
sprintf(buf, "test%d", (i+1));
|
||||
channels[i] = provider->createChannel(buf, channelRequester);
|
||||
}
|
||||
|
||||
g_event.wait();
|
||||
|
||||
cout << "connected to all" << endl;
|
||||
|
||||
vector<Channel::shared_pointer> channels(nChannels);
|
||||
|
||||
ChannelRequester::shared_pointer channelRequester(new ChannelRequesterImpl(nChannels, g_event));
|
||||
|
||||
char buf[16];
|
||||
for (size_t i = 0; i < nChannels; i++)
|
||||
{
|
||||
sprintf(buf, "test%zu", (i+1));
|
||||
channels.push_back(provider->createChannel(buf, channelRequester));
|
||||
}
|
||||
|
||||
g_event.wait();
|
||||
|
||||
cout << "connected to all" << endl;
|
||||
}
|
||||
|
||||
ClientFactory::stop();
|
||||
}
|
||||
|
||||
|
||||
@@ -352,7 +352,7 @@ namespace epics {
|
||||
|
||||
bool verify(epics::pvData::int32 timeoutMs) { return true;}
|
||||
|
||||
void verified() {}
|
||||
void verified(epics::pvData::Status const &) {}
|
||||
|
||||
void aliveNotification() {}
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ void get_all()
|
||||
for (vector<ChannelGet::shared_pointer>::const_iterator i = channelGetList.begin();
|
||||
i != channelGetList.end();
|
||||
i++)
|
||||
(*i)->get(false);
|
||||
(*i)->get();
|
||||
|
||||
// we assume all channels are from the same provider
|
||||
if (bulkMode) provider->flush();
|
||||
@@ -125,9 +125,6 @@ void get_all()
|
||||
class ChannelGetRequesterImpl : public ChannelGetRequester
|
||||
{
|
||||
private:
|
||||
ChannelGet::shared_pointer m_channelGet;
|
||||
PVStructure::shared_pointer m_pvStructure;
|
||||
BitSet::shared_pointer m_bitSet;
|
||||
Event m_event;
|
||||
Event m_connectionEvent;
|
||||
String m_channelName;
|
||||
@@ -153,9 +150,8 @@ public:
|
||||
}
|
||||
|
||||
virtual void channelGetConnect(const epics::pvData::Status& status,
|
||||
ChannelGet::shared_pointer const & channelGet,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvStructure,
|
||||
epics::pvData::BitSet::shared_pointer const & bitSet)
|
||||
ChannelGet::shared_pointer const & /*channelGet*/,
|
||||
epics::pvData::Structure::const_shared_pointer const & /*structure*/)
|
||||
{
|
||||
if (status.isSuccess())
|
||||
{
|
||||
@@ -165,10 +161,6 @@ public:
|
||||
std::cout << "[" << m_channelName << "] channel get create: " << status.toString() << std::endl;
|
||||
}
|
||||
|
||||
m_channelGet = channelGet;
|
||||
m_pvStructure = pvStructure;
|
||||
m_bitSet = bitSet;
|
||||
|
||||
m_connectionEvent.signal();
|
||||
}
|
||||
else
|
||||
@@ -177,7 +169,10 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
virtual void getDone(const epics::pvData::Status& status)
|
||||
virtual void getDone(const epics::pvData::Status& status,
|
||||
ChannelGet::shared_pointer const & /*channelGet*/,
|
||||
epics::pvData::PVStructure::shared_pointer const & /*pvStructure*/,
|
||||
epics::pvData::BitSet::shared_pointer const & /*bitSet*/)
|
||||
{
|
||||
if (status.isSuccess())
|
||||
{
|
||||
@@ -470,7 +465,7 @@ int main (int argc, char *argv[])
|
||||
}
|
||||
|
||||
ClientFactory::start();
|
||||
provider = getChannelAccess()->getProvider("pva");
|
||||
provider = getChannelProviderRegistry()->getProvider("pva");
|
||||
|
||||
if (!testFile.empty())
|
||||
{
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
|
||||
#define SLEEP_TIME 1.0
|
||||
|
||||
class ChannelFindRequesterImpl : public ChannelFindRequester
|
||||
{
|
||||
@@ -60,7 +61,7 @@ class GetFieldRequesterImpl : public GetFieldRequester
|
||||
std::cout << "[" << getRequesterName() << "] message(" << message << ", " << getMessageTypeName(messageType) << ")" << std::endl;
|
||||
}
|
||||
|
||||
virtual void getDone(const epics::pvData::Status& status,epics::pvData::FieldConstPtr const & field)
|
||||
virtual void getDone(const epics::pvData::Status& status, epics::pvData::FieldConstPtr const & field)
|
||||
{
|
||||
std::cout << "getDone(" << status.toString() << ", ";
|
||||
if (status.isSuccess() && field)
|
||||
@@ -77,12 +78,6 @@ class GetFieldRequesterImpl : public GetFieldRequester
|
||||
|
||||
class ChannelGetRequesterImpl : public ChannelGetRequester
|
||||
{
|
||||
private:
|
||||
|
||||
//ChannelGet::shared_pointer m_channelGet;
|
||||
epics::pvData::PVStructure::shared_pointer m_pvStructure;
|
||||
epics::pvData::BitSet::shared_pointer m_bitSet;
|
||||
|
||||
public:
|
||||
|
||||
virtual String getRequesterName()
|
||||
@@ -96,8 +91,7 @@ class ChannelGetRequesterImpl : public ChannelGetRequester
|
||||
}
|
||||
|
||||
virtual void channelGetConnect(const epics::pvData::Status& status,ChannelGet::shared_pointer const & /*channelGet*/,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvStructure,
|
||||
epics::pvData::BitSet::shared_pointer const & bitSet)
|
||||
epics::pvData::Structure::const_shared_pointer const & pvStructure)
|
||||
{
|
||||
std::cout << "channelGetConnect(" << status.toString() << ")" << std::endl;
|
||||
if (status.isSuccess())
|
||||
@@ -106,20 +100,17 @@ class ChannelGetRequesterImpl : public ChannelGetRequester
|
||||
pvStructure->toString(&st);
|
||||
std::cout << st << std::endl;
|
||||
}
|
||||
|
||||
//m_channelGet = channelGet;
|
||||
m_pvStructure = pvStructure;
|
||||
m_bitSet = bitSet;
|
||||
}
|
||||
|
||||
virtual void getDone(const epics::pvData::Status& status)
|
||||
virtual void getDone(const epics::pvData::Status& status, ChannelGet::shared_pointer const &,
|
||||
PVStructure::shared_pointer const & getData, BitSet::shared_pointer const & /*bitSet*/)
|
||||
{
|
||||
std::cout << "getDone(" << status.toString() << ")" << std::endl;
|
||||
|
||||
if (status.isSuccess())
|
||||
{
|
||||
String str;
|
||||
m_pvStructure->toString(&str);
|
||||
getData->toString(&str);
|
||||
std::cout << str;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
@@ -128,12 +119,6 @@ class ChannelGetRequesterImpl : public ChannelGetRequester
|
||||
|
||||
class ChannelPutRequesterImpl : public ChannelPutRequester
|
||||
{
|
||||
private:
|
||||
|
||||
//ChannelPut::shared_pointer m_channelPut;
|
||||
epics::pvData::PVStructure::shared_pointer m_pvStructure;
|
||||
epics::pvData::BitSet::shared_pointer m_bitSet;
|
||||
|
||||
public:
|
||||
|
||||
virtual String getRequesterName()
|
||||
@@ -147,50 +132,39 @@ class ChannelPutRequesterImpl : public ChannelPutRequester
|
||||
}
|
||||
|
||||
virtual void channelPutConnect(const epics::pvData::Status& status,ChannelPut::shared_pointer const & /*channelPut*/,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvStructure,
|
||||
epics::pvData::BitSet::shared_pointer const & bitSet)
|
||||
epics::pvData::Structure::const_shared_pointer const & pvStructure)
|
||||
{
|
||||
std::cout << "channelPutConnect(" << status.toString() << ")" << std::endl;
|
||||
|
||||
//m_channelPut = channelPut;
|
||||
m_pvStructure = pvStructure;
|
||||
m_bitSet = bitSet;
|
||||
if (status.isSuccess())
|
||||
{
|
||||
String st;
|
||||
pvStructure->toString(&st);
|
||||
std::cout << st << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void getDone(const epics::pvData::Status& status)
|
||||
virtual void getDone(const epics::pvData::Status& status, ChannelPut::shared_pointer const &,
|
||||
PVStructure::shared_pointer const & getData, BitSet::shared_pointer const & /*bitSet*/)
|
||||
{
|
||||
std::cout << "getDone(" << status.toString() << ")" << std::endl;
|
||||
if (status.isSuccess())
|
||||
{
|
||||
String str;
|
||||
m_pvStructure->toString(&str);
|
||||
getData->toString(&str);
|
||||
std::cout << str;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void putDone(const epics::pvData::Status& status)
|
||||
virtual void putDone(const epics::pvData::Status& status, ChannelPut::shared_pointer const &)
|
||||
{
|
||||
std::cout << "putDone(" << status.toString() << ")" << std::endl;
|
||||
if (status.isSuccess())
|
||||
{
|
||||
String str;
|
||||
m_pvStructure->toString(&str);
|
||||
std::cout << str;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class ChannelPutGetRequesterImpl : public ChannelPutGetRequester
|
||||
{
|
||||
private:
|
||||
|
||||
//ChannelPutGet::shared_pointer m_channelPutGet;
|
||||
epics::pvData::PVStructure::shared_pointer m_putData;
|
||||
epics::pvData::PVStructure::shared_pointer m_getData;
|
||||
|
||||
public:
|
||||
|
||||
virtual String getRequesterName()
|
||||
@@ -204,62 +178,61 @@ class ChannelPutGetRequesterImpl : public ChannelPutGetRequester
|
||||
}
|
||||
|
||||
virtual void channelPutGetConnect(const epics::pvData::Status& status, ChannelPutGet::shared_pointer const & /*channelPutGet*/,
|
||||
epics::pvData::PVStructure::shared_pointer const & putData,
|
||||
epics::pvData::PVStructure::shared_pointer const & getData)
|
||||
epics::pvData::Structure::const_shared_pointer const & putData,
|
||||
epics::pvData::Structure::const_shared_pointer const & getData)
|
||||
{
|
||||
std::cout << "channelGetPutConnect(" << status.toString() << ")" << std::endl;
|
||||
|
||||
//m_channelPutGet = channelPutGet;
|
||||
m_putData = putData;
|
||||
m_getData = getData;
|
||||
|
||||
if (m_putData)
|
||||
if (putData)
|
||||
{
|
||||
String str;
|
||||
m_putData->toString(&str);
|
||||
putData->toString(&str);
|
||||
std::cout << str;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
if (m_getData)
|
||||
if (getData)
|
||||
{
|
||||
String str;
|
||||
m_getData->toString(&str);
|
||||
getData->toString(&str);
|
||||
std::cout << str;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void getGetDone(const epics::pvData::Status& status)
|
||||
virtual void getGetDone(const epics::pvData::Status& status, ChannelPutGet::shared_pointer const &,
|
||||
PVStructure::shared_pointer const & getData, BitSet::shared_pointer const & /*bitSet*/)
|
||||
{
|
||||
std::cout << "getGetDone(" << status.toString() << ")" << std::endl;
|
||||
if (status.isSuccess())
|
||||
{
|
||||
String str;
|
||||
m_getData->toString(&str);
|
||||
getData->toString(&str);
|
||||
std::cout << str;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void getPutDone(const epics::pvData::Status& status)
|
||||
virtual void getPutDone(const epics::pvData::Status& status, ChannelPutGet::shared_pointer const &,
|
||||
PVStructure::shared_pointer const & putData, BitSet::shared_pointer const & /*bitSet*/)
|
||||
{
|
||||
std::cout << "getPutDone(" << status.toString() << ")" << std::endl;
|
||||
if (status.isSuccess())
|
||||
{
|
||||
String str;
|
||||
m_putData->toString(&str);
|
||||
putData->toString(&str);
|
||||
std::cout << str;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void putGetDone(const epics::pvData::Status& status)
|
||||
virtual void putGetDone(const epics::pvData::Status& status, ChannelPutGet::shared_pointer const &,
|
||||
PVStructure::shared_pointer const & putData, BitSet::shared_pointer const & /*bitSet*/)
|
||||
{
|
||||
std::cout << "putGetDone(" << status.toString() << ")" << std::endl;
|
||||
if (status.isSuccess())
|
||||
{
|
||||
String str;
|
||||
m_putData->toString(&str);
|
||||
putData->toString(&str);
|
||||
std::cout << str;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
@@ -270,8 +243,6 @@ class ChannelPutGetRequesterImpl : public ChannelPutGetRequester
|
||||
|
||||
class ChannelRPCRequesterImpl : public ChannelRPCRequester
|
||||
{
|
||||
//ChannelRPC::shared_pointer m_channelRPC;
|
||||
|
||||
virtual String getRequesterName()
|
||||
{
|
||||
return "ChannelRPCRequesterImpl";
|
||||
@@ -286,11 +257,10 @@ class ChannelRPCRequesterImpl : public ChannelRPCRequester
|
||||
ChannelRPC::shared_pointer const & /*channelRPC*/)
|
||||
{
|
||||
std::cout << "channelRPCConnect(" << status.toString() << ")" << std::endl;
|
||||
|
||||
//m_channelRPC = channelRPC;
|
||||
}
|
||||
|
||||
virtual void requestDone(const epics::pvData::Status& status,epics::pvData::PVStructure::shared_pointer const & pvResponse)
|
||||
virtual void requestDone(const epics::pvData::Status& status, ChannelRPC::shared_pointer const &,
|
||||
epics::pvData::PVStructure::shared_pointer const & pvResponse)
|
||||
{
|
||||
std::cout << "requestDone(" << status.toString() << ")" << std::endl;
|
||||
if (status.isSuccess())
|
||||
@@ -305,11 +275,6 @@ class ChannelRPCRequesterImpl : public ChannelRPCRequester
|
||||
|
||||
class ChannelArrayRequesterImpl : public ChannelArrayRequester
|
||||
{
|
||||
private:
|
||||
|
||||
//ChannelArray::shared_pointer m_channelArray;
|
||||
epics::pvData::PVArray::shared_pointer m_pvArray;
|
||||
|
||||
public:
|
||||
|
||||
virtual String getRequesterName()
|
||||
@@ -323,41 +288,46 @@ class ChannelArrayRequesterImpl : public ChannelArrayRequester
|
||||
}
|
||||
|
||||
virtual void channelArrayConnect(const epics::pvData::Status& status,ChannelArray::shared_pointer const & /*channelArray*/,
|
||||
epics::pvData::PVArray::shared_pointer const & pvArray)
|
||||
epics::pvData::Array::const_shared_pointer const & array)
|
||||
{
|
||||
std::cout << "channelArrayConnect(" << status.toString() << ")" << std::endl;
|
||||
if (status.isSuccess())
|
||||
{
|
||||
String st;
|
||||
pvArray->toString(&st);
|
||||
array->toString(&st);
|
||||
std::cout << st << std::endl;
|
||||
}
|
||||
|
||||
//m_channelArray = channelArray;
|
||||
m_pvArray = pvArray;
|
||||
}
|
||||
|
||||
virtual void getArrayDone(const epics::pvData::Status& status)
|
||||
virtual void getArrayDone(const epics::pvData::Status& status, ChannelArray::shared_pointer const &,
|
||||
PVArray::shared_pointer const & pvArray)
|
||||
{
|
||||
std::cout << "getArrayDone(" << status.toString() << ")" << std::endl;
|
||||
if (status.isSuccess())
|
||||
{
|
||||
String str;
|
||||
m_pvArray->toString(&str);
|
||||
pvArray->toString(&str);
|
||||
std::cout << str;
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void putArrayDone(const epics::pvData::Status& status)
|
||||
virtual void putArrayDone(const epics::pvData::Status& status, ChannelArray::shared_pointer const &)
|
||||
{
|
||||
std::cout << "putArrayDone(" << status.toString() << ")" << std::endl;
|
||||
}
|
||||
|
||||
virtual void setLengthDone(const epics::pvData::Status& status)
|
||||
virtual void setLengthDone(const epics::pvData::Status& status, ChannelArray::shared_pointer const &)
|
||||
{
|
||||
std::cout << "setLengthDone(" << status.toString() << ")" << std::endl;
|
||||
}
|
||||
|
||||
virtual void getLengthDone(const epics::pvData::Status& status, ChannelArray::shared_pointer const &,
|
||||
size_t length, size_t capacity)
|
||||
{
|
||||
std::cout << "getLengthDone(" << status.toString() << "," << length << "," << capacity << ")" << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
class MonitorRequesterImpl : public MonitorRequester
|
||||
@@ -430,7 +400,7 @@ class ChannelProcessRequesterImpl : public ChannelProcessRequester
|
||||
//m_channelProcess = channelProcess;
|
||||
}
|
||||
|
||||
virtual void processDone(const epics::pvData::Status& status)
|
||||
virtual void processDone(const epics::pvData::Status& status, ChannelProcess::shared_pointer const &)
|
||||
{
|
||||
std::cout << "processDone(" << status.toString() << ")" << std::endl;
|
||||
}
|
||||
@@ -449,39 +419,39 @@ int main()
|
||||
context->initialize();
|
||||
context->printInfo();
|
||||
|
||||
epicsThreadSleep ( 1.0 );
|
||||
epicsThreadSleep ( SLEEP_TIME );
|
||||
|
||||
ChannelProvider::shared_pointer provider = context->getProvider();
|
||||
*/
|
||||
|
||||
ClientFactory::start();
|
||||
ChannelProvider::shared_pointer provider = getChannelAccess()->getProvider("pva");
|
||||
ChannelProvider::shared_pointer provider = getChannelProviderRegistry()->getProvider("pva");
|
||||
|
||||
ChannelFindRequester::shared_pointer findRequester(new ChannelFindRequesterImpl());
|
||||
ChannelFind::shared_pointer channelFind = provider->channelFind("testSomething", findRequester);
|
||||
epicsThreadSleep ( 1.0 );
|
||||
epicsThreadSleep ( SLEEP_TIME );
|
||||
//channelFind->destroy();
|
||||
|
||||
ChannelRequester::shared_pointer channelRequester(new ChannelRequesterImpl());
|
||||
Channel::shared_pointer channel = provider->createChannel("testStructureArrayTest", channelRequester);
|
||||
epicsThreadSleep ( 1.0 );
|
||||
epicsThreadSleep ( SLEEP_TIME );
|
||||
channel->printInfo();
|
||||
|
||||
{
|
||||
GetFieldRequester::shared_pointer getFieldRequesterImpl(new GetFieldRequesterImpl());
|
||||
channel->getField(getFieldRequesterImpl, "");
|
||||
epicsThreadSleep ( 1.0 );
|
||||
epicsThreadSleep ( SLEEP_TIME );
|
||||
}
|
||||
|
||||
{
|
||||
ChannelProcessRequester::shared_pointer channelProcessRequester(new ChannelProcessRequesterImpl());
|
||||
PVStructure::shared_pointer pvRequest;
|
||||
ChannelProcess::shared_pointer channelProcess = channel->createChannelProcess(channelProcessRequester, pvRequest);
|
||||
epicsThreadSleep ( 1.0 );
|
||||
channelProcess->process(false);
|
||||
epicsThreadSleep ( 1.0 );
|
||||
epicsThreadSleep ( SLEEP_TIME );
|
||||
channelProcess->process();
|
||||
epicsThreadSleep ( SLEEP_TIME );
|
||||
channelProcess->destroy();
|
||||
epicsThreadSleep ( 1.0 );
|
||||
epicsThreadSleep ( SLEEP_TIME );
|
||||
}
|
||||
|
||||
{
|
||||
@@ -489,7 +459,7 @@ int main()
|
||||
PVStructure::shared_pointer pvRequest = CreateRequest::create()->createRequest("field()");
|
||||
ChannelGet::shared_pointer channelGet = channel->createChannelGet(channelGetRequesterImpl, pvRequest);
|
||||
epicsThreadSleep ( 3.0 );
|
||||
channelGet->get(false);
|
||||
channelGet->get();
|
||||
epicsThreadSleep ( 3.0 );
|
||||
channelGet->destroy();
|
||||
}
|
||||
@@ -498,11 +468,12 @@ int main()
|
||||
ChannelPutRequester::shared_pointer channelPutRequesterImpl(new ChannelPutRequesterImpl());
|
||||
PVStructure::shared_pointer pvRequest = CreateRequest::create()->createRequest("field(value,timeStamp)");
|
||||
ChannelPut::shared_pointer channelPut = channel->createChannelPut(channelPutRequesterImpl, pvRequest);
|
||||
epicsThreadSleep ( 1.0 );
|
||||
epicsThreadSleep ( SLEEP_TIME );
|
||||
channelPut->get();
|
||||
epicsThreadSleep ( 1.0 );
|
||||
channelPut->put(false);
|
||||
epicsThreadSleep ( 1.0 );
|
||||
epicsThreadSleep ( SLEEP_TIME );
|
||||
// TODO !!!
|
||||
//channelPut->put();
|
||||
//epicsThreadSleep ( SLEEP_TIME );
|
||||
channelPut->destroy();
|
||||
}
|
||||
|
||||
@@ -510,13 +481,14 @@ int main()
|
||||
ChannelPutGetRequester::shared_pointer channelPutGetRequesterImpl(new ChannelPutGetRequesterImpl());
|
||||
PVStructure::shared_pointer pvRequest = CreateRequest::create()->createRequest("putField(value,timeStamp)getField(timeStamp)");
|
||||
ChannelPutGet::shared_pointer channelPutGet = channel->createChannelPutGet(channelPutGetRequesterImpl, pvRequest);
|
||||
epicsThreadSleep ( 1.0 );
|
||||
epicsThreadSleep ( SLEEP_TIME );
|
||||
channelPutGet->getGet();
|
||||
epicsThreadSleep ( 1.0 );
|
||||
epicsThreadSleep ( SLEEP_TIME );
|
||||
channelPutGet->getPut();
|
||||
epicsThreadSleep ( 1.0 );
|
||||
channelPutGet->putGet(false);
|
||||
epicsThreadSleep ( 1.0 );
|
||||
epicsThreadSleep ( SLEEP_TIME );
|
||||
// TODO !!!
|
||||
//channelPutGet->putGet();
|
||||
//epicsThreadSleep ( SLEEP_TIME );
|
||||
channelPutGet->destroy();
|
||||
}
|
||||
|
||||
@@ -524,10 +496,10 @@ int main()
|
||||
ChannelRPCRequester::shared_pointer channelRPCRequesterImpl(new ChannelRPCRequesterImpl());
|
||||
PVStructure::shared_pointer pvRequest = CreateRequest::create()->createRequest("record[]field(arguments)");
|
||||
ChannelRPC::shared_pointer channelRPC = channel->createChannelRPC(channelRPCRequesterImpl, pvRequest);
|
||||
epicsThreadSleep ( 1.0 );
|
||||
epicsThreadSleep ( SLEEP_TIME );
|
||||
// for test simply use pvRequest as arguments
|
||||
channelRPC->request(pvRequest, false);
|
||||
epicsThreadSleep ( 1.0 );
|
||||
channelRPC->request(pvRequest);
|
||||
epicsThreadSleep ( SLEEP_TIME );
|
||||
channelRPC->destroy();
|
||||
}
|
||||
|
||||
@@ -538,13 +510,16 @@ int main()
|
||||
PVStructure::shared_pointer pvRequest(getPVDataCreate()->createPVStructure(getFieldCreate()->createStructure(fieldNames, fields)));
|
||||
|
||||
ChannelArray::shared_pointer channelArray = channel->createChannelArray(channelArrayRequesterImpl, pvRequest);
|
||||
epicsThreadSleep ( 1.0 );
|
||||
channelArray->getArray(false,0,-1);
|
||||
epicsThreadSleep ( 1.0 );
|
||||
channelArray->putArray(false,0,-1);
|
||||
epicsThreadSleep ( 1.0 );
|
||||
channelArray->setLength(false,3,4);
|
||||
epicsThreadSleep ( 1.0 );
|
||||
epicsThreadSleep ( SLEEP_TIME );
|
||||
channelArray->getArray(0,0,1);
|
||||
epicsThreadSleep ( SLEEP_TIME );
|
||||
// TODO !!!
|
||||
//channelArray->putArray(0,0,1);
|
||||
//epicsThreadSleep ( SLEEP_TIME );
|
||||
channelArray->setLength(3,4);
|
||||
epicsThreadSleep ( SLEEP_TIME );
|
||||
channelArray->getLength();
|
||||
epicsThreadSleep ( SLEEP_TIME );
|
||||
channelArray->destroy();
|
||||
}
|
||||
|
||||
@@ -553,12 +528,12 @@ int main()
|
||||
PVStructure::shared_pointer pvRequest = CreateRequest::create()->createRequest("field()");
|
||||
Monitor::shared_pointer monitor = channel->createMonitor(monitorRequesterImpl, pvRequest);
|
||||
|
||||
epicsThreadSleep( 1.0 );
|
||||
epicsThreadSleep( SLEEP_TIME );
|
||||
|
||||
Status status = monitor->start();
|
||||
std::cout << "monitor->start() = " << status.toString() << std::endl;
|
||||
|
||||
epicsThreadSleep( 3.0 );
|
||||
epicsThreadSleep( 3*SLEEP_TIME );
|
||||
|
||||
status = monitor->stop();
|
||||
std::cout << "monitor->stop() = " << status.toString() << std::endl;
|
||||
@@ -567,12 +542,12 @@ int main()
|
||||
monitor->destroy();
|
||||
}
|
||||
|
||||
epicsThreadSleep ( 3.0 );
|
||||
epicsThreadSleep ( 3*SLEEP_TIME );
|
||||
printf("Destroying channel... \n");
|
||||
channel->destroy();
|
||||
printf("done.\n");
|
||||
|
||||
epicsThreadSleep ( 3.0 );
|
||||
epicsThreadSleep ( 3*SLEEP_TIME );
|
||||
|
||||
}
|
||||
|
||||
@@ -584,7 +559,7 @@ int main()
|
||||
printf("done.\n");
|
||||
*/
|
||||
|
||||
epicsThreadSleep ( 1.0 ); }
|
||||
epicsThreadSleep ( SLEEP_TIME ); }
|
||||
//std::cout << "-----------------------------------------------------------------------" << std::endl;
|
||||
//epicsExitCallAtExits();
|
||||
return(0);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -24,6 +24,14 @@ public:
|
||||
return nullCF;
|
||||
}
|
||||
|
||||
ChannelFind::shared_pointer channelList(ChannelListRequester::shared_pointer const & channelListRequester)
|
||||
{
|
||||
ChannelFind::shared_pointer nullCF;
|
||||
PVStringArray::const_svector none;
|
||||
channelListRequester->channelListResult(Status::Ok, nullCF, none, false);
|
||||
return nullCF;
|
||||
}
|
||||
|
||||
Channel::shared_pointer createChannel(
|
||||
epics::pvData::String const & channelName,
|
||||
ChannelRequester::shared_pointer const & channelRequester,
|
||||
@@ -48,10 +56,10 @@ public:
|
||||
};
|
||||
|
||||
|
||||
class TestChannelAccess : public ChannelAccess {
|
||||
class TestChannelProviderRegistry : public ChannelProviderRegistry {
|
||||
public:
|
||||
|
||||
virtual ~TestChannelAccess() {};
|
||||
virtual ~TestChannelProviderRegistry() {};
|
||||
|
||||
ChannelProvider::shared_pointer getProvider(epics::pvData::String const & providerName)
|
||||
{
|
||||
@@ -81,7 +89,7 @@ void testServerContext()
|
||||
|
||||
ServerContextImpl::shared_pointer ctx = ServerContextImpl::create();
|
||||
|
||||
ChannelAccess::shared_pointer ca(new TestChannelAccess());
|
||||
ChannelProviderRegistry::shared_pointer ca(new TestChannelProviderRegistry());
|
||||
ctx->initialize(ca);
|
||||
|
||||
ctx->printInfo();
|
||||
|
||||
@@ -125,6 +125,22 @@ void test_encodeAsIPv6Address()
|
||||
testOk1(strncmp(buff->getArray(), src, 16) == 0);
|
||||
}
|
||||
|
||||
void test_isMulticastAddress()
|
||||
{
|
||||
testDiag("Test test_isMulticastAddress()");
|
||||
|
||||
auto_ptr<InetAddrVector> vec(getSocketAddressList("127.0.0.1 255.255.255.255 0.0.0.0 224.0.0.0 239.255.255.255 235.3.6.3", 0));
|
||||
|
||||
testOk1(static_cast<size_t>(6) == vec->size());
|
||||
|
||||
testOk1(!isMulticastAddress(&vec->at(0)));
|
||||
testOk1(!isMulticastAddress(&vec->at(1)));
|
||||
testOk1(!isMulticastAddress(&vec->at(2)));
|
||||
testOk1(isMulticastAddress(&vec->at(3)));
|
||||
testOk1(isMulticastAddress(&vec->at(4)));
|
||||
testOk1(isMulticastAddress(&vec->at(5)));
|
||||
}
|
||||
|
||||
void test_getBroadcastAddresses()
|
||||
{
|
||||
testDiag("Test getBroadcastAddresses()");
|
||||
@@ -146,13 +162,14 @@ void test_getBroadcastAddresses()
|
||||
|
||||
MAIN(testInetAddressUtils)
|
||||
{
|
||||
testPlan(44);
|
||||
testPlan(51);
|
||||
testDiag("Tests for InetAddress utils");
|
||||
|
||||
test_getSocketAddressList();
|
||||
test_ipv4AddressToInt();
|
||||
test_intToIPv4Address();
|
||||
test_encodeAsIPv6Address();
|
||||
test_isMulticastAddress();
|
||||
test_getBroadcastAddresses();
|
||||
|
||||
return testDone();
|
||||
|
||||
Reference in New Issue
Block a user