port from pvAccessCPP-md
This commit is contained in:
3
README
3
README
@@ -1,5 +1,6 @@
|
||||
Define
|
||||
|
||||
EPICS_BASE
|
||||
PVDATA_HOME
|
||||
|
||||
env. variable that points to pvDataCPP installation directory (includes and libraries).
|
||||
variables that points to EPICS base and pvDataCPP installation directory (includes and libraries) in configure/RELEASE.
|
||||
|
||||
@@ -26,8 +26,8 @@ TEMPLATE_TOP=$(EPICS_BASE)/templates/makeBaseApp/top
|
||||
|
||||
# EPICS_BASE usually appears last so other apps can override stuff:
|
||||
|
||||
PVDATA=/home/mrk/hg/pvDataCPP
|
||||
EPICS_BASE=/home/install/epics/base
|
||||
PVDATA=/Users/msekoranja/tmp/pvDataCPP
|
||||
EPICS_BASE=/opt/epics/base
|
||||
|
||||
#PVDATA=/home/mrk/hg/pvDataCPP
|
||||
#EPICS_BASE=/home/install/epics/base
|
||||
|
||||
@@ -15,8 +15,6 @@ LIBSRCS += clientFactory.cpp
|
||||
SRC_DIRS += $(PVACCESS)/utils
|
||||
INC += hexDump.h
|
||||
INC += wildcharMatcher.h
|
||||
INC += arrayFIFO.h
|
||||
INC += growingCircularBuffer.h
|
||||
INC += inetAddressUtil.h
|
||||
INC += logger.h
|
||||
INC += introspectionRegistry.h
|
||||
@@ -30,10 +28,8 @@ LIBSRCS += inetAddressUtil.cpp
|
||||
LIBSRCS += logger.cpp
|
||||
LIBSRCS += introspectionRegistry.cpp
|
||||
LIBSRCS += transportRegistry.cpp
|
||||
LIBSRCS += namedLockPattern.cpp
|
||||
LIBSRCS += referenceCountingLock.cpp
|
||||
LIBSRCS += configuration.cpp
|
||||
|
||||
LIBSRCS += referenceCountingLock.cpp
|
||||
|
||||
SRC_DIRS += $(PVACCESS)/client
|
||||
INC += pvAccess.h
|
||||
@@ -44,12 +40,14 @@ INC += serverContext.h
|
||||
INC += responseHandlers.h
|
||||
INC += serverChannelImpl.h
|
||||
INC += baseChannelRequester.h
|
||||
INC += referencedTransportSender.h
|
||||
INC += beaconEmitter.h
|
||||
INC += beaconServerStatusProvider.h
|
||||
LIBSRCS += responseHandlers.cpp
|
||||
LIBSRCS += serverContext.cpp
|
||||
LIBSRCS += serverChannelImpl.cpp
|
||||
LIBSRCS += baseChannelRequester.cpp
|
||||
LIBSRCS += referencedTransportSender.h
|
||||
LIBSRCS += beaconEmitter.cpp
|
||||
LIBSRCS += beaconServerStatusProvider.cpp
|
||||
|
||||
SRC_DIRS += $(PVACCESS)/factory
|
||||
LIBSRCS += ChannelAccessFactory.cpp
|
||||
@@ -59,23 +57,19 @@ LIBSRCS += CreateRequestFactory.cpp
|
||||
SRC_DIRS += $(PVACCESS)/remote
|
||||
INC += remote.h
|
||||
INC += blockingUDP.h
|
||||
INC += beaconEmitter.h
|
||||
INC += beaconServerStatusProvider.h
|
||||
INC += beaconHandler.h
|
||||
INC += blockingTCP.h
|
||||
INC += channelSearchManager.h
|
||||
LIBSRCS += blockingUDPTransport.cpp
|
||||
LIBSRCS += blockingUDPConnector.cpp
|
||||
LIBSRCS += beaconEmitter.cpp
|
||||
LIBSRCS += beaconServerStatusProvider.cpp
|
||||
LIBSRCS += beaconHandler.cpp
|
||||
LIBSRCS += blockingTCPTransport.cpp
|
||||
LIBSRCS += blockingClientTCPTransport.cpp
|
||||
LIBSRCS += blockingTCPConnector.cpp
|
||||
LIBSRCS += blockingServerTCPTransport.cpp
|
||||
LIBSRCS += blockingTCPAcceptor.cpp
|
||||
LIBSRCS += channelSearchManager.cpp
|
||||
LIBSRCS += abstractResponseHandler.cpp
|
||||
LIBSRCS += blockingTCPAcceptor.cpp
|
||||
|
||||
|
||||
SRC_DIRS += $(PVACCESS)/remoteClient
|
||||
|
||||
@@ -74,10 +74,10 @@ namespace epics {
|
||||
const int16 INVALID_DATA_TYPE = (int16)0xFFFF;
|
||||
|
||||
/** Invalid IOID. */
|
||||
const int32 CAJ_INVALID_IOID = 0;
|
||||
const int32 INVALID_IOID = 0;
|
||||
|
||||
/** Default CA provider name. */
|
||||
const String CAJ_DEFAULT_PROVIDER = "local";
|
||||
const String PVACCESS_DEFAULT_PROVIDER = "local";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -8,18 +8,19 @@ using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
|
||||
Mutex ClientFactory::m_mutex;
|
||||
ClientContextImpl* ClientFactory::m_context = 0;
|
||||
ClientContextImpl::shared_pointer ClientFactory::m_context;
|
||||
|
||||
void ClientFactory::start()
|
||||
{
|
||||
Lock guard(m_mutex);
|
||||
|
||||
if (m_context) return;
|
||||
if (m_context.get()) return;
|
||||
|
||||
try {
|
||||
m_context = createClientContextImpl();
|
||||
m_context->initialize();
|
||||
registerChannelProvider(m_context->getProvider());
|
||||
ChannelProvider::shared_pointer provider = m_context->getProvider();
|
||||
registerChannelProvider(provider);
|
||||
} catch (std::exception &e) {
|
||||
errlogSevPrintf(errlogMajor, "Unhandled exception caught at %s:%d: %s", __FILE__, __LINE__, e.what());
|
||||
} catch (...) {
|
||||
@@ -31,7 +32,11 @@ void ClientFactory::stop()
|
||||
{
|
||||
Lock guard(m_mutex);
|
||||
|
||||
unregisterChannelProvider(m_context->getProvider());
|
||||
if (!m_context.get()) return;
|
||||
|
||||
ChannelProvider::shared_pointer provider = m_context->getProvider();
|
||||
unregisterChannelProvider(provider);
|
||||
|
||||
m_context->dispose();
|
||||
m_context = 0;
|
||||
m_context.reset();
|
||||
}
|
||||
|
||||
@@ -14,9 +14,9 @@ class ClientFactory {
|
||||
|
||||
private:
|
||||
static epics::pvData::Mutex m_mutex;
|
||||
static ClientContextImpl* m_context;
|
||||
static ClientContextImpl::shared_pointer m_context;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /* CLIENTFACTORY_H */
|
||||
#endif /* CLIENTFACTORY_H */
|
||||
|
||||
@@ -30,11 +30,20 @@ namespace epics { namespace pvAccess {
|
||||
class Channel;
|
||||
class ChannelProvider;
|
||||
|
||||
#define POINTER_DEFINITIONS(clazz) \
|
||||
typedef std::tr1::shared_ptr<clazz> shared_pointer; \
|
||||
typedef std::tr1::shared_ptr<const clazz> const_shared_pointer; \
|
||||
typedef std::tr1::weak_ptr<clazz> weak_pointer; \
|
||||
typedef std::tr1::weak_ptr<const clazz> const_weak_pointer;
|
||||
|
||||
|
||||
/**
|
||||
* Base interface for all channel requests.
|
||||
* @author mse
|
||||
*/
|
||||
class ChannelRequest : public epics::pvData::Destroyable, private epics::pvData::NoDefaultMethods {
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelRequest);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -45,6 +54,7 @@ namespace epics { namespace pvAccess {
|
||||
*/
|
||||
class ChannelArray : public ChannelRequest{
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelArray);
|
||||
|
||||
/**
|
||||
* put to the remote array.
|
||||
@@ -78,6 +88,7 @@ namespace epics { namespace pvAccess {
|
||||
*/
|
||||
class ChannelArrayRequester : virtual public epics::pvData::Requester {
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelArrayRequester);
|
||||
|
||||
/**
|
||||
* The client and server have both completed the createChannelArray request.
|
||||
@@ -85,25 +96,28 @@ namespace epics { namespace pvAccess {
|
||||
* @param channelArray The channelArray interface or null if the request failed.
|
||||
* @param pvArray The PVArray that holds the data.
|
||||
*/
|
||||
virtual void channelArrayConnect(const epics::pvData::Status &status,ChannelArray *channelArray,epics::pvData::PVArray *pvArray) = 0;
|
||||
virtual void channelArrayConnect(
|
||||
const epics::pvData::Status& status,
|
||||
ChannelArray::shared_pointer& channelArray,
|
||||
epics::pvData::PVArray::shared_pointer& pvArray) = 0;
|
||||
|
||||
/**
|
||||
* The request is done. This is always called with no locks held.
|
||||
* @param status Completion status.
|
||||
*/
|
||||
virtual void putArrayDone(const epics::pvData::Status &status) = 0;
|
||||
virtual void putArrayDone(const epics::pvData::Status& status) = 0;
|
||||
|
||||
/**
|
||||
* The request is done. This is always called with no locks held.
|
||||
* @param status Completion status.
|
||||
*/
|
||||
virtual void getArrayDone(const epics::pvData::Status &status) = 0;
|
||||
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) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -113,7 +127,9 @@ namespace epics { namespace pvAccess {
|
||||
*/
|
||||
class ChannelFind : public epics::pvData::Destroyable, private epics::pvData::NoDefaultMethods {
|
||||
public:
|
||||
virtual ChannelProvider* getChannelProvider() = 0;
|
||||
POINTER_DEFINITIONS(ChannelFind);
|
||||
|
||||
virtual std::tr1::shared_ptr<ChannelProvider> getChannelProvider() = 0;
|
||||
virtual void cancelChannelFind() = 0;
|
||||
};
|
||||
|
||||
@@ -123,11 +139,12 @@ namespace epics { namespace pvAccess {
|
||||
*/
|
||||
class ChannelFindRequester {
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelFindRequester);
|
||||
|
||||
/**
|
||||
* @param status Completion status.
|
||||
*/
|
||||
virtual void channelFindResult(const epics::pvData::Status &status,ChannelFind *channelFind,bool wasFound) = 0;
|
||||
virtual void channelFindResult(const epics::pvData::Status& status,ChannelFind::shared_pointer& channelFind,bool wasFound) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -138,6 +155,7 @@ namespace epics { namespace pvAccess {
|
||||
*/
|
||||
class ChannelGet : public ChannelRequest {
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelGet);
|
||||
|
||||
/**
|
||||
* Get data from the channel.
|
||||
@@ -156,6 +174,7 @@ namespace epics { namespace pvAccess {
|
||||
*/
|
||||
class ChannelGetRequester : virtual public epics::pvData::Requester {
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelGetRequester);
|
||||
|
||||
/**
|
||||
* The client and server have both completed the createChannelGet request.
|
||||
@@ -164,14 +183,14 @@ namespace epics { namespace pvAccess {
|
||||
* @param pvStructure The PVStructure that holds the data.
|
||||
* @param bitSet The bitSet for that shows what data has changed.
|
||||
*/
|
||||
virtual void channelGetConnect(const epics::pvData::Status &status,ChannelGet *channelGet,
|
||||
epics::pvData::PVStructure *pvStructure,epics::pvData::BitSet *bitSet) = 0;
|
||||
virtual void channelGetConnect(const epics::pvData::Status& status,ChannelGet::shared_pointer& channelGet,
|
||||
epics::pvData::PVStructure::shared_pointer& pvStructure,epics::pvData::BitSet::shared_pointer& bitSet) = 0;
|
||||
|
||||
/**
|
||||
* The request is done. This is always called with no locks held.
|
||||
* @param status Completion status.
|
||||
*/
|
||||
virtual void getDone(const epics::pvData::Status &status) = 0;
|
||||
virtual void getDone(const epics::pvData::Status& status) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -182,6 +201,7 @@ namespace epics { namespace pvAccess {
|
||||
*/
|
||||
class ChannelProcess : public ChannelRequest {
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelProcess);
|
||||
|
||||
/**
|
||||
* Issue a process request.
|
||||
@@ -200,6 +220,7 @@ namespace epics { namespace pvAccess {
|
||||
*/
|
||||
class ChannelProcessRequester : virtual public epics::pvData::Requester {
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelProcessRequester);
|
||||
|
||||
/**
|
||||
* The client and server have both completed the createChannelProcess request.
|
||||
@@ -207,13 +228,13 @@ namespace epics { namespace pvAccess {
|
||||
* @param channelProcess The channelProcess interface or null if the client could not become
|
||||
* the record processor.
|
||||
*/
|
||||
virtual void channelProcessConnect(const epics::pvData::Status &status,ChannelProcess *channelProcess) = 0;
|
||||
virtual void channelProcessConnect(const epics::pvData::Status& status,ChannelProcess::shared_pointer& channelProcess) = 0;
|
||||
|
||||
/**
|
||||
* The process request is done. This is always called with no locks held.
|
||||
* @param status Completion status.
|
||||
*/
|
||||
virtual void processDone(const epics::pvData::Status &status) = 0;
|
||||
virtual void processDone(const epics::pvData::Status& status) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -224,6 +245,7 @@ namespace epics { namespace pvAccess {
|
||||
*/
|
||||
class ChannelPut : public ChannelRequest {
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelPut);
|
||||
|
||||
/**
|
||||
* Put data to a channel.
|
||||
@@ -247,6 +269,7 @@ namespace epics { namespace pvAccess {
|
||||
*/
|
||||
class ChannelPutRequester : virtual public epics::pvData::Requester {
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelPutRequester);
|
||||
|
||||
/**
|
||||
* The client and server have both processed the createChannelPut request.
|
||||
@@ -255,20 +278,20 @@ namespace epics { namespace pvAccess {
|
||||
* @param pvStructure The PVStructure that holds the data.
|
||||
* @param bitSet The bitSet for that shows what data has changed.
|
||||
*/
|
||||
virtual void channelPutConnect(const epics::pvData::Status &status,ChannelPut *channelPut,
|
||||
epics::pvData::PVStructure *pvStructure,epics::pvData::BitSet *bitSet) = 0;
|
||||
virtual void channelPutConnect(const epics::pvData::Status& status,ChannelPut::shared_pointer& channelPut,
|
||||
epics::pvData::PVStructure::shared_pointer& pvStructure,epics::pvData::BitSet::shared_pointer& bitSet) = 0;
|
||||
|
||||
/**
|
||||
* The request is done. This is always called with no locks held.
|
||||
* @param status Completion status.
|
||||
*/
|
||||
virtual void putDone(const epics::pvData::Status &status) = 0;
|
||||
virtual void putDone(const epics::pvData::Status& status) = 0;
|
||||
|
||||
/**
|
||||
* The get request is done. This is always called with no locks held.
|
||||
* @param status Completion status.
|
||||
*/
|
||||
virtual void getDone(const epics::pvData::Status &status) = 0;
|
||||
virtual void getDone(const epics::pvData::Status& status) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -280,6 +303,7 @@ namespace epics { namespace pvAccess {
|
||||
*/
|
||||
class ChannelPutGet : public ChannelRequest {
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelPutGet);
|
||||
|
||||
/**
|
||||
* Issue a put/get request. If process was requested when the ChannelPutGet was created this is a put, process, get.
|
||||
@@ -309,6 +333,7 @@ namespace epics { namespace pvAccess {
|
||||
class ChannelPutGetRequester : virtual public epics::pvData::Requester
|
||||
{
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelPutGetRequester);
|
||||
|
||||
/**
|
||||
* The client and server have both completed the createChannelPutGet request.
|
||||
@@ -317,25 +342,25 @@ namespace epics { namespace pvAccess {
|
||||
* @param pvPutStructure The PVStructure that holds the putData.
|
||||
* @param pvGetStructure The PVStructure that holds the getData.
|
||||
*/
|
||||
virtual void channelPutGetConnect(const epics::pvData::Status &status,ChannelPutGet *channelPutGet,
|
||||
epics::pvData::PVStructure *pvPutStructure,epics::pvData::PVStructure *pvGetStructure) = 0;
|
||||
virtual void channelPutGetConnect(const epics::pvData::Status& status,ChannelPutGet::shared_pointer& channelPutGet,
|
||||
epics::pvData::PVStructure::shared_pointer& pvPutStructure,epics::pvData::PVStructure::shared_pointer& pvGetStructure) = 0;
|
||||
/**
|
||||
* The putGet request is done. This is always called with no locks held.
|
||||
* @param status Completion status.
|
||||
*/
|
||||
virtual void putGetDone(const epics::pvData::Status &status) = 0;
|
||||
virtual void putGetDone(const epics::pvData::Status& status) = 0;
|
||||
|
||||
/**
|
||||
* The getPut request is done. This is always called with no locks held.
|
||||
* @param status Completion status.
|
||||
*/
|
||||
virtual void getPutDone(const epics::pvData::Status &status) = 0;
|
||||
virtual void getPutDone(const epics::pvData::Status& status) = 0;
|
||||
|
||||
/**
|
||||
* The getGet request is done. This is always called with no locks held.
|
||||
* @param status Completion status.
|
||||
*/
|
||||
virtual void getGetDone(const epics::pvData::Status &status) = 0;
|
||||
virtual void getGetDone(const epics::pvData::Status& status) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -346,6 +371,7 @@ namespace epics { namespace pvAccess {
|
||||
*/
|
||||
class ChannelRPC : public ChannelRequest {
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelRPC);
|
||||
|
||||
/**
|
||||
* Issue an RPC request to the channel.
|
||||
@@ -363,6 +389,7 @@ namespace epics { namespace pvAccess {
|
||||
*/
|
||||
class ChannelRPCRequester : virtual public epics::pvData::Requester {
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelRPCRequester);
|
||||
|
||||
/**
|
||||
* The client and server have both completed the createChannelGet request.
|
||||
@@ -371,15 +398,15 @@ namespace epics { namespace pvAccess {
|
||||
* @param pvArgument The argument structure for an RPC request.
|
||||
* @param bitSet The bitSet for argument changes.
|
||||
*/
|
||||
virtual void channelRPCConnect(const epics::pvData::Status &status,ChannelRPC *channelRPC,
|
||||
epics::pvData::PVStructure *pvArgument,epics::pvData::BitSet *bitSet) = 0;
|
||||
virtual void channelRPCConnect(const epics::pvData::Status& status,ChannelRPC::shared_pointer& channelRPC,
|
||||
epics::pvData::PVStructure::shared_pointer& pvArgument,epics::pvData::BitSet::shared_pointer& bitSet) = 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.
|
||||
*/
|
||||
virtual void requestDone(const epics::pvData::Status &status,epics::pvData::PVStructure *pvResponse) = 0;
|
||||
virtual void requestDone(const epics::pvData::Status& status,epics::pvData::PVStructure::shared_pointer& pvResponse) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -390,13 +417,15 @@ namespace epics { namespace pvAccess {
|
||||
*/
|
||||
class GetFieldRequester : virtual public epics::pvData::Requester {
|
||||
public:
|
||||
POINTER_DEFINITIONS(GetFieldRequester);
|
||||
|
||||
/**
|
||||
* The client and server have both completed the getStructure request.
|
||||
* @param status Completion status.
|
||||
* @param field The Structure for the request.
|
||||
*/
|
||||
virtual void getDone(const epics::pvData::Status &status,epics::pvData::FieldConstPtr field) = 0;
|
||||
// TODO naming convention
|
||||
virtual void getDone(const epics::pvData::Status& status,epics::pvData::FieldConstPtr& field) = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -413,6 +442,7 @@ namespace epics { namespace pvAccess {
|
||||
public epics::pvData::Destroyable,
|
||||
private epics::pvData::NoDefaultMethods {
|
||||
public:
|
||||
POINTER_DEFINITIONS(Channel);
|
||||
|
||||
/**
|
||||
* Channel connection status.
|
||||
@@ -427,7 +457,8 @@ namespace epics { namespace pvAccess {
|
||||
* Get the the channel provider of this channel.
|
||||
* @return The channel provider.
|
||||
*/
|
||||
virtual ChannelProvider* getProvider() = 0;
|
||||
virtual std::tr1::shared_ptr<ChannelProvider> getProvider() = 0;
|
||||
// virtual ChannelProvider::shared_pointer getProvider() = 0;
|
||||
|
||||
/**
|
||||
* Returns the channel's remote address, e.g. "/192.168.1.101:5064" or "#C0 S1".
|
||||
@@ -451,7 +482,8 @@ namespace epics { namespace pvAccess {
|
||||
* Get the channel epics::pvData::Requester.
|
||||
* @return The epics::pvData::Requester.
|
||||
*/
|
||||
virtual ChannelRequester* getChannelRequester() = 0;
|
||||
// virtual ChannelRequester::shared_pointer getChannelRequester() = 0;
|
||||
virtual std::tr1::shared_ptr<ChannelRequester> getChannelRequester() = 0;
|
||||
|
||||
/**
|
||||
* Is the channel connected?
|
||||
@@ -467,7 +499,7 @@ namespace epics { namespace pvAccess {
|
||||
* @param subField The name of the subField.
|
||||
* If this is null or an empty epics::pvData::String the returned Field is for the entire record.
|
||||
*/
|
||||
virtual void getField(GetFieldRequester *requester,epics::pvData::String subField) = 0;
|
||||
virtual void getField(GetFieldRequester::shared_pointer& requester,epics::pvData::String subField) = 0;
|
||||
|
||||
/**
|
||||
* Get the access rights for a field of a PVStructure created via a call to createPVStructure.
|
||||
@@ -475,7 +507,7 @@ namespace epics { namespace pvAccess {
|
||||
* @param pvField The field for which access rights is desired.
|
||||
* @return The access rights.
|
||||
*/
|
||||
virtual AccessRights getAccessRights(epics::pvData::PVField *pvField) = 0;
|
||||
virtual AccessRights getAccessRights(epics::pvData::PVField::shared_pointer& pvField) = 0;
|
||||
|
||||
/**
|
||||
* Create a ChannelProcess.
|
||||
@@ -486,9 +518,9 @@ namespace epics { namespace pvAccess {
|
||||
* @param pvRequest Additional options (e.g. triggering).
|
||||
* @return <code>ChannelProcess</code> instance.
|
||||
*/
|
||||
virtual ChannelProcess* createChannelProcess(
|
||||
ChannelProcessRequester *channelProcessRequester,
|
||||
epics::pvData::PVStructure *pvRequest) = 0;
|
||||
virtual ChannelProcess::shared_pointer createChannelProcess(
|
||||
ChannelProcessRequester::shared_pointer& channelProcessRequester,
|
||||
epics::pvData::PVStructure::shared_pointer& pvRequest) = 0;
|
||||
|
||||
/**
|
||||
* Create a ChannelGet.
|
||||
@@ -500,9 +532,9 @@ namespace epics { namespace pvAccess {
|
||||
* This has the same form as a pvRequest to PVCopyFactory.create.
|
||||
* @return <code>ChannelGet</code> instance.
|
||||
*/
|
||||
virtual ChannelGet* createChannelGet(
|
||||
ChannelGetRequester *channelGetRequester,
|
||||
epics::pvData::PVStructure *pvRequest) = 0;
|
||||
virtual ChannelGet::shared_pointer createChannelGet(
|
||||
ChannelGetRequester::shared_pointer& channelGetRequester,
|
||||
epics::pvData::PVStructure::shared_pointer& pvRequest) = 0;
|
||||
|
||||
/**
|
||||
* Create a ChannelPut.
|
||||
@@ -514,9 +546,9 @@ namespace epics { namespace pvAccess {
|
||||
* This has the same form as a pvRequest to PVCopyFactory.create.
|
||||
* @return <code>ChannelPut</code> instance.
|
||||
*/
|
||||
virtual ChannelPut* createChannelPut(
|
||||
ChannelPutRequester *channelPutRequester,
|
||||
epics::pvData::PVStructure *pvRequest) = 0;
|
||||
virtual ChannelPut::shared_pointer createChannelPut(
|
||||
ChannelPutRequester::shared_pointer& channelPutRequester,
|
||||
epics::pvData::PVStructure::shared_pointer& pvRequest) = 0;
|
||||
|
||||
/**
|
||||
* Create a ChannelPutGet.
|
||||
@@ -528,9 +560,9 @@ namespace epics { namespace pvAccess {
|
||||
* This has the same form as a pvRequest to PVCopyFactory.create.
|
||||
* @return <code>ChannelPutGet</code> instance.
|
||||
*/
|
||||
virtual ChannelPutGet* createChannelPutGet(
|
||||
ChannelPutGetRequester *channelPutGetRequester,
|
||||
epics::pvData::PVStructure *pvRequest) = 0;
|
||||
virtual ChannelPutGet::shared_pointer createChannelPutGet(
|
||||
ChannelPutGetRequester::shared_pointer& channelPutGetRequester,
|
||||
epics::pvData::PVStructure::shared_pointer& pvRequest) = 0;
|
||||
|
||||
/**
|
||||
* Create a ChannelRPC (Remote Procedure Call).
|
||||
@@ -538,8 +570,9 @@ namespace epics { namespace pvAccess {
|
||||
* @param pvRequest Request options.
|
||||
* @return <code>ChannelRPC</code> instance.
|
||||
*/
|
||||
virtual ChannelRPC* createChannelRPC(ChannelRPCRequester *channelRPCRequester,
|
||||
epics::pvData::PVStructure *pvRequest) = 0;
|
||||
virtual ChannelRPC::shared_pointer createChannelRPC(
|
||||
ChannelRPCRequester::shared_pointer& channelRPCRequester,
|
||||
epics::pvData::PVStructure::shared_pointer& pvRequest) = 0;
|
||||
|
||||
/**
|
||||
* Create a Monitor.
|
||||
@@ -548,9 +581,9 @@ namespace epics { namespace pvAccess {
|
||||
* This has the same form as a pvRequest to PVCopyFactory.create.
|
||||
* @return <code>Monitor</code> instance.
|
||||
*/
|
||||
virtual epics::pvData::Monitor* createMonitor(
|
||||
epics::pvData::MonitorRequester *monitorRequester,
|
||||
epics::pvData::PVStructure *pvRequest) = 0;
|
||||
virtual epics::pvData::Monitor::shared_pointer createMonitor(
|
||||
epics::pvData::MonitorRequester::shared_pointer& monitorRequester,
|
||||
epics::pvData::PVStructure::shared_pointer& pvRequest) = 0;
|
||||
|
||||
/**
|
||||
* Create a ChannelArray.
|
||||
@@ -558,9 +591,9 @@ namespace epics { namespace pvAccess {
|
||||
* @param pvRequest Additional options (e.g. triggering).
|
||||
* @return <code>ChannelArray</code> instance.
|
||||
*/
|
||||
virtual ChannelArray* createChannelArray(
|
||||
ChannelArrayRequester *channelArrayRequester,
|
||||
epics::pvData::PVStructure *pvRequest) = 0;
|
||||
virtual ChannelArray::shared_pointer createChannelArray(
|
||||
ChannelArrayRequester::shared_pointer& channelArrayRequester,
|
||||
epics::pvData::PVStructure::shared_pointer& pvRequest) = 0;
|
||||
|
||||
/**
|
||||
* Prints detailed information about the context to the standard output stream.
|
||||
@@ -582,49 +615,23 @@ namespace epics { namespace pvAccess {
|
||||
*/
|
||||
class ChannelRequester : public virtual epics::pvData::Requester {
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelRequester);
|
||||
|
||||
/**
|
||||
* A channel has been created. This may be called multiple times if there are multiple providers.
|
||||
* @param status Completion status.
|
||||
* @param channel The channel.
|
||||
*/
|
||||
virtual void channelCreated(const epics::pvData::Status &status, Channel *channel) = 0;
|
||||
virtual void channelCreated(const epics::pvData::Status& status, Channel::shared_pointer& channel) = 0;
|
||||
|
||||
/**
|
||||
* A channel connection state change has occurred.
|
||||
* @param c The channel.
|
||||
* @param connectionState The new connection state.
|
||||
*/
|
||||
virtual void channelStateChange(Channel *c, Channel::ConnectionState connectionState) = 0;
|
||||
virtual void channelStateChange(Channel::shared_pointer& channel, Channel::ConnectionState connectionState) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface for locating channel providers.
|
||||
* @author mrk
|
||||
*
|
||||
*/
|
||||
class ChannelAccess : private epics::pvData::NoDefaultMethods {
|
||||
public:
|
||||
virtual ~ChannelAccess() {};
|
||||
|
||||
/**
|
||||
* Get the provider with the specified name.
|
||||
* @param providerName The name of the provider.
|
||||
* @return The interface for the provider or null if the provider is not known.
|
||||
*/
|
||||
virtual ChannelProvider* getProvider(epics::pvData::String providerName) = 0;
|
||||
|
||||
/**
|
||||
* Get a array of the names of all the known providers.
|
||||
* @return The names. Be sure to delete vector instance.
|
||||
*/
|
||||
virtual std::vector<epics::pvData::String>* getProviderNames() = 0;
|
||||
};
|
||||
|
||||
extern ChannelAccess * getChannelAccess();
|
||||
extern void registerChannelProvider(ChannelProvider *channelProvider);
|
||||
extern void unregisterChannelProvider(ChannelProvider *channelProvider);
|
||||
|
||||
/**
|
||||
* Interface implemented by code that can provide access to the record
|
||||
* to which a channel connects.
|
||||
@@ -633,6 +640,7 @@ namespace epics { namespace pvAccess {
|
||||
*/
|
||||
class ChannelProvider : public epics::pvData::Destroyable, private epics::pvData::NoDefaultMethods {
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelProvider);
|
||||
|
||||
/** Minimal priority. */
|
||||
static const short PRIORITY_MIN = 0;
|
||||
@@ -659,7 +667,8 @@ namespace epics { namespace pvAccess {
|
||||
* @param channelFindRequester The epics::pvData::Requester.
|
||||
* @return An interface for the find.
|
||||
*/
|
||||
virtual ChannelFind* channelFind(epics::pvData::String channelName,ChannelFindRequester *channelFindRequester) = 0;
|
||||
virtual ChannelFind::shared_pointer channelFind(epics::pvData::String channelName,
|
||||
ChannelFindRequester::shared_pointer& channelFindRequester) = 0;
|
||||
|
||||
/**
|
||||
* Create a channel.
|
||||
@@ -668,7 +677,8 @@ namespace epics { namespace pvAccess {
|
||||
* @param priority channel priority, must be <code>PRIORITY_MIN</code> <= priority <= <code>PRIORITY_MAX</code>.
|
||||
* @return <code>Channel</code> instance. If channel does not exist <code>null</code> is returned and <code>channelRequester</code> notified.
|
||||
*/
|
||||
virtual Channel* createChannel(epics::pvData::String channelName,ChannelRequester *channelRequester,short priority = PRIORITY_DEFAULT) = 0;
|
||||
virtual Channel::shared_pointer createChannel(epics::pvData::String channelName,ChannelRequester::shared_pointer& channelRequester,
|
||||
short priority = PRIORITY_DEFAULT) = 0;
|
||||
|
||||
/**
|
||||
* Create a channel.
|
||||
@@ -678,9 +688,41 @@ namespace epics { namespace pvAccess {
|
||||
* @param address address (or list of addresses) where to look for a channel. Implementation independed epics::pvData::String.
|
||||
* @return <code>Channel</code> instance. If channel does not exist <code>null</code> is returned and <code>channelRequester</code> notified.
|
||||
*/
|
||||
virtual Channel* createChannel(epics::pvData::String channelName,ChannelRequester *channelRequester,short priority,epics::pvData::String address) = 0;
|
||||
virtual Channel::shared_pointer createChannel(epics::pvData::String channelName,ChannelRequester::shared_pointer& channelRequester,
|
||||
short priority, epics::pvData::String address) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface for locating channel providers.
|
||||
* @author mrk
|
||||
*
|
||||
*/
|
||||
class ChannelAccess : private epics::pvData::NoDefaultMethods {
|
||||
public:
|
||||
POINTER_DEFINITIONS(ChannelAccess);
|
||||
|
||||
typedef std::vector<epics::pvData::String> stringVector_t;
|
||||
|
||||
virtual ~ChannelAccess() {};
|
||||
|
||||
/**
|
||||
* Get the provider with the specified name.
|
||||
* @param providerName The name of the provider.
|
||||
* @return The interface for the provider or null if the provider is not known.
|
||||
*/
|
||||
virtual ChannelProvider::shared_pointer getProvider(epics::pvData::String providerName) = 0;
|
||||
|
||||
/**
|
||||
* Get a array of the names of all the known providers.
|
||||
* @return The names. Be sure to delete vector instance.
|
||||
*/
|
||||
virtual std::auto_ptr<stringVector_t> getProviderNames() = 0;
|
||||
};
|
||||
|
||||
extern ChannelAccess::shared_pointer getChannelAccess();
|
||||
extern void registerChannelProvider(ChannelProvider::shared_pointer& channelProvider);
|
||||
extern void unregisterChannelProvider(ChannelProvider::shared_pointer& channelProvider);
|
||||
|
||||
|
||||
/**
|
||||
* The class representing a CA Client Context.
|
||||
@@ -688,12 +730,13 @@ namespace epics { namespace pvAccess {
|
||||
*/
|
||||
class ClientContext : public epics::pvData::Destroyable, private epics::pvData::NoDefaultMethods {
|
||||
public:
|
||||
POINTER_DEFINITIONS(ClientContext);
|
||||
|
||||
/**
|
||||
* Get context implementation version.
|
||||
* @return version of the context implementation.
|
||||
*/
|
||||
virtual Version* getVersion() = 0;
|
||||
virtual Version& getVersion() = 0;
|
||||
|
||||
/**
|
||||
* Initialize client context. This method is called immediately after instance construction (call of constructor).
|
||||
@@ -704,7 +747,7 @@ namespace epics { namespace pvAccess {
|
||||
* Get channel provider implementation.
|
||||
* @return the channel provider.
|
||||
*/
|
||||
virtual ChannelProvider* getProvider() = 0;
|
||||
virtual ChannelProvider::shared_pointer getProvider() = 0;
|
||||
|
||||
/**
|
||||
* Prints detailed information about the context to the standard output stream.
|
||||
@@ -732,6 +775,8 @@ namespace epics { namespace pvAccess {
|
||||
*/
|
||||
class CreateRequest : private epics::pvData::NoDefaultMethods {
|
||||
public:
|
||||
POINTER_DEFINITIONS(CreateRequest);
|
||||
|
||||
virtual ~CreateRequest() {};
|
||||
|
||||
/**
|
||||
@@ -741,10 +786,10 @@ namespace epics { namespace pvAccess {
|
||||
* @param requester The requester;
|
||||
* @return The request structure if an invalid request was given.
|
||||
*/
|
||||
virtual epics::pvData::PVStructure* createRequest(String request, epics::pvData::Requester* requester) = 0;
|
||||
virtual epics::pvData::PVStructure::shared_pointer createRequest(String request) = 0;
|
||||
};
|
||||
|
||||
extern CreateRequest * getCreateRequest();
|
||||
extern CreateRequest::shared_pointer getCreateRequest();
|
||||
|
||||
|
||||
}}
|
||||
|
||||
@@ -12,25 +12,25 @@ using namespace epics::pvData;
|
||||
|
||||
namespace epics { namespace pvAccess {
|
||||
|
||||
static ChannelAccess* channelAccess = 0;
|
||||
static ChannelAccess::shared_pointer channelAccess;
|
||||
|
||||
static Mutex channelProviderMutex;
|
||||
|
||||
typedef std::map<String, ChannelProvider*> ChannelProviderMap;
|
||||
typedef std::map<String, ChannelProvider::shared_pointer> ChannelProviderMap;
|
||||
static ChannelProviderMap channelProviders;
|
||||
|
||||
|
||||
class ChannelAccessImpl : public ChannelAccess {
|
||||
public:
|
||||
|
||||
ChannelProvider* getProvider(String providerName) {
|
||||
ChannelProvider::shared_pointer getProvider(String providerName) {
|
||||
Lock guard(channelProviderMutex);
|
||||
return channelProviders[providerName];
|
||||
}
|
||||
|
||||
std::vector<String>* getProviderNames() {
|
||||
std::auto_ptr<stringVector_t> getProviderNames() {
|
||||
Lock guard(channelProviderMutex);
|
||||
std::vector<String>* providers = new std::vector<String>();
|
||||
std::auto_ptr<stringVector_t> providers(new stringVector_t());
|
||||
for (ChannelProviderMap::const_iterator i = channelProviders.begin();
|
||||
i != channelProviders.end(); i++)
|
||||
providers->push_back(i->first);
|
||||
@@ -39,22 +39,22 @@ class ChannelAccessImpl : public ChannelAccess {
|
||||
}
|
||||
};
|
||||
|
||||
ChannelAccess * getChannelAccess() {
|
||||
ChannelAccess::shared_pointer getChannelAccess() {
|
||||
static Mutex mutex;
|
||||
Lock guard(mutex);
|
||||
|
||||
if(channelAccess==0){
|
||||
channelAccess = new ChannelAccessImpl();
|
||||
if(channelAccess.get()==0){
|
||||
channelAccess.reset(new ChannelAccessImpl());
|
||||
}
|
||||
return channelAccess;
|
||||
}
|
||||
|
||||
void registerChannelProvider(ChannelProvider *channelProvider) {
|
||||
void registerChannelProvider(ChannelProvider::shared_pointer& channelProvider) {
|
||||
Lock guard(channelProviderMutex);
|
||||
channelProviders[channelProvider->getProviderName()] = channelProvider;
|
||||
}
|
||||
|
||||
void unregisterChannelProvider(ChannelProvider *channelProvider) {
|
||||
void unregisterChannelProvider(ChannelProvider::shared_pointer& channelProvider) {
|
||||
Lock guard(channelProviderMutex);
|
||||
channelProviders.erase(channelProvider->getProviderName());
|
||||
}
|
||||
|
||||
@@ -12,254 +12,210 @@
|
||||
|
||||
using namespace epics::pvData;
|
||||
|
||||
|
||||
namespace epics { namespace pvAccess {
|
||||
|
||||
class CreateRequestImpl : public CreateRequest {
|
||||
private:
|
||||
|
||||
static void trim(std::string& str)
|
||||
{
|
||||
std::string::size_type pos = str.find_last_not_of(' ');
|
||||
if(pos != std::string::npos) {
|
||||
str.erase(pos + 1);
|
||||
pos = str.find_first_not_of(' ');
|
||||
if(pos != std::string::npos) str.erase(0, pos);
|
||||
}
|
||||
else str.erase(str.begin(), str.end());
|
||||
}
|
||||
|
||||
static int findMatchingBrace(std::string& request, int index, int numOpen) {
|
||||
size_t openBrace = request.find('{', index+1);
|
||||
size_t closeBrace = request.find('}', index+1);
|
||||
if(openBrace == std::string::npos && closeBrace == std::string::npos) return std::string::npos;
|
||||
if (openBrace != std::string::npos) {
|
||||
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 bool createFieldRequest(PVStructure* pvParent,std::string request,bool fieldListOK,Requester* requester) {
|
||||
trim(request);
|
||||
if(request.length()<=0) return true;
|
||||
size_t comma = request.find(',');
|
||||
size_t openBrace = request.find('{');
|
||||
size_t openBracket = request.find('[');
|
||||
if(openBrace != std::string::npos || openBracket != std::string::npos) fieldListOK = false;
|
||||
if(openBrace != std::string::npos && (comma==std::string::npos || comma>openBrace)) {
|
||||
//find matching brace
|
||||
size_t closeBrace = findMatchingBrace(request,openBrace+1,1);
|
||||
if(closeBrace==std::string::npos) {
|
||||
requester->message(request + "mismatched { }", errorMessage);
|
||||
return false;
|
||||
}
|
||||
String fieldName = request.substr(0,openBrace);
|
||||
PVStructure* pvStructure = getPVDataCreate()->createPVStructure(pvParent, fieldName, 0);
|
||||
createFieldRequest(pvStructure,request.substr(openBrace+1,closeBrace-openBrace-1),false,requester);
|
||||
// error check?
|
||||
pvParent->appendPVField(pvStructure);
|
||||
if(request.length()>closeBrace+1) {
|
||||
if(request.at(closeBrace+1) != ',') {
|
||||
requester->message(request + "misssing , after }", errorMessage);
|
||||
return false;
|
||||
}
|
||||
if(!createFieldRequest(pvParent,request.substr(closeBrace+2),false,requester)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if(openBracket==std::string::npos && fieldListOK) {
|
||||
PVString* pvStringField = static_cast<PVString*>(getPVDataCreate()->createPVScalar(pvParent, "fieldList", pvString));
|
||||
pvStringField->put(request);
|
||||
pvParent->appendPVField(pvStringField);
|
||||
return true;
|
||||
}
|
||||
if(openBracket!=std::string::npos && (comma==std::string::npos || comma>openBracket)) {
|
||||
size_t closeBracket = request.find(']');
|
||||
if(closeBracket==std::string::npos) {
|
||||
requester->message(request + "option does not have matching []", errorMessage);
|
||||
return false;
|
||||
}
|
||||
if(!createLeafFieldRequest(pvParent,request.substr(0, closeBracket+1),requester)) return false;
|
||||
size_t commaLoc = request.rfind(',');
|
||||
if(commaLoc!=std::string::npos && commaLoc>closeBracket) {
|
||||
int nextComma = request.find(',', closeBracket);
|
||||
if(!createFieldRequest(pvParent,request.substr(nextComma+1),false,requester)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if(comma!=std::string::npos) {
|
||||
if(!createLeafFieldRequest(pvParent,request.substr(0, comma),requester)) return false;
|
||||
return createFieldRequest(pvParent,request.substr(comma+1),false,requester);
|
||||
}
|
||||
return createLeafFieldRequest(pvParent,request,requester);
|
||||
}
|
||||
|
||||
static bool createLeafFieldRequest(PVStructure* pvParent,String request,Requester* requester) {
|
||||
size_t openBracket = request.find('[');
|
||||
String fullName = request;
|
||||
if(openBracket != std::string::npos) fullName = request.substr(0,openBracket);
|
||||
size_t indLast = fullName.rfind('.');
|
||||
String fieldName = fullName;
|
||||
if(indLast>1 && indLast != std::string::npos) fieldName = fullName.substr(indLast+1);
|
||||
PVStructure* pvStructure = getPVDataCreate()->createPVStructure(pvParent, fieldName, 0);
|
||||
PVStructure* pvLeaf = getPVDataCreate()->createPVStructure(pvStructure,"leaf", 0);
|
||||
PVString* pvStringField = static_cast<PVString*>(getPVDataCreate()->createPVScalar(pvLeaf, "source", pvString));
|
||||
pvStringField->put(fullName);
|
||||
pvLeaf->appendPVField(pvStringField);
|
||||
if(openBracket != std::string::npos) {
|
||||
size_t closeBracket = request.find(']');
|
||||
if(closeBracket==std::string::npos) {
|
||||
delete pvLeaf;
|
||||
delete pvStructure;
|
||||
requester->message("option does not have matching []", errorMessage);
|
||||
return false;
|
||||
}
|
||||
if(!createRequestOptions(pvLeaf,request.substr(openBracket+1, closeBracket-openBracket-1),requester))
|
||||
{
|
||||
delete pvLeaf;
|
||||
delete pvStructure;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
pvStructure->appendPVField(pvLeaf);
|
||||
pvParent->appendPVField(pvStructure);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool createRequestOptions(PVStructure* pvParent,std::string request,Requester* requester) {
|
||||
trim(request);
|
||||
if(request.length()<=1) return true;
|
||||
|
||||
std::string token;
|
||||
std::istringstream iss(request);
|
||||
while (getline(iss, token, ','))
|
||||
{
|
||||
size_t equalsPos = token.find('=');
|
||||
size_t equalsRPos = token.rfind('=');
|
||||
if (equalsPos != equalsRPos)
|
||||
{
|
||||
requester->message("illegal option", errorMessage);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (equalsPos != std::string::npos)
|
||||
{
|
||||
PVString* pvStringField = static_cast<PVString*>(getPVDataCreate()->createPVScalar(pvParent, token.substr(0, equalsPos), pvString));
|
||||
pvStringField->put(token.substr(equalsPos+1));
|
||||
pvParent->appendPVField(pvStringField);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
virtual PVStructure* createRequest(String request, Requester* requester)
|
||||
{
|
||||
static String emptyString;
|
||||
if (!request.empty()) trim(request);
|
||||
if (request.empty())
|
||||
{
|
||||
return getPVDataCreate()->createPVStructure(0, emptyString, 0);
|
||||
}
|
||||
private:
|
||||
|
||||
size_t offsetRecord = request.find("record[");
|
||||
size_t offsetField = request.find("field(");
|
||||
size_t offsetPutField = request.find("putField(");
|
||||
size_t offsetGetField = request.find("getField(");
|
||||
static void trim(std::string& str)
|
||||
{
|
||||
std::string::size_type pos = str.find_last_not_of(' ');
|
||||
if(pos != std::string::npos) {
|
||||
str.erase(pos + 1);
|
||||
pos = str.find_first_not_of(' ');
|
||||
if(pos != std::string::npos) str.erase(0, pos);
|
||||
}
|
||||
else str.erase(str.begin(), str.end());
|
||||
}
|
||||
|
||||
PVStructure* pvStructure = getPVDataCreate()->createPVStructure(0, emptyString, 0);
|
||||
static size_t findMatchingBrace(std::string& request, int index, int numOpen) {
|
||||
size_t openBrace = request.find('{', index+1);
|
||||
size_t closeBrace = request.find('}', index+1);
|
||||
if(openBrace == std::string::npos && closeBrace == std::string::npos) return std::string::npos;
|
||||
if (openBrace != std::string::npos) {
|
||||
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 void createFieldRequest(PVStructure* pvParent,std::string request,bool fieldListOK) {
|
||||
trim(request);
|
||||
if(request.length()<=0) return;
|
||||
size_t comma = request.find(',');
|
||||
size_t openBrace = request.find('{');
|
||||
size_t openBracket = request.find('[');
|
||||
if(openBrace != std::string::npos || openBracket != std::string::npos) fieldListOK = false;
|
||||
if(openBrace != std::string::npos && (comma==std::string::npos || comma>openBrace)) {
|
||||
//find matching brace
|
||||
size_t closeBrace = findMatchingBrace(request,openBrace+1,1);
|
||||
if(closeBrace==std::string::npos) {
|
||||
THROW_BASE_EXCEPTION("mismatched { }");
|
||||
}
|
||||
String fieldName = request.substr(0,openBrace);
|
||||
std::auto_ptr<PVStructure> pvStructure(getPVDataCreate()->createPVStructure(pvParent, fieldName, 0));
|
||||
createFieldRequest(pvStructure.get(),request.substr(openBrace+1,closeBrace-openBrace-1),false);
|
||||
pvParent->appendPVField(pvStructure.release());
|
||||
if(request.length()>closeBrace+1) {
|
||||
if(request.at(closeBrace+1) != ',') {
|
||||
THROW_BASE_EXCEPTION("misssing , after }");
|
||||
}
|
||||
createFieldRequest(pvParent,request.substr(closeBrace+2),false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(openBracket==std::string::npos && fieldListOK) {
|
||||
std::auto_ptr<PVString> pvStringField(static_cast<PVString*>(getPVDataCreate()->createPVScalar(pvParent, "fieldList", pvString)));
|
||||
pvStringField->put(request);
|
||||
pvParent->appendPVField(pvStringField.release());
|
||||
return;
|
||||
}
|
||||
if(openBracket!=std::string::npos && (comma==std::string::npos || comma>openBracket)) {
|
||||
size_t closeBracket = request.find(']');
|
||||
if(closeBracket==std::string::npos) {
|
||||
THROW_BASE_EXCEPTION("option does not have matching []");
|
||||
}
|
||||
createLeafFieldRequest(pvParent,request.substr(0, closeBracket+1));
|
||||
size_t commaLoc = request.rfind(',');
|
||||
if(commaLoc!=std::string::npos && commaLoc>closeBracket) {
|
||||
int nextComma = request.find(',', closeBracket);
|
||||
createFieldRequest(pvParent,request.substr(nextComma+1),false);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if(comma!=std::string::npos) {
|
||||
createLeafFieldRequest(pvParent,request.substr(0, comma));
|
||||
createFieldRequest(pvParent,request.substr(comma+1),false);
|
||||
return;
|
||||
}
|
||||
createLeafFieldRequest(pvParent,request);
|
||||
}
|
||||
|
||||
static void createLeafFieldRequest(PVStructure* pvParent,String request) {
|
||||
size_t openBracket = request.find('[');
|
||||
String fullName = request;
|
||||
if(openBracket != std::string::npos) fullName = request.substr(0,openBracket);
|
||||
size_t indLast = fullName.rfind('.');
|
||||
String fieldName = fullName;
|
||||
if(indLast>1 && indLast != std::string::npos) fieldName = fullName.substr(indLast+1);
|
||||
std::auto_ptr<PVStructure> pvStructure(getPVDataCreate()->createPVStructure(pvParent, fieldName, 0));
|
||||
std::auto_ptr<PVStructure> pvLeaf(getPVDataCreate()->createPVStructure(pvStructure.get(),"leaf", 0));
|
||||
std::auto_ptr<PVString> pvStringField(static_cast<PVString*>(getPVDataCreate()->createPVScalar(pvLeaf.get(), "source", pvString)));
|
||||
pvStringField->put(fullName);
|
||||
pvLeaf->appendPVField(pvStringField.release());
|
||||
if(openBracket != std::string::npos) {
|
||||
size_t closeBracket = request.find(']');
|
||||
if(closeBracket==std::string::npos) {
|
||||
THROW_BASE_EXCEPTION("option does not have matching []");
|
||||
}
|
||||
createRequestOptions(pvLeaf.get(),request.substr(openBracket+1, closeBracket-openBracket-1));
|
||||
}
|
||||
pvStructure->appendPVField(pvLeaf.release());
|
||||
pvParent->appendPVField(pvStructure.release());
|
||||
}
|
||||
|
||||
static void createRequestOptions(PVStructure* pvParent,std::string request) {
|
||||
trim(request);
|
||||
if(request.length()<=1) return;
|
||||
|
||||
std::string token;
|
||||
std::istringstream iss(request);
|
||||
while (getline(iss, token, ','))
|
||||
{
|
||||
size_t equalsPos = token.find('=');
|
||||
size_t equalsRPos = token.rfind('=');
|
||||
if (equalsPos != equalsRPos)
|
||||
{
|
||||
THROW_BASE_EXCEPTION("illegal option");
|
||||
}
|
||||
|
||||
if (equalsPos != std::string::npos)
|
||||
{
|
||||
std::auto_ptr<PVString> pvStringField(static_cast<PVString*>(getPVDataCreate()->createPVScalar(pvParent, token.substr(0, equalsPos), pvString)));
|
||||
pvStringField->put(token.substr(equalsPos+1));
|
||||
pvParent->appendPVField(pvStringField.release());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
virtual PVStructure::shared_pointer createRequest(String request)
|
||||
{
|
||||
static String emptyString;
|
||||
if (!request.empty()) trim(request);
|
||||
if (request.empty())
|
||||
{
|
||||
PVStructure::shared_pointer pvStructure(getPVDataCreate()->createPVStructure(0, emptyString, 0));
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
size_t offsetRecord = request.find("record[");
|
||||
size_t offsetField = request.find("field(");
|
||||
size_t offsetPutField = request.find("putField(");
|
||||
size_t offsetGetField = request.find("getField(");
|
||||
|
||||
PVStructure::shared_pointer pvStructure(getPVDataCreate()->createPVStructure(0, emptyString, 0));
|
||||
|
||||
if (offsetRecord != std::string::npos) {
|
||||
size_t offsetBegin = request.find('[', offsetRecord);
|
||||
size_t offsetEnd = request.find(']', offsetBegin);
|
||||
if(offsetEnd == std::string::npos) {
|
||||
THROW_BASE_EXCEPTION("record[ does not have matching ]");
|
||||
}
|
||||
std::auto_ptr<PVStructure> pvStruct(getPVDataCreate()->createPVStructure(pvStructure.get(), "record", 0));
|
||||
createRequestOptions(pvStruct.get(),request.substr(offsetBegin+1, offsetEnd-offsetBegin-1));
|
||||
pvStructure->appendPVField(pvStruct.release());
|
||||
}
|
||||
if (offsetField != std::string::npos) {
|
||||
size_t offsetBegin = request.find('(', offsetField);
|
||||
size_t offsetEnd = request.find(')', offsetBegin);
|
||||
if(offsetEnd == std::string::npos) {
|
||||
THROW_BASE_EXCEPTION("field( does not have matching )");
|
||||
}
|
||||
std::auto_ptr<PVStructure> pvStruct(getPVDataCreate()->createPVStructure(pvStructure.get(), "field", 0));
|
||||
createFieldRequest(pvStruct.get(),request.substr(offsetBegin+1, offsetEnd-offsetBegin-1),true);
|
||||
pvStructure->appendPVField(pvStruct.release());
|
||||
}
|
||||
if (offsetPutField != std::string::npos) {
|
||||
size_t offsetBegin = request.find('(', offsetPutField);
|
||||
size_t offsetEnd = request.find(')', offsetBegin);
|
||||
if(offsetEnd == std::string::npos) {
|
||||
THROW_BASE_EXCEPTION("putField( does not have matching )");
|
||||
}
|
||||
std::auto_ptr<PVStructure> pvStruct(getPVDataCreate()->createPVStructure(pvStructure.get(), "putField", 0));
|
||||
createFieldRequest(pvStruct.get(),request.substr(offsetBegin+1, offsetEnd-offsetBegin-1),true);
|
||||
pvStructure->appendPVField(pvStruct.release());
|
||||
}
|
||||
if (offsetGetField != std::string::npos) {
|
||||
size_t offsetBegin = request.find('(', offsetGetField);
|
||||
size_t offsetEnd = request.find(')', offsetBegin);
|
||||
if(offsetEnd == std::string::npos) {
|
||||
THROW_BASE_EXCEPTION("getField( does not have matching )");
|
||||
}
|
||||
std::auto_ptr<PVStructure> pvStruct(getPVDataCreate()->createPVStructure(pvStructure.get(), "getField", 0));
|
||||
createFieldRequest(pvStruct.get(),request.substr(offsetBegin+1, offsetEnd-offsetBegin-1),true);
|
||||
pvStructure->appendPVField(pvStruct.release());
|
||||
}
|
||||
if (pvStructure.get()->getStructure()->getNumberFields()==0) {
|
||||
createFieldRequest(pvStructure.get(),request,true);
|
||||
}
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
if (offsetRecord != std::string::npos) {
|
||||
size_t offsetBegin = request.find('[', offsetRecord);
|
||||
size_t offsetEnd = request.find(']', offsetBegin);
|
||||
if(offsetEnd == std::string::npos) {
|
||||
delete pvStructure;
|
||||
requester->message("record[ does not have matching ]", errorMessage);
|
||||
return 0;
|
||||
}
|
||||
PVStructure* pvStruct = getPVDataCreate()->createPVStructure(pvStructure, "record", 0);
|
||||
if(!createRequestOptions(pvStruct,request.substr(offsetBegin+1, offsetEnd-offsetBegin-1),requester))
|
||||
{
|
||||
delete pvStruct;
|
||||
delete pvStructure;
|
||||
return 0;
|
||||
}
|
||||
pvStructure->appendPVField(pvStruct);
|
||||
}
|
||||
if (offsetField != std::string::npos) {
|
||||
size_t offsetBegin = request.find('(', offsetField);
|
||||
size_t offsetEnd = request.find(')', offsetBegin);
|
||||
if(offsetEnd == std::string::npos) {
|
||||
delete pvStructure;
|
||||
requester->message("field( does not have matching )", errorMessage);
|
||||
return 0;
|
||||
}
|
||||
PVStructure* pvStruct = getPVDataCreate()->createPVStructure(pvStructure, "field", 0);
|
||||
if(!createFieldRequest(pvStruct,request.substr(offsetBegin+1, offsetEnd-offsetBegin-1),true,requester))
|
||||
{
|
||||
delete pvStruct;
|
||||
delete pvStructure;
|
||||
return 0;
|
||||
}
|
||||
pvStructure->appendPVField(pvStruct);
|
||||
}
|
||||
if (offsetPutField != std::string::npos) {
|
||||
size_t offsetBegin = request.find('(', offsetPutField);
|
||||
size_t offsetEnd = request.find(')', offsetBegin);
|
||||
if(offsetEnd == std::string::npos) {
|
||||
delete pvStructure;
|
||||
requester->message("putField( does not have matching )", errorMessage);
|
||||
return 0;
|
||||
}
|
||||
PVStructure* pvStruct = getPVDataCreate()->createPVStructure(pvStructure, "putField", 0);
|
||||
if(!createFieldRequest(pvStruct,request.substr(offsetBegin+1, offsetEnd-offsetBegin-1),true,requester))
|
||||
{
|
||||
delete pvStruct;
|
||||
delete pvStructure;
|
||||
return 0;
|
||||
}
|
||||
pvStructure->appendPVField(pvStruct);
|
||||
}
|
||||
if (offsetGetField != std::string::npos) {
|
||||
size_t offsetBegin = request.find('(', offsetGetField);
|
||||
size_t offsetEnd = request.find(')', offsetBegin);
|
||||
if(offsetEnd == std::string::npos) {
|
||||
delete pvStructure;
|
||||
requester->message("getField( does not have matching )", errorMessage);
|
||||
return 0;
|
||||
}
|
||||
PVStructure* pvStruct = getPVDataCreate()->createPVStructure(pvStructure, "getField", 0);
|
||||
if(!createFieldRequest(pvStruct,request.substr(offsetBegin+1, offsetEnd-offsetBegin-1),true,requester))
|
||||
{
|
||||
delete pvStruct;
|
||||
delete pvStructure;
|
||||
return 0;
|
||||
}
|
||||
pvStructure->appendPVField(pvStruct);
|
||||
}
|
||||
if (pvStructure->getStructure()->getNumberFields()==0) {
|
||||
if(!createFieldRequest(pvStructure,request,true,requester))
|
||||
{
|
||||
delete pvStructure;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return pvStructure;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
static CreateRequest* createRequest = 0;
|
||||
CreateRequest::shared_pointer createRequest;
|
||||
|
||||
CreateRequest * getCreateRequest() {
|
||||
CreateRequest::shared_pointer getCreateRequest() {
|
||||
static Mutex mutex;
|
||||
Lock guard(mutex);
|
||||
|
||||
if(createRequest==0){
|
||||
createRequest = new CreateRequestImpl();
|
||||
if(createRequest.get()==0){
|
||||
createRequest.reset(new CreateRequestImpl());
|
||||
}
|
||||
return createRequest;
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
*/
|
||||
|
||||
#include "remote.h"
|
||||
#include "hexDump.h"
|
||||
#include <hexDump.h>
|
||||
|
||||
#include <byteBuffer.h>
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
void AbstractResponseHandler::handleResponse(osiSockAddr* responseFrom,
|
||||
Transport* transport, int8 version, int8 command,
|
||||
Transport::shared_pointer& transport, int8 version, int8 command,
|
||||
int payloadSize, ByteBuffer* payloadBuffer) {
|
||||
if(_debug) {
|
||||
char ipAddrStr[48];
|
||||
|
||||
@@ -1,157 +0,0 @@
|
||||
/*
|
||||
* beaconEmitter.cpp
|
||||
*/
|
||||
|
||||
#include "beaconEmitter.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvAccess {
|
||||
|
||||
const float BeaconEmitter::EPICS_CA_MIN_BEACON_PERIOD = 1.0;
|
||||
const float BeaconEmitter::EPICS_CA_MIN_BEACON_COUNT_LIMIT = 3.0;
|
||||
|
||||
BeaconEmitter::BeaconEmitter(Transport* transport, ServerContextImpl* context): _transport(transport)
|
||||
{
|
||||
if(transport == NULL || context == NULL)
|
||||
{
|
||||
THROW_BASE_EXCEPTION("null transport or context");
|
||||
}
|
||||
|
||||
_timer = context->getTimer();
|
||||
_beaconSequenceID = 0;
|
||||
_serverAddress = context->getServerInetAddress();
|
||||
_serverPort = context->getServerPort();
|
||||
_serverStatusProvider = context->getBeaconServerStatusProvider();
|
||||
_fastBeaconPeriod = std::max(context->getBeaconPeriod(), EPICS_CA_MIN_BEACON_PERIOD);
|
||||
_slowBeaconPeriod = std::max(180.0, _fastBeaconPeriod); // TODO configurable
|
||||
_beaconCountLimit = (int16)std::max(10.0f, EPICS_CA_MIN_BEACON_COUNT_LIMIT); // TODO configurable
|
||||
_startupTime = new TimeStamp();
|
||||
_startupTime->getCurrent();
|
||||
_timerNode = new TimerNode(*this);
|
||||
}
|
||||
|
||||
BeaconEmitter::BeaconEmitter(Transport* transport,const osiSockAddr* serverAddress): _transport(transport)
|
||||
{
|
||||
if(transport == NULL)
|
||||
{
|
||||
THROW_BASE_EXCEPTION("null transport");
|
||||
}
|
||||
|
||||
_timer = new Timer("pvAccess-server timer", lowPriority);
|
||||
|
||||
_beaconSequenceID = 0;
|
||||
_serverAddress = serverAddress;
|
||||
_serverPort = serverAddress->ia.sin_port;
|
||||
_serverStatusProvider = NULL;//new BeaconServerStatusProvider();
|
||||
_fastBeaconPeriod = EPICS_CA_MIN_BEACON_PERIOD;
|
||||
_slowBeaconPeriod = 180.0;
|
||||
_beaconCountLimit = 10;
|
||||
_startupTime = new TimeStamp();
|
||||
_startupTime->getCurrent();
|
||||
_timerNode = new TimerNode(*this);
|
||||
}
|
||||
|
||||
BeaconEmitter::~BeaconEmitter()
|
||||
{
|
||||
if(_serverStatusProvider) delete _serverStatusProvider;
|
||||
if(_timerNode) delete _timerNode;
|
||||
if(_startupTime) delete _startupTime;
|
||||
}
|
||||
|
||||
void BeaconEmitter::lock()
|
||||
{
|
||||
//noop
|
||||
}
|
||||
|
||||
void BeaconEmitter::unlock()
|
||||
{
|
||||
//noop
|
||||
}
|
||||
|
||||
void BeaconEmitter::acquire()
|
||||
{
|
||||
//noop
|
||||
}
|
||||
|
||||
void BeaconEmitter::release()
|
||||
{
|
||||
//noop
|
||||
}
|
||||
|
||||
void BeaconEmitter::send(ByteBuffer* buffer, TransportSendControl* control)
|
||||
{
|
||||
// get server status
|
||||
PVFieldPtr serverStatus = NULL;
|
||||
if(_serverStatusProvider != NULL)
|
||||
{
|
||||
try
|
||||
{
|
||||
serverStatus = _serverStatusProvider->getServerStatusData();
|
||||
}
|
||||
catch (...) {
|
||||
// we have to proctect internal code from external implementation...
|
||||
errlogSevPrintf(errlogMinor, "BeaconServerStatusProvider implementation thrown an exception.");
|
||||
}
|
||||
}
|
||||
|
||||
// send beacon
|
||||
control->startMessage((int8)0, (sizeof(int16)+2*sizeof(int32)+128+sizeof(int16))/sizeof(int8));
|
||||
|
||||
buffer->putShort(_beaconSequenceID);
|
||||
buffer->putLong((int64)_startupTime->getSecondsPastEpoch());
|
||||
buffer->putInt((int32)_startupTime->getNanoSeconds());
|
||||
|
||||
// NOTE: is it possible (very likely) that address is any local address ::ffff:0.0.0.0
|
||||
encodeAsIPv6Address(buffer, _serverAddress);
|
||||
buffer->putShort((int16)_serverPort);
|
||||
|
||||
if (serverStatus != NULL)
|
||||
{
|
||||
// introspection interface + data
|
||||
IntrospectionRegistry::serializeFull(serverStatus->getField(), buffer, control);
|
||||
serverStatus->serialize(buffer, control);
|
||||
}
|
||||
else
|
||||
{
|
||||
IntrospectionRegistry::serializeFull(NULL, buffer, control);
|
||||
}
|
||||
control->flush(true);
|
||||
|
||||
// increment beacon sequence ID
|
||||
_beaconSequenceID++;
|
||||
|
||||
reschedule();
|
||||
}
|
||||
|
||||
void BeaconEmitter::timerStopped()
|
||||
{
|
||||
//noop
|
||||
}
|
||||
|
||||
void BeaconEmitter::destroy()
|
||||
{
|
||||
_timerNode->cancel();
|
||||
}
|
||||
|
||||
void BeaconEmitter::start()
|
||||
{
|
||||
_timer->scheduleAfterDelay(*_timerNode, 0.0);
|
||||
}
|
||||
|
||||
void BeaconEmitter::reschedule()
|
||||
{
|
||||
const double period = (_beaconSequenceID >= _beaconCountLimit) ? _slowBeaconPeriod : _fastBeaconPeriod;
|
||||
if (period > 0)
|
||||
{
|
||||
_timer->scheduleAfterDelay(*_timerNode, period);
|
||||
}
|
||||
}
|
||||
|
||||
void BeaconEmitter::callback()
|
||||
{
|
||||
_transport->enqueueSendRequest(this);
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
*/
|
||||
|
||||
#include "beaconHandler.h"
|
||||
#include "transportRegistry.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace epics::pvData;
|
||||
@@ -10,9 +11,9 @@ using namespace epics::pvAccess;
|
||||
|
||||
namespace epics { namespace pvAccess {
|
||||
|
||||
BeaconHandler::BeaconHandler(ClientContextImpl* context,
|
||||
BeaconHandler::BeaconHandler(Context::shared_pointer context,
|
||||
const osiSockAddr* responseFrom)
|
||||
:_context(context)
|
||||
:_context(Context::weak_pointer(context))
|
||||
,_responseFrom(*responseFrom)
|
||||
,_mutex()
|
||||
,_serverStartupTime(0)
|
||||
@@ -54,7 +55,7 @@ bool BeaconHandler::updateBeacon(int8 remoteTransportRevision, TimeStamp* timest
|
||||
_serverStartupTime = *startupTime;
|
||||
|
||||
// new server up..
|
||||
_context->beaconAnomalyNotify();
|
||||
_context.lock()->beaconAnomalyNotify();
|
||||
|
||||
// notify corresponding transport(s)
|
||||
beaconArrivalNotify();
|
||||
@@ -65,7 +66,7 @@ bool BeaconHandler::updateBeacon(int8 remoteTransportRevision, TimeStamp* timest
|
||||
bool networkChange = !(_serverStartupTime == *startupTime);
|
||||
if (networkChange)
|
||||
{
|
||||
_context->beaconAnomalyNotify();
|
||||
_context.lock()->beaconAnomalyNotify();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -77,38 +78,34 @@ bool BeaconHandler::updateBeacon(int8 remoteTransportRevision, TimeStamp* timest
|
||||
|
||||
void BeaconHandler::beaconArrivalNotify()
|
||||
{
|
||||
int32 size = 0;
|
||||
//TODO TCP name must be get from somewhere not hardcoded
|
||||
Transport** transports = _context->getTransportRegistry()->get("TCP", &_responseFrom, size);
|
||||
if (transports == NULL)
|
||||
{
|
||||
auto_ptr<TransportRegistry::transportVector_t> transports =
|
||||
_context.lock()->getTransportRegistry()->get("TCP", &_responseFrom);
|
||||
if (!transports.get())
|
||||
return;
|
||||
}
|
||||
|
||||
// notify all
|
||||
for (int i = 0; i < size; i++)
|
||||
for (TransportRegistry::transportVector_t::iterator iter = transports->begin();
|
||||
iter != transports->end();
|
||||
iter++)
|
||||
{
|
||||
transports[i]->aliveNotification();
|
||||
(*iter)->aliveNotification();
|
||||
}
|
||||
delete[] transports;
|
||||
}
|
||||
|
||||
void BeaconHandler::changedTransport()
|
||||
{
|
||||
int32 size = 0;
|
||||
//TODO TCP name must be get from somewhere not hardcoded
|
||||
Transport** transports = _context->getTransportRegistry()->get("TCP", &_responseFrom, size);
|
||||
if (transports == NULL)
|
||||
{
|
||||
auto_ptr<TransportRegistry::transportVector_t> transports =
|
||||
_context.lock()->getTransportRegistry()->get("TCP", &_responseFrom);
|
||||
if (!transports.get())
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// notify all
|
||||
for (int i = 0; i < size; i++)
|
||||
for (TransportRegistry::transportVector_t::iterator iter = transports->begin();
|
||||
iter != transports->end();
|
||||
iter++)
|
||||
{
|
||||
transports[i]->changedTransport();
|
||||
(*iter)->changedTransport();
|
||||
}
|
||||
delete[] transports;
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
#include "remote.h"
|
||||
#include <pvAccess.h>
|
||||
#include "clientContextImpl.h"
|
||||
|
||||
#include <timeStamp.h>
|
||||
#include <osiSock.h>
|
||||
@@ -21,12 +20,15 @@ namespace epics { namespace pvAccess {
|
||||
class BeaconHandler
|
||||
{
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<BeaconHandler> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const BeaconHandler> const_shared_pointer;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param transport transport to be used to send beacons.
|
||||
* @param context CA context.
|
||||
*/
|
||||
BeaconHandler(ClientContextImpl* context, const osiSockAddr* responseFrom);
|
||||
BeaconHandler(Context::shared_pointer context, const osiSockAddr* responseFrom);
|
||||
/**
|
||||
* Test Constructor (for testing)
|
||||
* @param transport transport to be used to send beacons.
|
||||
@@ -52,7 +54,7 @@ namespace epics { namespace pvAccess {
|
||||
/**
|
||||
* Context instance.
|
||||
*/
|
||||
ClientContextImpl* _context;
|
||||
Context::weak_pointer _context;
|
||||
/**
|
||||
* Remote address.
|
||||
*/
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* beaconServerStatusProvider.h
|
||||
*/
|
||||
|
||||
#ifndef BEACONSERVERSTATUSPROVIDER_H
|
||||
#define BEACONSERVERSTATUSPROVIDER_H
|
||||
|
||||
#include "pvData.h"
|
||||
|
||||
using namespace epics::pvData;
|
||||
|
||||
namespace epics { namespace pvAccess {
|
||||
|
||||
class ServerContext;
|
||||
/**
|
||||
* BeaconServerStatusProvider
|
||||
*/
|
||||
class BeaconServerStatusProvider
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param context CA context.
|
||||
*/
|
||||
BeaconServerStatusProvider(ServerContext* context);
|
||||
/**
|
||||
* Test Constructor (without context)
|
||||
*/
|
||||
BeaconServerStatusProvider();
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~BeaconServerStatusProvider();
|
||||
/**
|
||||
* Gets server status data.
|
||||
*/
|
||||
PVFieldPtr getServerStatusData();
|
||||
private:
|
||||
/**
|
||||
* Initialize
|
||||
*/
|
||||
void initialize();
|
||||
|
||||
|
||||
private:
|
||||
PVStructurePtr _status;
|
||||
ServerContext* _context;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /* INTROSPECTIONREGISTRY_H */
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <epicsTime.h>
|
||||
#include <sstream>
|
||||
|
||||
using std::set;
|
||||
using namespace std;
|
||||
using namespace epics::pvData;
|
||||
|
||||
namespace epics {
|
||||
@@ -31,16 +31,18 @@ namespace epics {
|
||||
catch (std::exception &e) { errlogSevPrintf(errlogMajor, "Unhandled exception caught from code at %s:%d: %s", __FILE__, __LINE__, e.what()); } \
|
||||
catch (...) { errlogSevPrintf(errlogMajor, "Unhandled exception caught from code at %s:%d.", __FILE__, __LINE__); }
|
||||
|
||||
BlockingClientTCPTransport::BlockingClientTCPTransport(
|
||||
Context* context, SOCKET channel,
|
||||
ResponseHandler* responseHandler, int receiveBufferSize,
|
||||
TransportClient* client, short remoteTransportRevision,
|
||||
BlockingClientTCPTransport::BlockingClientTCPTransport(
|
||||
Context::shared_pointer& context, SOCKET channel,
|
||||
auto_ptr<ResponseHandler>& responseHandler, int receiveBufferSize,
|
||||
TransportClient::shared_pointer client, short remoteTransportRevision,
|
||||
float beaconInterval, int16 priority) :
|
||||
BlockingTCPTransport(context, channel, responseHandler,
|
||||
receiveBufferSize, priority), _introspectionRegistry(
|
||||
new IntrospectionRegistry(false)), _connectionTimeout(beaconInterval
|
||||
*1000), _unresponsiveTransport(false), _timerNode(
|
||||
new TimerNode(*this)), _verifyOrEcho(true) {
|
||||
BlockingTCPTransport(context, channel, responseHandler, receiveBufferSize, priority),
|
||||
_introspectionRegistry(false),
|
||||
_connectionTimeout(beaconInterval*1000),
|
||||
_unresponsiveTransport(false),
|
||||
_timerNode(*this),
|
||||
_verifyOrEcho(true)
|
||||
{
|
||||
// _autoDelete = false;
|
||||
|
||||
// initialize owners list, send queue
|
||||
@@ -52,16 +54,13 @@ namespace epics {
|
||||
// setup connection timeout timer (watchdog)
|
||||
epicsTimeGetCurrent(&_aliveTimestamp);
|
||||
|
||||
context->getTimer()->schedulePeriodic(*_timerNode, beaconInterval,
|
||||
beaconInterval);
|
||||
context->getTimer()->schedulePeriodic(_timerNode, beaconInterval, beaconInterval);
|
||||
|
||||
start();
|
||||
//start();
|
||||
|
||||
}
|
||||
|
||||
BlockingClientTCPTransport::~BlockingClientTCPTransport() {
|
||||
delete _introspectionRegistry;
|
||||
delete _timerNode;
|
||||
}
|
||||
|
||||
void BlockingClientTCPTransport::callback() {
|
||||
@@ -79,7 +78,8 @@ namespace epics {
|
||||
// use some k (3/4) to handle "jitter"
|
||||
else if(diff>=((3*_connectionTimeout)/4)) {
|
||||
// send echo
|
||||
enqueueSendRequest(this);
|
||||
TransportSender::shared_pointer transportSender = std::tr1::dynamic_pointer_cast<TransportSender>(shared_from_this());
|
||||
enqueueSendRequest(transportSender);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,17 +88,18 @@ namespace epics {
|
||||
if(!_unresponsiveTransport) {
|
||||
_unresponsiveTransport = true;
|
||||
|
||||
set<TransportClient*>::iterator it = _owners.begin();
|
||||
TransportClientMap_t::iterator it = _owners.begin();
|
||||
for(; it!=_owners.end(); it++) {
|
||||
TransportClient* client = *it;
|
||||
client->acquire();
|
||||
EXCEPTION_GUARD(client->transportUnresponsive());
|
||||
client->release();
|
||||
TransportClient::shared_pointer client = it->second.lock();
|
||||
if (client)
|
||||
{
|
||||
EXCEPTION_GUARD(client->transportUnresponsive());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool BlockingClientTCPTransport::acquire(TransportClient* client) {
|
||||
bool BlockingClientTCPTransport::acquire(TransportClient::shared_pointer& client) {
|
||||
Lock lock(_mutex);
|
||||
if(_closed) return false;
|
||||
|
||||
@@ -108,7 +109,8 @@ namespace epics {
|
||||
|
||||
Lock lock2(_ownersMutex);
|
||||
// TODO double check? if(_closed) return false;
|
||||
_owners.insert(client);
|
||||
//_owners.insert(TransportClient::weak_pointer(client));
|
||||
_owners[client->getID()] = TransportClient::weak_pointer(client);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -116,7 +118,7 @@ namespace epics {
|
||||
void BlockingClientTCPTransport::internalClose(bool forced) {
|
||||
BlockingTCPTransport::internalClose(forced);
|
||||
|
||||
_timerNode->cancel();
|
||||
_timerNode.cancel();
|
||||
|
||||
closedNotifyClients();
|
||||
}
|
||||
@@ -137,12 +139,13 @@ namespace epics {
|
||||
"Transport to %s still has %d client(s) active and closing...",
|
||||
ipAddrStr, refs);
|
||||
|
||||
set<TransportClient*>::iterator it = _owners.begin();
|
||||
TransportClientMap_t::iterator it = _owners.begin();
|
||||
for(; it!=_owners.end(); it++) {
|
||||
TransportClient* client = *it;
|
||||
client->acquire();
|
||||
EXCEPTION_GUARD(client->transportClosed());
|
||||
client->release();
|
||||
TransportClient::shared_pointer client = it->second.lock();
|
||||
if (client)
|
||||
{
|
||||
EXCEPTION_GUARD(client->transportClosed());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -150,7 +153,8 @@ namespace epics {
|
||||
_owners.clear();
|
||||
}
|
||||
|
||||
void BlockingClientTCPTransport::release(TransportClient* client) {
|
||||
//void BlockingClientTCPTransport::release(TransportClient::shared_pointer& client) {
|
||||
void BlockingClientTCPTransport::release(pvAccessID clientID) {
|
||||
Lock lock(_mutex);
|
||||
if(_closed) return;
|
||||
|
||||
@@ -160,9 +164,10 @@ namespace epics {
|
||||
errlogSevPrintf(errlogInfo, "Releasing transport to %s.", ipAddrStr);
|
||||
|
||||
Lock lock2(_ownersMutex);
|
||||
_owners.erase(client);
|
||||
|
||||
// not used anymore
|
||||
_owners.erase(clientID);
|
||||
//_owners.erase(TransportClient::weak_pointer(client));
|
||||
|
||||
// not used anymore, close it
|
||||
// TODO consider delayed destruction (can improve performance!!!)
|
||||
if(_owners.size()==0) close(false);
|
||||
}
|
||||
@@ -178,26 +183,29 @@ namespace epics {
|
||||
if(_unresponsiveTransport) {
|
||||
_unresponsiveTransport = false;
|
||||
|
||||
set<TransportClient*>::iterator it = _owners.begin();
|
||||
Transport::shared_pointer thisSharedPtr = shared_from_this();
|
||||
TransportClientMap_t::iterator it = _owners.begin();
|
||||
for(; it!=_owners.end(); it++) {
|
||||
TransportClient* client = *it;
|
||||
client->acquire();
|
||||
EXCEPTION_GUARD(client->transportResponsive(this));
|
||||
client->release();
|
||||
TransportClient::shared_pointer client = it->second.lock();
|
||||
if (client)
|
||||
{
|
||||
EXCEPTION_GUARD(client->transportResponsive(thisSharedPtr));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void BlockingClientTCPTransport::changedTransport() {
|
||||
_introspectionRegistry->reset();
|
||||
_introspectionRegistry.reset();
|
||||
|
||||
Lock lock(_ownersMutex);
|
||||
set<TransportClient*>::iterator it = _owners.begin();
|
||||
TransportClientMap_t::iterator it = _owners.begin();
|
||||
for(; it!=_owners.end(); it++) {
|
||||
TransportClient* client = *it;
|
||||
client->acquire();
|
||||
EXCEPTION_GUARD(client->transportChanged());
|
||||
client->release();
|
||||
TransportClient::shared_pointer client = it->second.lock();
|
||||
if (client)
|
||||
{
|
||||
EXCEPTION_GUARD(client->transportChanged());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,27 +20,26 @@
|
||||
#include <map>
|
||||
|
||||
using namespace epics::pvData;
|
||||
using std::map;
|
||||
using namespace std;
|
||||
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
BlockingServerTCPTransport::BlockingServerTCPTransport(
|
||||
Context* context, SOCKET channel,
|
||||
ResponseHandler* responseHandler, int receiveBufferSize) :
|
||||
BlockingTCPTransport(context, channel, responseHandler,
|
||||
receiveBufferSize, CA_DEFAULT_PRIORITY),
|
||||
_introspectionRegistry(new IntrospectionRegistry(true)),
|
||||
_lastChannelSID(0) {
|
||||
Context::shared_pointer& context, SOCKET channel,
|
||||
auto_ptr<ResponseHandler>& responseHandler, int receiveBufferSize) :
|
||||
BlockingTCPTransport(context, channel, responseHandler, receiveBufferSize, CA_DEFAULT_PRIORITY),
|
||||
_introspectionRegistry(true),
|
||||
_lastChannelSID(0)
|
||||
{
|
||||
// NOTE: priority not yet known, default priority is used to register/unregister
|
||||
// TODO implement priorities in Reactor... not that user will
|
||||
// change it.. still getPriority() must return "registered" priority!
|
||||
|
||||
start();
|
||||
//start();
|
||||
}
|
||||
|
||||
BlockingServerTCPTransport::~BlockingServerTCPTransport() {
|
||||
delete _introspectionRegistry;
|
||||
}
|
||||
|
||||
void BlockingServerTCPTransport::destroyAllChannels() {
|
||||
@@ -53,9 +52,9 @@ namespace epics {
|
||||
errlogSevPrintf(
|
||||
errlogInfo,
|
||||
"Transport to %s still has %u channel(s) active and closing...",
|
||||
ipAddrStr, _channels.size());
|
||||
ipAddrStr, (unsigned int)_channels.size());
|
||||
|
||||
map<pvAccessID, ServerChannel*>::iterator it = _channels.begin();
|
||||
map<pvAccessID, ServerChannel::shared_pointer>::iterator it = _channels.begin();
|
||||
for(; it!=_channels.end(); it++)
|
||||
it->second->destroy();
|
||||
|
||||
@@ -76,8 +75,7 @@ namespace epics {
|
||||
return sid;
|
||||
}
|
||||
|
||||
void BlockingServerTCPTransport::registerChannel(pvAccessID sid,
|
||||
ServerChannel* channel) {
|
||||
void BlockingServerTCPTransport::registerChannel(pvAccessID sid, ServerChannel::shared_pointer& channel) {
|
||||
Lock lock(_channelsMutex);
|
||||
_channels[sid] = channel;
|
||||
}
|
||||
@@ -87,13 +85,13 @@ namespace epics {
|
||||
_channels.erase(sid);
|
||||
}
|
||||
|
||||
ServerChannel* BlockingServerTCPTransport::getChannel(pvAccessID sid) {
|
||||
ServerChannel::shared_pointer BlockingServerTCPTransport::getChannel(pvAccessID sid) {
|
||||
Lock lock(_channelsMutex);
|
||||
|
||||
map<pvAccessID, ServerChannel*>::iterator it = _channels.find(sid);
|
||||
map<pvAccessID, ServerChannel::shared_pointer>::iterator it = _channels.find(sid);
|
||||
if(it!=_channels.end()) return it->second;
|
||||
|
||||
return NULL;
|
||||
return ServerChannel::shared_pointer();
|
||||
}
|
||||
|
||||
int BlockingServerTCPTransport::getChannelCount() {
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
/* pvAccess */
|
||||
#include "caConstants.h"
|
||||
#include "remote.h"
|
||||
#include "growingCircularBuffer.h"
|
||||
#include "transportRegistry.h"
|
||||
#include "introspectionRegistry.h"
|
||||
#include "namedLockPattern.h"
|
||||
@@ -33,11 +32,12 @@
|
||||
/* standard */
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <deque>
|
||||
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
class MonitorSender;
|
||||
//class MonitorSender;
|
||||
|
||||
enum ReceiveStage {
|
||||
READ_FROM_SOCKET, PROCESS_HEADER, PROCESS_PAYLOAD, NONE
|
||||
@@ -47,13 +47,17 @@ namespace epics {
|
||||
IMMEDIATE, DELAYED, USER_CONTROLED
|
||||
};
|
||||
|
||||
class BlockingTCPTransport : public Transport,
|
||||
public TransportSendControl {
|
||||
public:
|
||||
BlockingTCPTransport(Context* context, SOCKET channel,
|
||||
ResponseHandler* responseHandler, int receiveBufferSize,
|
||||
class BlockingTCPTransport :
|
||||
public Transport,
|
||||
public TransportSendControl,
|
||||
public std::tr1::enable_shared_from_this<BlockingTCPTransport>
|
||||
{
|
||||
protected:
|
||||
BlockingTCPTransport(Context::shared_pointer& context, SOCKET channel,
|
||||
std::auto_ptr<ResponseHandler>& responseHandler, int receiveBufferSize,
|
||||
int16 priority);
|
||||
|
||||
public:
|
||||
virtual bool isClosed() {
|
||||
Lock guard(_mutex);
|
||||
return _closed;
|
||||
@@ -63,16 +67,12 @@ namespace epics {
|
||||
_remoteTransportRevision = minorRevision;
|
||||
}
|
||||
|
||||
virtual void setRemoteTransportReceiveBufferSize(
|
||||
int remoteTransportReceiveBufferSize) {
|
||||
_remoteTransportReceiveBufferSize
|
||||
= remoteTransportReceiveBufferSize;
|
||||
virtual void setRemoteTransportReceiveBufferSize(int remoteTransportReceiveBufferSize) {
|
||||
_remoteTransportReceiveBufferSize = remoteTransportReceiveBufferSize;
|
||||
}
|
||||
|
||||
virtual void setRemoteTransportSocketReceiveBufferSize(
|
||||
int socketReceiveBufferSize) {
|
||||
_remoteTransportSocketReceiveBufferSize
|
||||
= socketReceiveBufferSize;
|
||||
virtual void setRemoteTransportSocketReceiveBufferSize(int socketReceiveBufferSize) {
|
||||
_remoteTransportSocketReceiveBufferSize = socketReceiveBufferSize;
|
||||
}
|
||||
|
||||
virtual const String getType() const {
|
||||
@@ -117,6 +117,7 @@ namespace epics {
|
||||
virtual void verified() {
|
||||
Lock lock(_verifiedMutex);
|
||||
_verified = true;
|
||||
_verifiedEvent.signal();
|
||||
}
|
||||
|
||||
virtual void setRecipient(const osiSockAddr& sendTo) {
|
||||
@@ -162,9 +163,9 @@ namespace epics {
|
||||
*/
|
||||
void start();
|
||||
|
||||
virtual void enqueueSendRequest(TransportSender* sender);
|
||||
virtual void enqueueSendRequest(TransportSender::shared_pointer& sender);
|
||||
|
||||
void enqueueMonitorSendRequest(TransportSender* sender);
|
||||
//void enqueueMonitorSendRequest(TransportSender::shared_pointer& sender);
|
||||
|
||||
protected:
|
||||
|
||||
@@ -222,7 +223,7 @@ namespace epics {
|
||||
/**
|
||||
* CAS response handler.
|
||||
*/
|
||||
ResponseHandler* _responseHandler;
|
||||
std::auto_ptr<ResponseHandler> _responseHandler;
|
||||
|
||||
/**
|
||||
* Send buffer size.
|
||||
@@ -247,9 +248,10 @@ namespace epics {
|
||||
|
||||
epicsThreadId _sendThreadId;
|
||||
|
||||
MonitorSender* _monitorSender;
|
||||
// TODO
|
||||
//MonitorSender* _monitorSender;
|
||||
|
||||
Context* _context;
|
||||
Context::shared_pointer _context;
|
||||
|
||||
bool _autoDelete;
|
||||
|
||||
@@ -279,11 +281,11 @@ namespace epics {
|
||||
// and its reference is only valid when called from send thread
|
||||
|
||||
// initialized at construction time
|
||||
GrowingCircularBuffer<TransportSender*>* _sendQueue;
|
||||
std::deque<TransportSender::shared_pointer> _sendQueue;
|
||||
epics::pvData::Mutex _sendQueueMutex;
|
||||
|
||||
// initialized at construction time
|
||||
GrowingCircularBuffer<TransportSender*>* _monitorSendQueue;
|
||||
std::deque<TransportSender::shared_pointer> _monitorSendQueue;
|
||||
epics::pvData::Mutex _monitorMutex;
|
||||
|
||||
/**
|
||||
@@ -371,6 +373,8 @@ namespace epics {
|
||||
|
||||
Event _sendQueueEvent;
|
||||
|
||||
Event _verifiedEvent;
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -419,43 +423,63 @@ namespace epics {
|
||||
* Free all send buffers (return them to the cached buffer allocator).
|
||||
*/
|
||||
void freeSendBuffers();
|
||||
|
||||
TransportSender* extractFromSendQueue();
|
||||
};
|
||||
|
||||
|
||||
class BlockingClientTCPTransport : public BlockingTCPTransport,
|
||||
public TransportSender,
|
||||
public epics::pvData::TimerCallback,
|
||||
public ReferenceCountingTransport {
|
||||
|
||||
public:
|
||||
BlockingClientTCPTransport(Context* context, SOCKET channel,
|
||||
ResponseHandler* responseHandler, int receiveBufferSize,
|
||||
TransportClient* client, short remoteTransportRevision,
|
||||
typedef std::tr1::shared_ptr<BlockingClientTCPTransport> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const BlockingClientTCPTransport> const_shared_pointer;
|
||||
|
||||
private:
|
||||
BlockingClientTCPTransport(Context::shared_pointer& context, SOCKET channel,
|
||||
std::auto_ptr<ResponseHandler>& responseHandler, int receiveBufferSize,
|
||||
TransportClient::shared_pointer client, short remoteTransportRevision,
|
||||
float beaconInterval, int16 priority);
|
||||
|
||||
public:
|
||||
static BlockingClientTCPTransport::shared_pointer create(Context::shared_pointer& context, SOCKET channel,
|
||||
std::auto_ptr<ResponseHandler>& responseHandler, int receiveBufferSize,
|
||||
TransportClient::shared_pointer client, short remoteTransportRevision,
|
||||
float beaconInterval, int16 priority)
|
||||
{
|
||||
BlockingClientTCPTransport::shared_pointer thisPointer(
|
||||
new BlockingClientTCPTransport(context, channel, responseHandler, receiveBufferSize,
|
||||
client, remoteTransportRevision, beaconInterval, priority)
|
||||
);
|
||||
thisPointer->start();
|
||||
return thisPointer;
|
||||
}
|
||||
|
||||
virtual ~BlockingClientTCPTransport();
|
||||
|
||||
virtual void timerStopped() {
|
||||
// noop
|
||||
}
|
||||
|
||||
virtual void callback();
|
||||
|
||||
virtual IntrospectionRegistry* getIntrospectionRegistry() {
|
||||
return &_introspectionRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Acquires transport.
|
||||
* @param client client (channel) acquiring the transport
|
||||
* @return <code>true</code> if transport was granted, <code>false</code> otherwise.
|
||||
*/
|
||||
virtual bool acquire(TransportClient* client);
|
||||
|
||||
virtual IntrospectionRegistry* getIntrospectionRegistry() {
|
||||
return _introspectionRegistry;
|
||||
}
|
||||
virtual bool acquire(TransportClient::shared_pointer& client);
|
||||
|
||||
/**
|
||||
* Releases transport.
|
||||
* @param client client (channel) releasing the transport
|
||||
*/
|
||||
virtual void release(TransportClient* client);
|
||||
virtual void release(pvAccessID clientId);
|
||||
//virtual void release(TransportClient::shared_pointer& client);
|
||||
|
||||
/**
|
||||
* Alive notification.
|
||||
@@ -493,18 +517,18 @@ namespace epics {
|
||||
/**
|
||||
* Introspection registry.
|
||||
*/
|
||||
IntrospectionRegistry* _introspectionRegistry;
|
||||
IntrospectionRegistry _introspectionRegistry;
|
||||
|
||||
virtual void internalClose(bool force);
|
||||
|
||||
virtual ~BlockingClientTCPTransport();
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Owners (users) of the transport.
|
||||
*/
|
||||
std::set<TransportClient*> _owners;
|
||||
// TODO consider using TR1 hash map
|
||||
typedef std::map<pvAccessID, TransportClient::weak_pointer> TransportClientMap_t;
|
||||
TransportClientMap_t _owners;
|
||||
|
||||
/**
|
||||
* Connection timeout (no-traffic) flag.
|
||||
@@ -519,7 +543,7 @@ namespace epics {
|
||||
/**
|
||||
* Timer task node.
|
||||
*/
|
||||
TimerNode* _timerNode;
|
||||
TimerNode _timerNode;
|
||||
|
||||
/**
|
||||
* Timestamp of last "live" event on this transport.
|
||||
@@ -531,6 +555,9 @@ namespace epics {
|
||||
|
||||
bool _verifyOrEcho;
|
||||
|
||||
/**
|
||||
* Unresponsive transport notify.
|
||||
*/
|
||||
void unresponsiveTransport();
|
||||
|
||||
/**
|
||||
@@ -551,13 +578,13 @@ namespace epics {
|
||||
*/
|
||||
class BlockingTCPConnector : public Connector {
|
||||
public:
|
||||
BlockingTCPConnector(Context* context, int receiveBufferSize,
|
||||
BlockingTCPConnector(Context::shared_pointer& context, int receiveBufferSize,
|
||||
float beaconInterval);
|
||||
|
||||
virtual ~BlockingTCPConnector();
|
||||
|
||||
virtual Transport* connect(TransportClient* client,
|
||||
ResponseHandler* responseHandler, osiSockAddr& address,
|
||||
virtual Transport::shared_pointer connect(TransportClient::shared_pointer& client,
|
||||
std::auto_ptr<ResponseHandler>& responseHandler, osiSockAddr& address,
|
||||
short transportRevision, int16 priority);
|
||||
private:
|
||||
/**
|
||||
@@ -568,13 +595,12 @@ namespace epics {
|
||||
/**
|
||||
* Context instance.
|
||||
*/
|
||||
Context* _context;
|
||||
Context::weak_pointer _context;
|
||||
|
||||
/**
|
||||
* named lock
|
||||
*/
|
||||
NamedLockPattern<const osiSockAddr*, comp_osiSockAddrPtr>
|
||||
* _namedLocker;
|
||||
NamedLockPattern<const osiSockAddr*, comp_osiSockAddrPtr> _namedLocker;
|
||||
|
||||
/**
|
||||
* Receive buffer size.
|
||||
@@ -601,11 +627,25 @@ namespace epics {
|
||||
public ChannelHostingTransport,
|
||||
public TransportSender {
|
||||
public:
|
||||
BlockingServerTCPTransport(Context* context, SOCKET channel,
|
||||
ResponseHandler* responseHandler, int receiveBufferSize);
|
||||
typedef std::tr1::shared_ptr<BlockingServerTCPTransport> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const BlockingServerTCPTransport> const_shared_pointer;
|
||||
|
||||
private:
|
||||
BlockingServerTCPTransport(Context::shared_pointer& context, SOCKET channel,
|
||||
std::auto_ptr<ResponseHandler>& responseHandler, int receiveBufferSize);
|
||||
public:
|
||||
static BlockingServerTCPTransport::shared_pointer create(Context::shared_pointer& context, SOCKET channel,
|
||||
std::auto_ptr<ResponseHandler>& responseHandler, int receiveBufferSize)
|
||||
{
|
||||
BlockingServerTCPTransport::shared_pointer thisPointer(
|
||||
new BlockingServerTCPTransport(context, channel, responseHandler, receiveBufferSize)
|
||||
);
|
||||
thisPointer->start();
|
||||
return thisPointer;
|
||||
}
|
||||
|
||||
virtual IntrospectionRegistry* getIntrospectionRegistry() {
|
||||
return _introspectionRegistry;
|
||||
return &_introspectionRegistry;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -627,7 +667,7 @@ namespace epics {
|
||||
* @param sid preallocated channel SID.
|
||||
* @param channel channel to register.
|
||||
*/
|
||||
virtual void registerChannel(pvAccessID sid, ServerChannel* channel);
|
||||
virtual void registerChannel(pvAccessID sid, ServerChannel::shared_pointer& channel);
|
||||
|
||||
/**
|
||||
* Unregister a new channel (and deallocates its handle).
|
||||
@@ -640,7 +680,7 @@ namespace epics {
|
||||
* @param sid channel SID
|
||||
* @return channel with given SID, <code>NULL</code> otherwise
|
||||
*/
|
||||
virtual ServerChannel* getChannel(pvAccessID sid);
|
||||
virtual ServerChannel::shared_pointer getChannel(pvAccessID sid);
|
||||
|
||||
/**
|
||||
* Get channel count.
|
||||
@@ -648,8 +688,8 @@ namespace epics {
|
||||
*/
|
||||
virtual int getChannelCount();
|
||||
|
||||
virtual epics::pvData::PVField* getSecurityToken() {
|
||||
return NULL;
|
||||
virtual epics::pvData::PVField::shared_pointer getSecurityToken() {
|
||||
return epics::pvData::PVField::shared_pointer();
|
||||
}
|
||||
|
||||
virtual void lock() {
|
||||
@@ -672,7 +712,8 @@ namespace epics {
|
||||
* Verify transport. Server side is self-verified.
|
||||
*/
|
||||
void verify() {
|
||||
enqueueSendRequest(this);
|
||||
TransportSender::shared_pointer transportSender = std::tr1::dynamic_pointer_cast<TransportSender>(shared_from_this());
|
||||
enqueueSendRequest(transportSender);
|
||||
verified();
|
||||
}
|
||||
|
||||
@@ -699,16 +740,16 @@ namespace epics {
|
||||
virtual void send(epics::pvData::ByteBuffer* buffer,
|
||||
TransportSendControl* control);
|
||||
|
||||
virtual ~BlockingServerTCPTransport();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Introspection registry.
|
||||
*/
|
||||
IntrospectionRegistry* _introspectionRegistry;
|
||||
IntrospectionRegistry _introspectionRegistry;
|
||||
|
||||
virtual void internalClose(bool force);
|
||||
|
||||
virtual ~BlockingServerTCPTransport();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Last SID cache.
|
||||
@@ -718,7 +759,7 @@ namespace epics {
|
||||
/**
|
||||
* Channel table (SID -> channel mapping).
|
||||
*/
|
||||
std::map<pvAccessID, ServerChannel*> _channels;
|
||||
std::map<pvAccessID, ServerChannel::shared_pointer> _channels;
|
||||
|
||||
Mutex _channelsMutex;
|
||||
|
||||
@@ -727,7 +768,18 @@ namespace epics {
|
||||
*/
|
||||
void destroyAllChannels();
|
||||
};
|
||||
|
||||
class ResponseHandlerFactory
|
||||
{
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<ResponseHandlerFactory> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ResponseHandlerFactory> const_shared_pointer;
|
||||
|
||||
virtual ~ResponseHandlerFactory() {};
|
||||
|
||||
virtual std::auto_ptr<ResponseHandler> createResponseHandler() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Channel Access Server TCP acceptor.
|
||||
* @author <a href="mailto:matej.sekoranjaATcosylab.com">Matej Sekoranja</a>
|
||||
@@ -735,6 +787,8 @@ namespace epics {
|
||||
*/
|
||||
class BlockingTCPAcceptor {
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<BlockingTCPAcceptor> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const BlockingTCPAcceptor> const_shared_pointer;
|
||||
|
||||
/**
|
||||
* @param context
|
||||
@@ -742,8 +796,9 @@ namespace epics {
|
||||
* @param receiveBufferSize
|
||||
* @throws CAException
|
||||
*/
|
||||
BlockingTCPAcceptor(Context* context, int port,
|
||||
int receiveBufferSize);
|
||||
BlockingTCPAcceptor(Context::shared_pointer& context,
|
||||
ResponseHandlerFactory::shared_pointer& responseHandlerFactory,
|
||||
int port, int receiveBufferSize);
|
||||
|
||||
virtual ~BlockingTCPAcceptor();
|
||||
|
||||
@@ -753,7 +808,7 @@ namespace epics {
|
||||
* Bind socket address.
|
||||
* @return bind socket address, <code>null</code> if not binded.
|
||||
*/
|
||||
osiSockAddr* getBindAddress() {
|
||||
const osiSockAddr* getBindAddress() {
|
||||
return &_bindAddress;
|
||||
}
|
||||
|
||||
@@ -766,7 +821,12 @@ namespace epics {
|
||||
/**
|
||||
* Context instance.
|
||||
*/
|
||||
Context* _context;
|
||||
Context::shared_pointer _context;
|
||||
|
||||
/**
|
||||
* ResponseHandler factory.
|
||||
*/
|
||||
ResponseHandlerFactory::shared_pointer _responseHandlerFactory;
|
||||
|
||||
/**
|
||||
* Bind server socket address.
|
||||
@@ -802,8 +862,7 @@ namespace epics {
|
||||
* Validate connection by sending a validation message request.
|
||||
* @return <code>true</code> on success.
|
||||
*/
|
||||
bool validateConnection(BlockingServerTCPTransport* transport,
|
||||
const char* address);
|
||||
bool validateConnection(BlockingServerTCPTransport::shared_pointer& transport, const char* address);
|
||||
|
||||
static void handleEventsRunner(void* param);
|
||||
};
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
/*
|
||||
* blockingTCPAcceptor.cpp
|
||||
*
|
||||
* Created on: Jan 4, 2011
|
||||
* Author: Miha Vitorovic
|
||||
*/
|
||||
|
||||
/* pvAccess */
|
||||
#include "blockingTCP.h"
|
||||
#include "remote.h"
|
||||
#include "serverContext.h"
|
||||
#include "responseHandlers.h"
|
||||
#include <blockingTCP.h>
|
||||
#include <remote.h>
|
||||
|
||||
/* pvData */
|
||||
#include <epicsException.h>
|
||||
@@ -27,11 +22,19 @@ using std::ostringstream;
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
BlockingTCPAcceptor::BlockingTCPAcceptor(Context* context, int port,
|
||||
BlockingTCPAcceptor::BlockingTCPAcceptor(
|
||||
Context::shared_pointer& context,
|
||||
ResponseHandlerFactory::shared_pointer& responseHandlerFactory,
|
||||
int port,
|
||||
int receiveBufferSize) :
|
||||
_context(context), _bindAddress(), _serverSocketChannel(
|
||||
INVALID_SOCKET), _receiveBufferSize(receiveBufferSize),
|
||||
_destroyed(false), _threadId(NULL) {
|
||||
_context(context),
|
||||
_responseHandlerFactory(responseHandlerFactory),
|
||||
_bindAddress(),
|
||||
_serverSocketChannel(INVALID_SOCKET),
|
||||
_receiveBufferSize(receiveBufferSize),
|
||||
_destroyed(false),
|
||||
_threadId(0)
|
||||
{
|
||||
initialize(port);
|
||||
}
|
||||
|
||||
@@ -52,14 +55,11 @@ namespace epics {
|
||||
int tryCount = 0;
|
||||
while(tryCount<2) {
|
||||
|
||||
errlogSevPrintf(errlogInfo, "Creating acceptor to %s.",
|
||||
ipAddrStr);
|
||||
errlogSevPrintf(errlogInfo, "Creating acceptor to %s.", ipAddrStr);
|
||||
|
||||
_serverSocketChannel = epicsSocketCreate(AF_INET, SOCK_STREAM,
|
||||
IPPROTO_TCP);
|
||||
_serverSocketChannel = epicsSocketCreate(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if(_serverSocketChannel==INVALID_SOCKET) {
|
||||
epicsSocketConvertErrnoToString(strBuffer,
|
||||
sizeof(strBuffer));
|
||||
epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
|
||||
ostringstream temp;
|
||||
temp<<"Socket create error: "<<strBuffer;
|
||||
errlogSevPrintf(errlogMajor, "%s", temp.str().c_str());
|
||||
@@ -67,16 +67,13 @@ namespace epics {
|
||||
}
|
||||
else {
|
||||
|
||||
epicsSocketEnableAddressReuseDuringTimeWaitState(_serverSocketChannel);
|
||||
//epicsSocketEnableAddressReuseDuringTimeWaitState(_serverSocketChannel);
|
||||
|
||||
// try to bind
|
||||
int retval = ::bind(_serverSocketChannel,
|
||||
&_bindAddress.sa, sizeof(sockaddr));
|
||||
int retval = ::bind(_serverSocketChannel, &_bindAddress.sa, sizeof(sockaddr));
|
||||
if(retval<0) {
|
||||
epicsSocketConvertErrnoToString(strBuffer,
|
||||
sizeof(strBuffer));
|
||||
errlogSevPrintf(errlogMinor, "Socket bind error: %s",
|
||||
strBuffer);
|
||||
epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
|
||||
errlogSevPrintf(errlogMinor, "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
|
||||
@@ -98,14 +95,11 @@ namespace epics {
|
||||
if(ntohs(_bindAddress.ia.sin_port)==0) {
|
||||
socklen_t sockLen = sizeof(sockaddr);
|
||||
// read the actual socket info
|
||||
retval = ::getsockname(_serverSocketChannel,
|
||||
&_bindAddress.sa, &sockLen);
|
||||
retval = ::getsockname(_serverSocketChannel, &_bindAddress.sa, &sockLen);
|
||||
if(retval<0) {
|
||||
// error obtaining port number
|
||||
epicsSocketConvertErrnoToString(strBuffer,
|
||||
sizeof(strBuffer));
|
||||
errlogSevPrintf(errlogMinor,
|
||||
"getsockname error: %s", strBuffer);
|
||||
epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
|
||||
errlogSevPrintf(errlogMinor, "getsockname error: %s", strBuffer);
|
||||
}
|
||||
else {
|
||||
errlogSevPrintf(
|
||||
@@ -117,8 +111,7 @@ namespace epics {
|
||||
|
||||
retval = ::listen(_serverSocketChannel, 1024);
|
||||
if(retval<0) {
|
||||
epicsSocketConvertErrnoToString(strBuffer,
|
||||
sizeof(strBuffer));
|
||||
epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
|
||||
ostringstream temp;
|
||||
temp<<"Socket listen error: "<<strBuffer;
|
||||
errlogSevPrintf(errlogMajor, "%s", temp.str().c_str());
|
||||
@@ -150,8 +143,7 @@ namespace epics {
|
||||
// rise level if port is assigned dynamically
|
||||
char ipAddrStr[48];
|
||||
ipAddrToDottedIP(&_bindAddress.ia, ipAddrStr, sizeof(ipAddrStr));
|
||||
errlogSevPrintf(errlogInfo, "Accepting connections at %s.",
|
||||
ipAddrStr);
|
||||
errlogSevPrintf(errlogInfo, "Accepting connections at %s.", ipAddrStr);
|
||||
|
||||
bool socketOpen = true;
|
||||
char strBuffer[64];
|
||||
@@ -167,50 +159,39 @@ namespace epics {
|
||||
osiSockAddr address;
|
||||
osiSocklen_t len = sizeof(sockaddr);
|
||||
|
||||
SOCKET newClient = epicsSocketAccept(_serverSocketChannel,
|
||||
&address.sa, &len);
|
||||
SOCKET newClient = epicsSocketAccept(_serverSocketChannel, &address.sa, &len);
|
||||
if(newClient!=INVALID_SOCKET) {
|
||||
// accept succeeded
|
||||
ipAddrToDottedIP(&address.ia, ipAddrStr, sizeof(ipAddrStr));
|
||||
errlogSevPrintf(errlogInfo,
|
||||
"Accepted connection from CA client: %s", ipAddrStr);
|
||||
errlogSevPrintf(errlogInfo, "Accepted connection from CA client: %s", ipAddrStr);
|
||||
|
||||
// enable TCP_NODELAY (disable Nagle's algorithm)
|
||||
int optval = 1; // true
|
||||
int retval = ::setsockopt(newClient, IPPROTO_TCP,
|
||||
TCP_NODELAY, &optval, sizeof(int));
|
||||
int retval = ::setsockopt(newClient, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(int));
|
||||
if(retval<0) {
|
||||
epicsSocketConvertErrnoToString(strBuffer,
|
||||
sizeof(strBuffer));
|
||||
errlogSevPrintf(errlogMinor,
|
||||
"Error setting TCP_NODELAY: %s", strBuffer);
|
||||
epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
|
||||
errlogSevPrintf(errlogMinor, "Error setting TCP_NODELAY: %s", strBuffer);
|
||||
}
|
||||
|
||||
// enable TCP_KEEPALIVE
|
||||
retval = ::setsockopt(newClient, SOL_SOCKET, SO_KEEPALIVE,
|
||||
&optval, sizeof(int));
|
||||
retval = ::setsockopt(newClient, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(int));
|
||||
if(retval<0) {
|
||||
epicsSocketConvertErrnoToString(strBuffer,
|
||||
sizeof(strBuffer));
|
||||
errlogSevPrintf(errlogMinor,
|
||||
"Error setting SO_KEEPALIVE: %s", strBuffer);
|
||||
epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
|
||||
errlogSevPrintf(errlogMinor, "Error setting SO_KEEPALIVE: %s", strBuffer);
|
||||
}
|
||||
|
||||
// TODO tune buffer sizes?!
|
||||
//socket.socket().setReceiveBufferSize();
|
||||
//socket.socket().setSendBufferSize();
|
||||
|
||||
/* create transport
|
||||
* each transport should have its own response
|
||||
* handler since it is not "shareable"
|
||||
/**
|
||||
* Create transport, it registers itself to the registry.
|
||||
* Each transport should have its own response handler since it is not "shareable"
|
||||
*/
|
||||
BlockingServerTCPTransport
|
||||
* transport =
|
||||
new BlockingServerTCPTransport(
|
||||
auto_ptr<ResponseHandler> responseHandler = _responseHandlerFactory->createResponseHandler();
|
||||
BlockingServerTCPTransport::shared_pointer transport =
|
||||
BlockingServerTCPTransport::create(
|
||||
_context,
|
||||
newClient,
|
||||
new ServerResponseHandler(
|
||||
dynamic_cast<ServerContextImpl*> (_context)),
|
||||
responseHandler,
|
||||
_receiveBufferSize);
|
||||
|
||||
// validate connection
|
||||
@@ -223,8 +204,7 @@ namespace epics {
|
||||
return;
|
||||
}
|
||||
|
||||
errlogSevPrintf(errlogInfo, "Serving to CA client: %s",
|
||||
ipAddrStr);
|
||||
errlogSevPrintf(errlogInfo, "Serving to CA client: %s", ipAddrStr);
|
||||
|
||||
}// accept succeeded
|
||||
else
|
||||
@@ -232,8 +212,7 @@ namespace epics {
|
||||
} // while
|
||||
}
|
||||
|
||||
bool BlockingTCPAcceptor::validateConnection(
|
||||
BlockingServerTCPTransport* transport, const char* address) {
|
||||
bool BlockingTCPAcceptor::validateConnection(BlockingServerTCPTransport::shared_pointer& transport, const char* address) {
|
||||
try {
|
||||
transport->verify();
|
||||
return true;
|
||||
@@ -254,10 +233,8 @@ namespace epics {
|
||||
|
||||
if(_serverSocketChannel!=INVALID_SOCKET) {
|
||||
char ipAddrStr[48];
|
||||
ipAddrToDottedIP(&_bindAddress.ia, ipAddrStr,
|
||||
sizeof(ipAddrStr));
|
||||
errlogSevPrintf(errlogInfo,
|
||||
"Stopped accepting connections at %s.", ipAddrStr);
|
||||
ipAddrToDottedIP(&_bindAddress.ia, ipAddrStr, sizeof(ipAddrStr));
|
||||
errlogSevPrintf(errlogInfo, "Stopped accepting connections at %s.", ipAddrStr);
|
||||
|
||||
epicsSocketDestroy(_serverSocketChannel);
|
||||
}
|
||||
|
||||
@@ -20,105 +20,102 @@
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
BlockingTCPConnector::BlockingTCPConnector(Context* context,
|
||||
int receiveBufferSize, float beaconInterval) :
|
||||
_context(context), _namedLocker(new NamedLockPattern<
|
||||
const osiSockAddr*, comp_osiSockAddrPtr> ()),
|
||||
_receiveBufferSize(receiveBufferSize), _beaconInterval(
|
||||
beaconInterval) {
|
||||
BlockingTCPConnector::BlockingTCPConnector(
|
||||
Context::shared_pointer& context,
|
||||
int receiveBufferSize,
|
||||
float beaconInterval) :
|
||||
_context(context),
|
||||
_namedLocker(),
|
||||
_receiveBufferSize(receiveBufferSize),
|
||||
_beaconInterval(beaconInterval)
|
||||
{
|
||||
}
|
||||
|
||||
BlockingTCPConnector::~BlockingTCPConnector() {
|
||||
delete _namedLocker;
|
||||
}
|
||||
|
||||
SOCKET BlockingTCPConnector::tryConnect(osiSockAddr& address, int tries) {
|
||||
for(int tryCount = 0; tryCount<tries; tryCount++) {
|
||||
// sleep for a while
|
||||
if(tryCount>0) epicsThreadSleep(0.1);
|
||||
|
||||
char strBuffer[64];
|
||||
ipAddrToDottedIP(&address.ia, strBuffer, sizeof(strBuffer));
|
||||
|
||||
char strBuffer[64];
|
||||
ipAddrToDottedIP(&address.ia, strBuffer, sizeof(strBuffer));
|
||||
for(int tryCount = 0; tryCount<tries; tryCount++) {
|
||||
|
||||
errlogSevPrintf(errlogInfo,
|
||||
"Opening socket to CA server %s, attempt %d.",
|
||||
strBuffer, tryCount+1);
|
||||
|
||||
SOCKET socket = epicsSocketCreate(AF_INET, SOCK_STREAM,
|
||||
IPPROTO_TCP);
|
||||
if(socket==INVALID_SOCKET) {
|
||||
epicsSocketConvertErrnoToString(strBuffer,
|
||||
sizeof(strBuffer));
|
||||
errlogSevPrintf(errlogMinor, "Socket create error: %s",
|
||||
strBuffer);
|
||||
SOCKET socket = epicsSocketCreate(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (socket == INVALID_SOCKET)
|
||||
{
|
||||
epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
|
||||
errlogSevPrintf(errlogMinor, "Socket create error: %s", strBuffer);
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
else {
|
||||
if(::connect(socket, &address.sa, sizeof(sockaddr))==0)
|
||||
if(::connect(socket, &address.sa, sizeof(sockaddr))==0) {
|
||||
return socket;
|
||||
}
|
||||
else {
|
||||
epicsSocketConvertErrnoToString(strBuffer,
|
||||
sizeof(strBuffer));
|
||||
errlogSevPrintf(errlogMinor,
|
||||
"Socket connect error: %s", strBuffer);
|
||||
epicsSocketDestroy (socket);
|
||||
epicsSocketConvertErrnoToString(strBuffer, sizeof(strBuffer));
|
||||
errlogSevPrintf(errlogMinor, "Socket connect error: %s", strBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
return INVALID_SOCKET;
|
||||
}
|
||||
|
||||
Transport* BlockingTCPConnector::connect(TransportClient* client,
|
||||
ResponseHandler* responseHandler, osiSockAddr& address,
|
||||
Transport::shared_pointer BlockingTCPConnector::connect(TransportClient::shared_pointer& client,
|
||||
auto_ptr<ResponseHandler>& responseHandler, osiSockAddr& address,
|
||||
short transportRevision, int16 priority) {
|
||||
|
||||
SOCKET socket = INVALID_SOCKET;
|
||||
|
||||
char ipAddrStr[64];
|
||||
ipAddrToDottedIP(&address.ia, ipAddrStr, sizeof(ipAddrStr));
|
||||
|
||||
Context::shared_pointer context = _context.lock();
|
||||
|
||||
// first try to check cache w/o named lock...
|
||||
BlockingClientTCPTransport
|
||||
* transport =
|
||||
(BlockingClientTCPTransport*)(_context->getTransportRegistry()->get(
|
||||
"TCP", &address, priority));
|
||||
if(transport!=NULL) {
|
||||
Transport::shared_pointer tt = context->getTransportRegistry()->get("TCP", &address, priority);
|
||||
BlockingClientTCPTransport::shared_pointer transport = std::tr1::static_pointer_cast<BlockingClientTCPTransport>(tt);
|
||||
if(transport.get()) {
|
||||
errlogSevPrintf(errlogInfo,
|
||||
"Reusing existing connection to CA server: %s",
|
||||
ipAddrStr);
|
||||
if(transport->acquire(client)) return transport;
|
||||
if (transport->acquire(client))
|
||||
return transport;
|
||||
}
|
||||
|
||||
bool lockAcquired = _namedLocker->acquireSynchronizationObject(
|
||||
&address, LOCK_TIMEOUT);
|
||||
bool lockAcquired = _namedLocker.acquireSynchronizationObject(&address, LOCK_TIMEOUT);
|
||||
if(lockAcquired) {
|
||||
try {
|
||||
// ... transport created during waiting in lock
|
||||
transport
|
||||
= (BlockingClientTCPTransport*)(_context->getTransportRegistry()->get(
|
||||
"TCP", &address, priority));
|
||||
if(transport!=NULL) {
|
||||
tt = context->getTransportRegistry()->get("TCP", &address, priority);
|
||||
transport = std::tr1::static_pointer_cast<BlockingClientTCPTransport>(tt);
|
||||
if(transport.get()) {
|
||||
errlogSevPrintf(errlogInfo,
|
||||
"Reusing existing connection to CA server: %s",
|
||||
ipAddrStr);
|
||||
if(transport->acquire(client)) return transport;
|
||||
"Reusing existing connection to CA server: %s",
|
||||
ipAddrStr);
|
||||
if (transport->acquire(client))
|
||||
return transport;
|
||||
}
|
||||
|
||||
errlogSevPrintf(errlogInfo, "Connecting to CA server: %s",
|
||||
ipAddrStr);
|
||||
|
||||
errlogSevPrintf(errlogInfo, "Connecting to CA server: %s", ipAddrStr);
|
||||
|
||||
socket = tryConnect(address, 3);
|
||||
|
||||
// verify
|
||||
if(socket==INVALID_SOCKET) {
|
||||
errlogSevPrintf(errlogMajor,
|
||||
"Connection to CA server %s failed.", ipAddrStr);
|
||||
ostringstream temp;
|
||||
temp<<"Failed to verify TCP connection to '"<<ipAddrStr
|
||||
<<"'.";
|
||||
temp<<"Failed to verify TCP connection to '"<<ipAddrStr<<"'.";
|
||||
THROW_BASE_EXCEPTION(temp.str().c_str());
|
||||
}
|
||||
|
||||
// use blocking channel
|
||||
// socket is blocking bya default
|
||||
//socket.configureBlocking(true);
|
||||
errlogSevPrintf(errlogInfo, "Socket connected to CA server: %s.", ipAddrStr);
|
||||
|
||||
// enable TCP_NODELAY (disable Nagle's algorithm)
|
||||
int optval = 1; // true
|
||||
@@ -134,14 +131,11 @@ namespace epics {
|
||||
"Error setting SO_KEEPALIVE: %s", strerror(errno));
|
||||
|
||||
// TODO tune buffer sizes?! Win32 defaults are 8k, which is OK
|
||||
//socket.socket().setReceiveBufferSize();
|
||||
//socket.socket().setSendBufferSize();
|
||||
|
||||
// create transport
|
||||
transport = new BlockingClientTCPTransport(_context,
|
||||
socket, responseHandler, _receiveBufferSize,
|
||||
client, transportRevision, _beaconInterval,
|
||||
priority);
|
||||
transport = BlockingClientTCPTransport::create(
|
||||
context, socket, responseHandler, _receiveBufferSize,
|
||||
client, transportRevision, _beaconInterval, priority);
|
||||
|
||||
// verify
|
||||
if(!transport->waitUntilVerified(3.0)) {
|
||||
@@ -150,25 +144,31 @@ namespace epics {
|
||||
"Connection to CA server %s failed to be validated, closing it.",
|
||||
ipAddrStr);
|
||||
ostringstream temp;
|
||||
temp<<"Failed to verify TCP connection to '"<<ipAddrStr
|
||||
<<"'.";
|
||||
temp<<"Failed to verify TCP connection to '"<<ipAddrStr<<"'.";
|
||||
THROW_BASE_EXCEPTION(temp.str().c_str());
|
||||
}
|
||||
|
||||
// TODO send security token
|
||||
|
||||
errlogSevPrintf(errlogInfo, "Connected to CA server: %s",
|
||||
ipAddrStr);
|
||||
errlogSevPrintf(errlogInfo, "Connected to CA server: %s", ipAddrStr);
|
||||
|
||||
_namedLocker.releaseSynchronizationObject(&address);
|
||||
return transport;
|
||||
} catch(...) {
|
||||
if(transport!=NULL)
|
||||
} catch(std::exception& ex) {
|
||||
// TODO
|
||||
printf("ex %s\n", ex.what());
|
||||
if(transport.get())
|
||||
transport->close(true);
|
||||
else if(socket!=INVALID_SOCKET) epicsSocketDestroy(socket);
|
||||
_namedLocker->releaseSynchronizationObject(&address);
|
||||
_namedLocker.releaseSynchronizationObject(&address);
|
||||
throw;
|
||||
} catch(...) {
|
||||
if(transport.get())
|
||||
transport->close(true);
|
||||
else if(socket!=INVALID_SOCKET) epicsSocketDestroy(socket);
|
||||
_namedLocker.releaseSynchronizationObject(&address);
|
||||
throw;
|
||||
}
|
||||
_namedLocker->releaseSynchronizationObject(&address);
|
||||
}
|
||||
else {
|
||||
ostringstream temp;
|
||||
|
||||
@@ -6,9 +6,9 @@
|
||||
*/
|
||||
|
||||
#include "blockingTCP.h"
|
||||
#include "inetAddressUtil.h"
|
||||
#include "growingCircularBuffer.h"
|
||||
#include "caConstants.h"
|
||||
#include <inetAddressUtil.h>
|
||||
#include <caConstants.h>
|
||||
#include <CDRMonitor.h>
|
||||
|
||||
/* pvData */
|
||||
#include <lock.h>
|
||||
@@ -37,6 +37,7 @@ using std::ostringstream;
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
/*
|
||||
class MonitorSender : public TransportSender, public NoDefaultMethods {
|
||||
public:
|
||||
MonitorSender(Mutex* monitorMutex, GrowingCircularBuffer<
|
||||
@@ -67,49 +68,67 @@ namespace epics {
|
||||
Mutex* _monitorMutex;
|
||||
GrowingCircularBuffer<TransportSender*>* _monitorSendQueue;
|
||||
};
|
||||
*/
|
||||
|
||||
BlockingTCPTransport::BlockingTCPTransport(Context* context,
|
||||
SOCKET channel, ResponseHandler* responseHandler,
|
||||
PVDATA_REFCOUNT_MONITOR_DEFINE(blockingTCPTransport);
|
||||
|
||||
BlockingTCPTransport::BlockingTCPTransport(Context::shared_pointer& context,
|
||||
SOCKET channel, auto_ptr<ResponseHandler>& responseHandler,
|
||||
int receiveBufferSize, int16 priority) :
|
||||
_closed(false), _channel(channel),
|
||||
_channel(channel),
|
||||
_priority(priority),
|
||||
_responseHandler(responseHandler),
|
||||
_markerPeriodBytes(MARKER_PERIOD),
|
||||
_flushStrategy(DELAYED),
|
||||
_rcvThreadId(0),
|
||||
_sendThreadId(0),
|
||||
//_monitorSender(new MonitorSender(&_monitorMutex,_monitorSendQueue)),
|
||||
_context(context),
|
||||
_autoDelete(true),
|
||||
_remoteTransportRevision(0),
|
||||
_remoteTransportReceiveBufferSize(MAX_TCP_RECV),
|
||||
_remoteTransportSocketReceiveBufferSize(MAX_TCP_RECV),
|
||||
_priority(priority), _responseHandler(responseHandler),
|
||||
_totalBytesReceived(0), _totalBytesSent(0),
|
||||
_markerToSend(0), _verified(false), _remoteBufferFreeSpace(
|
||||
LONG_LONG_MAX), _autoDelete(true),
|
||||
_markerPeriodBytes(MARKER_PERIOD), _nextMarkerPosition(
|
||||
_markerPeriodBytes), _sendPending(false),
|
||||
_lastMessageStartPosition(0), _stage(READ_FROM_SOCKET),
|
||||
_lastSegmentedMessageType(0), _lastSegmentedMessageCommand(
|
||||
0), _storedPayloadSize(0), _storedPosition(0),
|
||||
_storedLimit(0), _magicAndVersion(0), _packetType(0),
|
||||
_command(0), _payloadSize(0), _flushRequested(false),
|
||||
_sendBufferSentPosition(0), _flushStrategy(DELAYED),
|
||||
_sendQueue(
|
||||
new GrowingCircularBuffer<TransportSender*> (100)),
|
||||
_rcvThreadId(NULL), _sendThreadId(NULL), _monitorSendQueue(
|
||||
new GrowingCircularBuffer<TransportSender*> (100)),
|
||||
_monitorSender(new MonitorSender(&_monitorMutex,
|
||||
_monitorSendQueue)), _context(context),
|
||||
_sendThreadExited(false) {
|
||||
_sendQueue(),
|
||||
//_monitorSendQueue(),
|
||||
_nextMarkerPosition(_markerPeriodBytes),
|
||||
_sendPending(false),
|
||||
_lastMessageStartPosition(0),
|
||||
_lastSegmentedMessageType(0),
|
||||
_lastSegmentedMessageCommand(0),
|
||||
_flushRequested(false),
|
||||
_sendBufferSentPosition(0),
|
||||
_storedPayloadSize(0),
|
||||
_storedPosition(0),
|
||||
_storedLimit(0),
|
||||
_magicAndVersion(0),
|
||||
_packetType(0),
|
||||
_command(0),
|
||||
_payloadSize(0),
|
||||
_stage(READ_FROM_SOCKET),
|
||||
_totalBytesReceived(0),
|
||||
_closed(false),
|
||||
_sendThreadExited(false),
|
||||
_verified(false),
|
||||
_markerToSend(0),
|
||||
_totalBytesSent(0),
|
||||
_remoteBufferFreeSpace(LONG_LONG_MAX)
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(blockingTCPTransport);
|
||||
|
||||
_socketBuffer = new ByteBuffer(max(MAX_TCP_RECV
|
||||
+MAX_ENSURE_DATA_BUFFER_SIZE, receiveBufferSize), EPICS_ENDIAN_BIG);
|
||||
// TODO minor tweak: deque size is not preallocated...
|
||||
|
||||
_socketBuffer = new ByteBuffer(max(MAX_TCP_RECV+MAX_ENSURE_DATA_BUFFER_SIZE, receiveBufferSize), EPICS_ENDIAN_BIG);
|
||||
_socketBuffer->setPosition(_socketBuffer->getLimit());
|
||||
_startPosition = _socketBuffer->getPosition();
|
||||
|
||||
// allocate buffer
|
||||
_sendBuffer = new ByteBuffer(_socketBuffer->getSize(), EPICS_ENDIAN_BIG);
|
||||
_maxPayloadSize = _sendBuffer->getSize()-2*CA_MESSAGE_HEADER_SIZE; // one for header, one for flow control
|
||||
_maxPayloadSize = _sendBuffer->getSize() - 2*CA_MESSAGE_HEADER_SIZE; // one for header, one for flow control
|
||||
|
||||
// get send buffer size
|
||||
|
||||
socklen_t intLen = sizeof(int);
|
||||
|
||||
int retval = getsockopt(_channel, SOL_SOCKET, SO_SNDBUF,
|
||||
&_socketSendBufferSize, &intLen);
|
||||
int retval = getsockopt(_channel, SOL_SOCKET, SO_SNDBUF, &_socketSendBufferSize, &intLen);
|
||||
if(retval<0) {
|
||||
_socketSendBufferSize = MAX_TCP_RECV;
|
||||
errlogSevPrintf(errlogMinor,
|
||||
@@ -121,74 +140,64 @@ namespace epics {
|
||||
retval = getpeername(_channel, &(_socketAddress.sa), &saSize);
|
||||
if(retval<0) {
|
||||
errlogSevPrintf(errlogMajor,
|
||||
"Error fetching socket remote address: %s", strerror(
|
||||
errno));
|
||||
"Error fetching socket remote address: %s",
|
||||
strerror(errno));
|
||||
}
|
||||
|
||||
// prepare buffer
|
||||
clearAndReleaseBuffer();
|
||||
|
||||
// add to registry
|
||||
_context->acquire();
|
||||
_context->getTransportRegistry()->put(this);
|
||||
}
|
||||
|
||||
BlockingTCPTransport::~BlockingTCPTransport() {
|
||||
PVDATA_REFCOUNT_MONITOR_DESTRUCT(blockingTCPTransport);
|
||||
|
||||
close(true);
|
||||
|
||||
TransportSender* sender;
|
||||
while ((sender = _monitorSendQueue->extract()))
|
||||
sender->release();
|
||||
delete _monitorSendQueue;
|
||||
|
||||
while ((sender = _sendQueue->extract()))
|
||||
sender->release();
|
||||
delete _sendQueue;
|
||||
|
||||
delete _monitorSender;
|
||||
|
||||
|
||||
delete _socketBuffer;
|
||||
delete _sendBuffer;
|
||||
|
||||
delete _responseHandler;
|
||||
|
||||
_context->release();
|
||||
}
|
||||
|
||||
// TODO consider epics::pvData::Thread
|
||||
void BlockingTCPTransport::start() {
|
||||
|
||||
// TODO consuder epics::pvData::Thread
|
||||
|
||||
String threadName = "TCP-receive "+inetAddressToString(
|
||||
_socketAddress);
|
||||
// TODO this was in constructor
|
||||
// add to registry
|
||||
Transport::shared_pointer thisSharedPtr = shared_from_this();
|
||||
_context->getTransportRegistry()->put(thisSharedPtr);
|
||||
|
||||
errlogSevPrintf(errlogInfo, "Starting thread: %s",
|
||||
threadName.c_str());
|
||||
|
||||
String socketAddressString = inetAddressToString(_socketAddress);
|
||||
|
||||
//
|
||||
// start receive thread
|
||||
//
|
||||
|
||||
String threadName = "TCP-receive " + socketAddressString;
|
||||
errlogSevPrintf(errlogInfo, "Starting thread: %s", threadName.c_str());
|
||||
|
||||
_rcvThreadId = epicsThreadCreate(threadName.c_str(),
|
||||
epicsThreadPriorityMedium, epicsThreadGetStackSize(
|
||||
epicsThreadStackMedium),
|
||||
epicsThreadPriorityMedium,
|
||||
epicsThreadGetStackSize(epicsThreadStackMedium),
|
||||
BlockingTCPTransport::rcvThreadRunner, this);
|
||||
|
||||
threadName = "TCP-send "+inetAddressToString(_socketAddress);
|
||||
//
|
||||
// start send thread
|
||||
//
|
||||
|
||||
errlogSevPrintf(errlogInfo, "Starting thread: %s",
|
||||
threadName.c_str());
|
||||
threadName = "TCP-send " + socketAddressString;
|
||||
errlogSevPrintf(errlogInfo, "Starting thread: %s",threadName.c_str());
|
||||
|
||||
_sendThreadId = epicsThreadCreate(threadName.c_str(),
|
||||
epicsThreadPriorityMedium, epicsThreadGetStackSize(
|
||||
epicsThreadStackMedium),
|
||||
epicsThreadPriorityMedium,
|
||||
epicsThreadGetStackSize(epicsThreadStackMedium),
|
||||
BlockingTCPTransport::sendThreadRunner, this);
|
||||
|
||||
}
|
||||
|
||||
void BlockingTCPTransport::clearAndReleaseBuffer() {
|
||||
// NOTE: take care that nextMarkerPosition is set right
|
||||
// fix position to be correct when buffer is cleared
|
||||
// do not include pre-buffered flow control message; not 100% correct, but OK
|
||||
_nextMarkerPosition -= _sendBuffer->getPosition()
|
||||
-CA_MESSAGE_HEADER_SIZE;
|
||||
_nextMarkerPosition -= _sendBuffer->getPosition() - CA_MESSAGE_HEADER_SIZE;
|
||||
|
||||
_sendQueueMutex.lock();
|
||||
_flushRequested = false;
|
||||
@@ -214,7 +223,8 @@ namespace epics {
|
||||
_closed = true;
|
||||
|
||||
// remove from registry
|
||||
_context->getTransportRegistry()->remove(this);
|
||||
Transport::shared_pointer thisSharedPtr = shared_from_this();
|
||||
_context->getTransportRegistry()->remove(thisSharedPtr);
|
||||
|
||||
// clean resources
|
||||
internalClose(force);
|
||||
@@ -239,33 +249,17 @@ namespace epics {
|
||||
int sockBufSize;
|
||||
socklen_t intLen = sizeof(int);
|
||||
|
||||
int retval = getsockopt(_channel, SOL_SOCKET, SO_RCVBUF,
|
||||
&sockBufSize, &intLen);
|
||||
if(retval<0) errlogSevPrintf(errlogMajor,
|
||||
"Socket getsockopt SO_RCVBUF error: %s", strerror(errno));
|
||||
int retval = getsockopt(_channel, SOL_SOCKET, SO_RCVBUF,&sockBufSize, &intLen);
|
||||
if(retval<0)
|
||||
errlogSevPrintf(errlogMajor,
|
||||
"Socket getsockopt SO_RCVBUF error: %s",
|
||||
strerror(errno));
|
||||
|
||||
return sockBufSize;
|
||||
}
|
||||
|
||||
// TODO reimplement using Event
|
||||
bool BlockingTCPTransport::waitUntilVerified(double timeout) {
|
||||
double internalTimeout = timeout;
|
||||
bool internalVerified = false;
|
||||
|
||||
_verifiedMutex.lock();
|
||||
internalVerified = _verified;
|
||||
_verifiedMutex.unlock();
|
||||
|
||||
while(!internalVerified&&internalTimeout>0) {
|
||||
epicsThreadSleep(min(0.1, internalTimeout));
|
||||
internalTimeout -= 0.1;
|
||||
|
||||
_verifiedMutex.lock();
|
||||
internalVerified = _verified;
|
||||
_verifiedMutex.unlock();
|
||||
}
|
||||
|
||||
return internalVerified;
|
||||
return _verifiedEvent.wait(timeout);
|
||||
}
|
||||
|
||||
void BlockingTCPTransport::flush(bool lastMessageCompleted) {
|
||||
@@ -291,15 +285,14 @@ namespace epics {
|
||||
_lastSegmentedMessageCommand, 0);
|
||||
}
|
||||
|
||||
void BlockingTCPTransport::startMessage(int8 command,
|
||||
int ensureCapacity) {
|
||||
void BlockingTCPTransport::startMessage(int8 command, int ensureCapacity) {
|
||||
_lastMessageStartPosition = -1;
|
||||
ensureBuffer(CA_MESSAGE_HEADER_SIZE+ensureCapacity);
|
||||
_lastMessageStartPosition = _sendBuffer->getPosition();
|
||||
_sendBuffer->putShort(CA_MAGIC_AND_VERSION);
|
||||
_sendBuffer->putByte(_lastSegmentedMessageType); // data
|
||||
_sendBuffer->putByte(command); // command
|
||||
_sendBuffer->putInt(0); // temporary zero payload
|
||||
_sendBuffer->putByte(command); // command
|
||||
_sendBuffer->putInt(0); // temporary zero payload
|
||||
|
||||
}
|
||||
|
||||
@@ -586,16 +579,14 @@ namespace epics {
|
||||
_socketBuffer->setLimit(min(_storedPosition+_storedPayloadSize, _storedLimit));
|
||||
try {
|
||||
// handle response
|
||||
Transport::shared_pointer thisPointer = shared_from_this();
|
||||
_responseHandler->handleResponse(&_socketAddress,
|
||||
this, version, _command, _payloadSize,
|
||||
thisPointer, version, _command, _payloadSize,
|
||||
_socketBuffer);
|
||||
} catch(...) {
|
||||
//noop // TODO print?
|
||||
}
|
||||
|
||||
/*
|
||||
* Java finally start
|
||||
*/
|
||||
_socketBuffer->setLimit(_storedLimit);
|
||||
int newPosition = _storedPosition+_storedPayloadSize;
|
||||
if(newPosition>_storedLimit) {
|
||||
@@ -606,9 +597,6 @@ namespace epics {
|
||||
}
|
||||
_socketBuffer->setPosition(newPosition);
|
||||
// TODO discard all possible segments?!!!
|
||||
/*
|
||||
* Java finally end
|
||||
*/
|
||||
|
||||
_stage = PROCESS_HEADER;
|
||||
|
||||
@@ -757,27 +745,25 @@ namespace epics {
|
||||
return true;
|
||||
}
|
||||
|
||||
TransportSender* BlockingTCPTransport::extractFromSendQueue() {
|
||||
TransportSender* retval;
|
||||
|
||||
_sendQueueMutex.lock();
|
||||
retval = _sendQueue->extract();
|
||||
_sendQueueMutex.unlock();
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void BlockingTCPTransport::processSendQueue() {
|
||||
// TODO sync _closed
|
||||
while(!_closed) {
|
||||
TransportSender* sender;
|
||||
|
||||
sender = extractFromSendQueue();
|
||||
_sendQueueMutex.lock();
|
||||
// TODO optimize
|
||||
TransportSender::shared_pointer sender;
|
||||
if (!_sendQueue.empty())
|
||||
{
|
||||
sender = _sendQueue.front();
|
||||
_sendQueue.pop_front();
|
||||
}
|
||||
_sendQueueMutex.unlock();
|
||||
|
||||
// wait for new message
|
||||
while(sender==NULL&&!_flushRequested&&!_closed) {
|
||||
while(sender.get()==0&&!_flushRequested&&!_closed) {
|
||||
if(_flushStrategy==DELAYED) {
|
||||
if(_delay>0) epicsThreadSleep(_delay);
|
||||
if(_sendQueue->size()==0) {
|
||||
if(_sendQueue.empty()) {
|
||||
// if (hasMonitors || sendBuffer.position() > CAConstants.CA_MESSAGE_HEADER_SIZE)
|
||||
if(_sendBuffer->getPosition()>CA_MESSAGE_HEADER_SIZE)
|
||||
_flushRequested = true;
|
||||
@@ -787,7 +773,16 @@ namespace epics {
|
||||
}
|
||||
else
|
||||
_sendQueueEvent.wait();
|
||||
sender = extractFromSendQueue();
|
||||
|
||||
_sendQueueMutex.lock();
|
||||
if (!_sendQueue.empty())
|
||||
{
|
||||
sender = _sendQueue.front();
|
||||
_sendQueue.pop_front();
|
||||
}
|
||||
else
|
||||
sender.reset();
|
||||
_sendQueueMutex.unlock();
|
||||
}
|
||||
|
||||
// always do flush from this thread
|
||||
@@ -802,7 +797,7 @@ namespace epics {
|
||||
flush();
|
||||
}
|
||||
|
||||
if(sender!=NULL) {
|
||||
if(sender.get()) {
|
||||
sender->lock();
|
||||
try {
|
||||
_lastMessageStartPosition = _sendBuffer->getPosition();
|
||||
@@ -820,7 +815,6 @@ namespace epics {
|
||||
_sendBuffer->setPosition(_lastMessageStartPosition);
|
||||
}
|
||||
sender->unlock();
|
||||
sender->release();
|
||||
} // if(sender!=NULL)
|
||||
} // while(!_closed)
|
||||
}
|
||||
@@ -843,6 +837,7 @@ namespace epics {
|
||||
|
||||
void BlockingTCPTransport::rcvThreadRunner(void* param) {
|
||||
BlockingTCPTransport* obj = (BlockingTCPTransport*)param;
|
||||
Transport::shared_pointer ptr = obj->shared_from_this(); // hold reference
|
||||
|
||||
try{
|
||||
obj->processReadCached(false, NONE, CA_MESSAGE_HEADER_SIZE, false);
|
||||
@@ -850,6 +845,7 @@ try{
|
||||
printf("rcvThreadRunnner exception\n");
|
||||
}
|
||||
|
||||
/*
|
||||
if(obj->_autoDelete) {
|
||||
while(true)
|
||||
{
|
||||
@@ -863,12 +859,16 @@ printf("rcvThreadRunnner exception\n");
|
||||
}
|
||||
delete obj;
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void BlockingTCPTransport::sendThreadRunner(void* param) {
|
||||
BlockingTCPTransport* obj = (BlockingTCPTransport*)param;
|
||||
Transport::shared_pointer ptr = obj->shared_from_this(); // hold reference
|
||||
try {
|
||||
obj->processSendQueue();
|
||||
} catch (std::exception& ex) {
|
||||
printf("sendThreadRunnner exception %s\n", ex.what());
|
||||
} catch (...) {
|
||||
printf("sendThreadRunnner exception\n");
|
||||
}
|
||||
@@ -881,21 +881,21 @@ printf("sendThreadRunnner exception\n");
|
||||
obj->_mutex.unlock();
|
||||
}
|
||||
|
||||
void BlockingTCPTransport::enqueueSendRequest(TransportSender* sender) {
|
||||
void BlockingTCPTransport::enqueueSendRequest(TransportSender::shared_pointer& sender) {
|
||||
Lock lock(_sendQueueMutex);
|
||||
if(_closed) return;
|
||||
sender->acquire();
|
||||
_sendQueue->insert(sender);
|
||||
_sendQueue.push_back(sender);
|
||||
_sendQueueEvent.signal();
|
||||
}
|
||||
|
||||
void BlockingTCPTransport::enqueueMonitorSendRequest(TransportSender* sender) {
|
||||
/*
|
||||
void BlockingTCPTransport::enqueueMonitorSendRequest(TransportSender::shared_pointer sender) {
|
||||
Lock lock(_monitorMutex);
|
||||
if(_closed) return;
|
||||
sender->acquire();
|
||||
_monitorSendQueue->insert(sender);
|
||||
if(_monitorSendQueue->size()==1) enqueueSendRequest(_monitorSender);
|
||||
_monitorSendQueue.insert(sender);
|
||||
if(_monitorSendQueue.size()==1) enqueueSendRequest(_monitorSender);
|
||||
}
|
||||
|
||||
|
||||
void MonitorSender::send(ByteBuffer* buffer, TransportSendControl* control) {
|
||||
control->startMessage(19, 0);
|
||||
@@ -911,13 +911,13 @@ printf("sendThreadRunnner exception\n");
|
||||
|
||||
if(sender==NULL) {
|
||||
control->ensureBuffer(sizeof(int32));
|
||||
buffer->putInt(CAJ_INVALID_IOID);
|
||||
buffer->putInt(INVALID_IOID);
|
||||
break;
|
||||
}
|
||||
sender->send(buffer, control);
|
||||
sender->release();
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,11 +29,27 @@ namespace epics {
|
||||
|
||||
class BlockingUDPTransport : public epics::pvData::NoDefaultMethods,
|
||||
public Transport,
|
||||
public TransportSendControl {
|
||||
public TransportSendControl,
|
||||
public std::tr1::enable_shared_from_this<BlockingUDPTransport>
|
||||
{
|
||||
public:
|
||||
BlockingUDPTransport(ResponseHandler* responseHandler,
|
||||
typedef std::tr1::shared_ptr<BlockingUDPTransport> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const BlockingUDPTransport> const_shared_pointer;
|
||||
|
||||
private:
|
||||
BlockingUDPTransport(std::auto_ptr<ResponseHandler>& responseHandler,
|
||||
SOCKET channel, osiSockAddr& bindAddress,
|
||||
short remoteTransportRevision);
|
||||
public:
|
||||
static BlockingUDPTransport::shared_pointer create(std::auto_ptr<ResponseHandler>& responseHandler,
|
||||
SOCKET channel, osiSockAddr& bindAddress,
|
||||
short remoteTransportRevision);
|
||||
short remoteTransportRevision)
|
||||
{
|
||||
BlockingUDPTransport::shared_pointer thisPointer(
|
||||
new BlockingUDPTransport(responseHandler, channel, bindAddress, remoteTransportRevision)
|
||||
);
|
||||
return thisPointer;
|
||||
}
|
||||
|
||||
virtual ~BlockingUDPTransport();
|
||||
|
||||
@@ -43,6 +59,7 @@ namespace epics {
|
||||
}
|
||||
|
||||
virtual const osiSockAddr* getRemoteAddress() const {
|
||||
// always connected
|
||||
return &_bindAddress;
|
||||
}
|
||||
|
||||
@@ -90,7 +107,7 @@ namespace epics {
|
||||
// noop
|
||||
}
|
||||
|
||||
virtual void enqueueSendRequest(TransportSender* sender);
|
||||
virtual void enqueueSendRequest(TransportSender::shared_pointer& sender);
|
||||
|
||||
void start();
|
||||
|
||||
@@ -190,14 +207,14 @@ namespace epics {
|
||||
/**
|
||||
* Response handler.
|
||||
*/
|
||||
ResponseHandler* _responseHandler;
|
||||
std::auto_ptr<ResponseHandler> _responseHandler;
|
||||
|
||||
virtual void processRead();
|
||||
|
||||
private:
|
||||
static void threadRunner(void* param);
|
||||
|
||||
bool processBuffer(osiSockAddr& fromAddress,
|
||||
epics::pvData::ByteBuffer* receiveBuffer);
|
||||
bool processBuffer(Transport::shared_pointer& transport, osiSockAddr& fromAddress, epics::pvData::ByteBuffer* receiveBuffer);
|
||||
|
||||
void close(bool forced, bool waitForThreadToComplete);
|
||||
|
||||
@@ -276,8 +293,8 @@ namespace epics {
|
||||
/**
|
||||
* NOTE: transport client is ignored for broadcast (UDP).
|
||||
*/
|
||||
virtual Transport* connect(TransportClient* client,
|
||||
ResponseHandler* responseHandler, osiSockAddr& bindAddress,
|
||||
virtual Transport::shared_pointer connect(TransportClient::shared_pointer& client,
|
||||
std::auto_ptr<ResponseHandler>& responseHandler, osiSockAddr& bindAddress,
|
||||
short transportRevision, int16 priority);
|
||||
|
||||
private:
|
||||
|
||||
@@ -17,11 +17,13 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
Transport* BlockingUDPConnector::connect(TransportClient* client,
|
||||
ResponseHandler* responseHandler, osiSockAddr& bindAddress,
|
||||
Transport::shared_pointer BlockingUDPConnector::connect(TransportClient::shared_pointer& client,
|
||||
auto_ptr<ResponseHandler>& responseHandler, osiSockAddr& bindAddress,
|
||||
short transportRevision, int16 priority) {
|
||||
|
||||
errlogSevPrintf(errlogInfo, "Creating datagram socket to: %s",
|
||||
@@ -32,7 +34,7 @@ namespace epics {
|
||||
char errStr[64];
|
||||
epicsSocketConvertErrnoToString(errStr, sizeof(errStr));
|
||||
errlogSevPrintf(errlogMajor, "Error creating socket: %s", errStr);
|
||||
return 0;
|
||||
return Transport::shared_pointer();
|
||||
}
|
||||
|
||||
int optval = _broadcast ? 1 : 0;
|
||||
@@ -41,7 +43,7 @@ namespace epics {
|
||||
{
|
||||
errlogSevPrintf(errlogMajor, "Error setting SO_BROADCAST: %s", strerror(errno));
|
||||
epicsSocketDestroy (socket);
|
||||
return 0;
|
||||
return Transport::shared_pointer();
|
||||
}
|
||||
|
||||
// set SO_REUSEADDR or SO_REUSEPORT, OS dependant
|
||||
@@ -52,11 +54,12 @@ namespace epics {
|
||||
if(retval<0) {
|
||||
errlogSevPrintf(errlogMajor, "Error binding socket: %s", strerror(errno));
|
||||
epicsSocketDestroy (socket);
|
||||
return 0;
|
||||
return Transport::shared_pointer();
|
||||
}
|
||||
|
||||
// sockets are blocking by default
|
||||
return new BlockingUDPTransport(responseHandler, socket, bindAddress, transportRevision);
|
||||
Transport::shared_pointer transport = BlockingUDPTransport::create(responseHandler, socket, bindAddress, transportRevision);
|
||||
return transport;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,12 +7,13 @@
|
||||
/* pvAccess */
|
||||
#include "blockingUDP.h"
|
||||
|
||||
#include "caConstants.h"
|
||||
#include "inetAddressUtil.h"
|
||||
#include <caConstants.h>
|
||||
#include <inetAddressUtil.h>
|
||||
|
||||
/* pvData */
|
||||
#include <byteBuffer.h>
|
||||
#include <lock.h>
|
||||
#include <CDRMonitor.h>
|
||||
|
||||
/* EPICSv3 */
|
||||
#include <osdSock.h>
|
||||
@@ -26,13 +27,16 @@
|
||||
#include <sys/socket.h>
|
||||
#include <errno.h>
|
||||
|
||||
using namespace epics::pvData;
|
||||
using namespace std;
|
||||
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
using namespace epics::pvData;
|
||||
PVDATA_REFCOUNT_MONITOR_DEFINE(blockingUDPTransport);
|
||||
|
||||
BlockingUDPTransport::BlockingUDPTransport(
|
||||
ResponseHandler* responseHandler, SOCKET channel,
|
||||
auto_ptr<ResponseHandler>& responseHandler, SOCKET channel,
|
||||
osiSockAddr& bindAddress,
|
||||
short remoteTransportRevision) :
|
||||
_closed(false),
|
||||
@@ -47,9 +51,12 @@ namespace epics {
|
||||
_lastMessageStartPosition(0),
|
||||
_threadId(0)
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(blockingUDPTransport);
|
||||
}
|
||||
|
||||
BlockingUDPTransport::~BlockingUDPTransport() {
|
||||
PVDATA_REFCOUNT_MONITOR_DESTRUCT(blockingUDPTransport);
|
||||
|
||||
close(true); // close the socket and stop the thread.
|
||||
|
||||
if (_sendAddresses) delete _sendAddresses;
|
||||
@@ -57,12 +64,11 @@ namespace epics {
|
||||
|
||||
delete _receiveBuffer;
|
||||
delete _sendBuffer;
|
||||
delete _responseHandler;
|
||||
}
|
||||
|
||||
void BlockingUDPTransport::start() {
|
||||
String threadName = "UDP-receive "+inetAddressToString(_bindAddress);
|
||||
|
||||
String threadName = "UDP-receive "+inetAddressToString(_bindAddress);
|
||||
errlogSevPrintf(errlogInfo, "Starting thread: %s",threadName.c_str());
|
||||
|
||||
_threadId = epicsThreadCreate(threadName.c_str(),
|
||||
@@ -93,7 +99,7 @@ namespace epics {
|
||||
_shutdownEvent.wait();
|
||||
}
|
||||
|
||||
void BlockingUDPTransport::enqueueSendRequest(TransportSender* sender) {
|
||||
void BlockingUDPTransport::enqueueSendRequest(TransportSender::shared_pointer& sender) {
|
||||
Lock lock(_sendMutex);
|
||||
|
||||
_sendToEnabled = false;
|
||||
@@ -132,11 +138,13 @@ namespace epics {
|
||||
|
||||
char _readBuffer[MAX_UDP_RECV];
|
||||
osiSockAddr fromAddress;
|
||||
Transport::shared_pointer thisTransport = shared_from_this();
|
||||
|
||||
try {
|
||||
|
||||
bool closed;
|
||||
while(!_closed) {
|
||||
while(!_closed)
|
||||
{
|
||||
|
||||
_mutex.lock();
|
||||
closed = _closed;
|
||||
@@ -161,10 +169,12 @@ namespace epics {
|
||||
if(_ignoredAddresses!=0)
|
||||
{
|
||||
for(size_t i = 0; i <_ignoredAddresses->size(); i++)
|
||||
if(_ignoredAddresses->at(i).ia.sin_addr.s_addr
|
||||
==fromAddress.ia.sin_addr.s_addr) {
|
||||
ignore = true;
|
||||
break;
|
||||
{
|
||||
if(_ignoredAddresses->at(i).ia.sin_addr.s_addr==fromAddress.ia.sin_addr.s_addr)
|
||||
{
|
||||
ignore = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,20 +182,19 @@ namespace epics {
|
||||
// TODO do not copy.... wrap the buffer!!!
|
||||
_receiveBuffer->put(_readBuffer, 0,
|
||||
bytesRead <_receiveBuffer->getRemaining() ?
|
||||
bytesRead :
|
||||
_receiveBuffer->getRemaining()
|
||||
bytesRead : _receiveBuffer->getRemaining()
|
||||
);
|
||||
|
||||
_receiveBuffer->flip();
|
||||
|
||||
processBuffer(fromAddress, _receiveBuffer);
|
||||
processBuffer(thisTransport, fromAddress, _receiveBuffer);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// 0 == socket remotely closed
|
||||
// log a 'recvfrom' error
|
||||
if(!_closed && bytesRead==-1) errlogSevPrintf(errlogMajor,
|
||||
"Socket recv error: %s", strerror(errno));
|
||||
if(!_closed && bytesRead==-1)
|
||||
errlogSevPrintf(errlogMajor, "Socket recv error: %s", strerror(errno));
|
||||
|
||||
close(true, false);
|
||||
break;
|
||||
@@ -204,8 +213,7 @@ namespace epics {
|
||||
_shutdownEvent.signal();
|
||||
}
|
||||
|
||||
bool BlockingUDPTransport::processBuffer(osiSockAddr& fromAddress,
|
||||
ByteBuffer* receiveBuffer) {
|
||||
bool BlockingUDPTransport::processBuffer(Transport::shared_pointer& thisTransport, osiSockAddr& fromAddress, ByteBuffer* receiveBuffer) {
|
||||
|
||||
// handle response(s)
|
||||
while(receiveBuffer->getRemaining()>=CA_MESSAGE_HEADER_SIZE) {
|
||||
@@ -225,14 +233,13 @@ namespace epics {
|
||||
// command ID and paylaod
|
||||
int8 command = receiveBuffer->getByte();
|
||||
int payloadSize = receiveBuffer->getInt();
|
||||
int nextRequestPosition = receiveBuffer->getPosition()
|
||||
+payloadSize;
|
||||
int nextRequestPosition = receiveBuffer->getPosition() + payloadSize;
|
||||
|
||||
// payload size check
|
||||
if(nextRequestPosition>receiveBuffer->getLimit()) return false;
|
||||
|
||||
// handle
|
||||
_responseHandler->handleResponse(&fromAddress, this,
|
||||
_responseHandler->handleResponse(&fromAddress, thisTransport,
|
||||
(int8)(magicAndVersion&0xFF), command, payloadSize,
|
||||
_receiveBuffer);
|
||||
|
||||
@@ -244,8 +251,7 @@ namespace epics {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool BlockingUDPTransport::send(ByteBuffer* buffer,
|
||||
const osiSockAddr& address) {
|
||||
bool BlockingUDPTransport::send(ByteBuffer* buffer, const osiSockAddr& address) {
|
||||
|
||||
buffer->flip();
|
||||
int retval = sendto(_channel, buffer->getArray(),
|
||||
@@ -268,8 +274,7 @@ namespace epics {
|
||||
buffer->getLimit(), 0, &(_sendAddresses->at(i).sa),
|
||||
sizeof(sockaddr));
|
||||
{
|
||||
if(retval<0) errlogSevPrintf(errlogMajor,
|
||||
"Socket sendto error: %s", strerror(errno));
|
||||
if(retval<0) errlogSevPrintf(errlogMajor, "Socket sendto error: %s", strerror(errno));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,19 +21,19 @@ void BaseSearchInstance::initializeSearchInstance()
|
||||
void BaseSearchInstance::unsetListOwnership()
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
if (_owner != NULL) this->release();
|
||||
//if (_owner != NULL) this->release();
|
||||
_owner = NULL;
|
||||
}
|
||||
|
||||
void BaseSearchInstance::addAndSetListOwnership(ArrayFIFO<SearchInstance*>* newOwner, Mutex* ownerMutex, int32 index)
|
||||
void BaseSearchInstance::addAndSetListOwnership(SearchInstance::List* newOwner, Mutex* ownerMutex, int32 index)
|
||||
{
|
||||
if(ownerMutex == NULL) THROW_BASE_EXCEPTION("Null owner mutex");
|
||||
|
||||
_ownerMutex = ownerMutex;
|
||||
Lock ownerGuard(*_ownerMutex);
|
||||
Lock guard(_mutex);
|
||||
newOwner->push(this);
|
||||
if (_owner == NULL) this->acquire(); // new owner
|
||||
newOwner->push_back(this);
|
||||
//if (_owner == NULL) this->acquire(); // new owner
|
||||
_owner = newOwner;
|
||||
_ownerIndex = index;
|
||||
}
|
||||
@@ -47,8 +47,14 @@ void BaseSearchInstance::removeAndUnsetListOwnership()
|
||||
Lock guard(_mutex);
|
||||
if(_owner != NULL)
|
||||
{
|
||||
this->release();
|
||||
_owner->remove(this);
|
||||
//this->release();
|
||||
// TODO !!!
|
||||
for (SearchInstance::List::iterator iter = _owner->begin(); iter != _owner->end(); iter++)
|
||||
if (*iter == this)
|
||||
{
|
||||
_owner->erase(iter);
|
||||
break;
|
||||
}
|
||||
_owner = NULL;
|
||||
}
|
||||
}
|
||||
@@ -65,10 +71,12 @@ bool BaseSearchInstance::generateSearchRequestMessage(ByteBuffer* requestMessage
|
||||
int16 dataCount = requestMessage->getShort(DATA_COUNT_POSITION);
|
||||
|
||||
dataCount++;
|
||||
/*
|
||||
if(dataCount >= MAX_SEARCH_BATCH_COUNT)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
|
||||
const String name = getSearchInstanceName();
|
||||
// not nice...
|
||||
@@ -100,8 +108,8 @@ SearchTimer::SearchTimer(ChannelSearchManager* _chanSearchManager, int32 timerIn
|
||||
_timerIndex(timerIndex),
|
||||
_allowBoost(allowBoost),
|
||||
_allowSlowdown(allowSlowdown),
|
||||
_requestPendingChannels(new ArrayFIFO<SearchInstance*>),
|
||||
_responsePendingChannels(new ArrayFIFO<SearchInstance*>),
|
||||
_requestPendingChannels(new SearchInstance::List()),
|
||||
_responsePendingChannels(new SearchInstance::List()),
|
||||
_timerNode(new TimerNode(*this)),
|
||||
_canceled(false),
|
||||
_timeAtResponseCheck(0)
|
||||
@@ -141,7 +149,7 @@ void SearchTimer::installChannel(SearchInstance* channel)
|
||||
if(_canceled) return;
|
||||
|
||||
Lock pendingChannelGuard(_requestPendingChannelsMutex);
|
||||
bool startImmediately = _requestPendingChannels->isEmpty();
|
||||
bool startImmediately = _requestPendingChannels->empty();
|
||||
channel->addAndSetListOwnership(_requestPendingChannels, &_requestPendingChannelsMutex, _timerIndex);
|
||||
|
||||
// start searching
|
||||
@@ -163,9 +171,11 @@ void SearchTimer::installChannel(SearchInstance* channel)
|
||||
void SearchTimer::moveChannels(SearchTimer* destination)
|
||||
{
|
||||
// do not sync this, not necessary and might cause deadlock
|
||||
SearchInstance* channel;
|
||||
while((channel = _responsePendingChannels->pop()) != NULL)
|
||||
while(!_responsePendingChannels->empty())
|
||||
{
|
||||
SearchInstance* channel = _responsePendingChannels->front();
|
||||
_responsePendingChannels->pop_front();
|
||||
|
||||
{
|
||||
Lock guard(_volMutex);
|
||||
if(_searchAttempts > 0)
|
||||
@@ -178,9 +188,12 @@ void SearchTimer::moveChannels(SearchTimer* destination)
|
||||
|
||||
// bulk move
|
||||
Lock guard(_requestPendingChannelsMutex);
|
||||
while (!_requestPendingChannels->isEmpty())
|
||||
while (!_requestPendingChannels->empty())
|
||||
{
|
||||
destination->installChannel(_requestPendingChannels->pop());
|
||||
SearchInstance* channel = _requestPendingChannels->front();
|
||||
_requestPendingChannels->pop_front();
|
||||
|
||||
destination->installChannel(channel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,19 +219,19 @@ void SearchTimer::callback()
|
||||
if(_allowBoost && searchRespones > 0)
|
||||
{
|
||||
Lock guard(_requestPendingChannelsMutex);
|
||||
while(!_requestPendingChannels->isEmpty())
|
||||
while(!_requestPendingChannels->empty())
|
||||
{
|
||||
SearchInstance* channel = _requestPendingChannels->peek();
|
||||
SearchInstance* channel = _requestPendingChannels->front();
|
||||
// boost needed check
|
||||
//final int boostIndex = searchRespones >= searchAttempts * SUCCESS_RATE ? Math.min(Math.max(0, timerIndex - 1), beaconAnomalyTimerIndex) : beaconAnomalyTimerIndex;
|
||||
const int boostIndex = _chanSearchManager->_beaconAnomalyTimerIndex;
|
||||
if(channel->getOwnerIndex() > boostIndex)
|
||||
{
|
||||
_requestPendingChannels->pop();
|
||||
channel->acquire();
|
||||
_requestPendingChannels->pop_front();
|
||||
//channel->acquire();
|
||||
channel->unsetListOwnership();
|
||||
_chanSearchManager->boostSearching(channel, boostIndex);
|
||||
channel->release();
|
||||
//channel->release();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -234,14 +247,17 @@ void SearchTimer::callback()
|
||||
_timeAtResponseCheck = now;
|
||||
|
||||
// notify about timeout (move it to other timer)
|
||||
while((channel = _responsePendingChannels->pop()) != NULL)
|
||||
while(!_responsePendingChannels->empty())
|
||||
{
|
||||
channel = _responsePendingChannels->front();
|
||||
_responsePendingChannels->pop_front();
|
||||
|
||||
if(_allowSlowdown)
|
||||
{
|
||||
channel->acquire();
|
||||
//channel->acquire();
|
||||
channel->unsetListOwnership();
|
||||
_chanSearchManager->searchResponseTimeout(channel, _timerIndex);
|
||||
channel->release();
|
||||
//channel->release();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -306,11 +322,17 @@ void SearchTimer::callback()
|
||||
|
||||
{
|
||||
Lock guard(_requestPendingChannelsMutex);
|
||||
channel = _requestPendingChannels->pop();
|
||||
if (_requestPendingChannels->empty())
|
||||
channel = 0;
|
||||
else {
|
||||
channel = _requestPendingChannels->front();
|
||||
_requestPendingChannels->pop_front();
|
||||
}
|
||||
|
||||
}
|
||||
while (!canceled && channel != NULL)
|
||||
{
|
||||
channel->acquire();
|
||||
//channel->acquire();
|
||||
channel->unsetListOwnership();
|
||||
|
||||
bool requestSent = true;
|
||||
@@ -345,7 +367,7 @@ void SearchTimer::callback()
|
||||
}
|
||||
}
|
||||
|
||||
channel->release();
|
||||
//channel->release();
|
||||
|
||||
// limit
|
||||
if(triesInFrame == 0 && !allowNewFrame) break;
|
||||
@@ -357,7 +379,12 @@ void SearchTimer::callback()
|
||||
|
||||
{
|
||||
Lock guard(_requestPendingChannelsMutex);
|
||||
channel = _requestPendingChannels->pop();
|
||||
if (_requestPendingChannels->empty())
|
||||
channel = 0;
|
||||
else {
|
||||
channel = _requestPendingChannels->front();
|
||||
_requestPendingChannels->pop_front();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -380,7 +407,7 @@ void SearchTimer::callback()
|
||||
Lock guard(_requestPendingChannelsMutex);
|
||||
if(!canceled && !_timerNode->isScheduled())
|
||||
{
|
||||
bool someWorkToDo = (!_requestPendingChannels->isEmpty() || !_responsePendingChannels->isEmpty());
|
||||
bool someWorkToDo = (!_requestPendingChannels->empty() || !_responsePendingChannels->empty());
|
||||
if(someWorkToDo)
|
||||
{
|
||||
_chanSearchManager->_context->getTimer()->scheduleAfterDelay(*_timerNode, period()/1000.0);
|
||||
@@ -546,7 +573,7 @@ void ChannelSearchManager::searchResponse(int32 cid, int32 seqNo, int8 minorRevi
|
||||
{
|
||||
si = _channelsIter->second;
|
||||
_channels.erase(_channelsIter);
|
||||
si->acquire();
|
||||
//si->acquire();
|
||||
si->removeAndUnsetListOwnership();
|
||||
|
||||
// report success
|
||||
@@ -557,17 +584,17 @@ void ChannelSearchManager::searchResponse(int32 cid, int32 seqNo, int8 minorRevi
|
||||
|
||||
// then notify SearchInstance
|
||||
si->searchResponse(minorRevision, serverAddress);
|
||||
si->release();
|
||||
//si->release();
|
||||
}
|
||||
else
|
||||
{
|
||||
// minor hack to enable duplicate reports
|
||||
si = dynamic_cast<SearchInstance*>(_context->getChannel(cid));
|
||||
si = dynamic_cast<SearchInstance*>(_context->getChannel(cid).get()); // TODO
|
||||
if(si != NULL)
|
||||
{
|
||||
si->acquire(); // TODO not thread/destruction safe
|
||||
//si->acquire(); // TODO not thread/destruction safe
|
||||
si->searchResponse(minorRevision, serverAddress);
|
||||
si->release();
|
||||
//si->release();
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -611,7 +638,10 @@ void ChannelSearchManager::flushSendBuffer()
|
||||
TimeStamp now;
|
||||
now.getCurrent();
|
||||
_timeAtLastSend = now.getMilliseconds();
|
||||
((BlockingUDPTransport*)_context->getSearchTransport())->send(_sendBuffer);
|
||||
|
||||
Transport::shared_pointer tt = _context->getSearchTransport();
|
||||
BlockingUDPTransport::shared_pointer ut = std::tr1::static_pointer_cast<BlockingUDPTransport>(tt);
|
||||
ut->send(_sendBuffer); // TODO
|
||||
initializeSendBuffer();
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
|
||||
#include "remote.h"
|
||||
#include "pvAccess.h"
|
||||
#include "arrayFIFO.h"
|
||||
#include "caConstants.h"
|
||||
#include "blockingUDP.h"
|
||||
|
||||
@@ -20,6 +19,8 @@
|
||||
#include <float.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <deque>
|
||||
|
||||
using namespace epics::pvData;
|
||||
|
||||
namespace epics { namespace pvAccess {
|
||||
@@ -29,8 +30,11 @@ namespace epics { namespace pvAccess {
|
||||
/**
|
||||
* SearchInstance.
|
||||
*/
|
||||
class SearchInstance : public ReferenceCountingInstance {
|
||||
class SearchInstance {
|
||||
public:
|
||||
|
||||
typedef std::deque<SearchInstance*> List;
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
@@ -61,7 +65,7 @@ public:
|
||||
*
|
||||
* @throws BaseException if the ownerMutex is NULL.
|
||||
*/
|
||||
virtual void addAndSetListOwnership(ArrayFIFO<SearchInstance*>* newOwner, Mutex* ownerMutex, int32 index) = 0;
|
||||
virtual void addAndSetListOwnership(List* newOwner, Mutex* ownerMutex, int32 index) = 0;
|
||||
/**
|
||||
* Removes this search instance from the owner list and also removes the list as the owner of this
|
||||
* search instance.
|
||||
@@ -97,7 +101,7 @@ public:
|
||||
virtual pvAccessID getSearchInstanceID() = 0;
|
||||
virtual String getSearchInstanceName() = 0;
|
||||
virtual void unsetListOwnership();
|
||||
virtual void addAndSetListOwnership(ArrayFIFO<SearchInstance*>* newOwner, Mutex* ownerMutex, int32 index);
|
||||
virtual void addAndSetListOwnership(List* newOwner, Mutex* ownerMutex, int32 index);
|
||||
virtual void removeAndUnsetListOwnership();
|
||||
virtual int32 getOwnerIndex();
|
||||
/**
|
||||
@@ -107,7 +111,7 @@ public:
|
||||
virtual bool generateSearchRequestMessage(ByteBuffer* requestMessage, TransportSendControl* control);
|
||||
private:
|
||||
Mutex _mutex;
|
||||
ArrayFIFO<SearchInstance*>* _owner;
|
||||
List* _owner;
|
||||
Mutex* _ownerMutex;
|
||||
int32 _ownerIndex;
|
||||
|
||||
@@ -211,11 +215,13 @@ private:
|
||||
/**
|
||||
* Ordered (as inserted) list of channels with search request pending.
|
||||
*/
|
||||
ArrayFIFO<SearchInstance*>* _requestPendingChannels;
|
||||
// TODO replace with stl::deque<SearchInstance::shared_pointer>
|
||||
SearchInstance::List* _requestPendingChannels;
|
||||
/**
|
||||
* Ordered (as inserted) list of channels with search request pending.
|
||||
*/
|
||||
ArrayFIFO<SearchInstance*>* _responsePendingChannels;
|
||||
// TODO replace with stl::deque<SearchInstance::shared_pointer>
|
||||
SearchInstance::List* _responsePendingChannels;
|
||||
/**
|
||||
* Timer node.
|
||||
* (sync on requestPendingChannels)
|
||||
@@ -266,6 +272,9 @@ public:
|
||||
class ChannelSearchManager
|
||||
{
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<ChannelSearchManager> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ChannelSearchManager> const_shared_pointer;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param context
|
||||
|
||||
@@ -8,10 +8,9 @@
|
||||
#ifndef REMOTE_H_
|
||||
#define REMOTE_H_
|
||||
|
||||
#include "caConstants.h"
|
||||
#include "transportRegistry.h"
|
||||
#include <caConstants.h>
|
||||
#include <configuration.h>
|
||||
#include "introspectionRegistry.h"
|
||||
#include "configuration.h"
|
||||
|
||||
#include <serialize.h>
|
||||
#include <pvType.h>
|
||||
@@ -19,6 +18,8 @@
|
||||
#include <timer.h>
|
||||
#include <pvData.h>
|
||||
|
||||
#include <sharedPtr.h>
|
||||
|
||||
#include <osiSock.h>
|
||||
#include <osdSock.h>
|
||||
|
||||
@@ -27,10 +28,6 @@ namespace epics {
|
||||
|
||||
class TransportRegistry;
|
||||
|
||||
enum ProtocolType {
|
||||
TCP, UDP, SSL
|
||||
};
|
||||
|
||||
enum QoS {
|
||||
/**
|
||||
* Default behavior.
|
||||
@@ -72,51 +69,57 @@ namespace epics {
|
||||
|
||||
typedef int32 pvAccessID;
|
||||
|
||||
enum MessageCommands {
|
||||
CMD_BEACON = 0, CMD_CONNECTION_VALIDATION = 1, CMD_ECHO = 2,
|
||||
CMD_SEARCH = 3, CMD_SEARCH_RESPONSE = 4,
|
||||
CMD_INTROSPECTION_SEARCH = 5, CMD_CREATE_CHANNEL = 7,
|
||||
CMD_DESTROY_CHANNEL = 8, CMD_GET = 10, CMD_PUT = 11,
|
||||
CMD_PUT_GET = 12, CMD_MONITOR = 13, CMD_ARRAY = 14,
|
||||
CMD_CANCEL_REQUEST = 15, CMD_PROCESS = 16, CMD_GET_FIELD = 17,
|
||||
CMD_MESSAGE = 18, CMD_MULTIPLE_DATA = 19, CMD_RPC = 20,
|
||||
enum MessageCommands {
|
||||
CMD_BEACON = 0,
|
||||
CMD_CONNECTION_VALIDATION = 1,
|
||||
CMD_ECHO = 2,
|
||||
CMD_SEARCH = 3,
|
||||
CMD_SEARCH_RESPONSE = 4,
|
||||
CMD_INTROSPECTION_SEARCH = 5,
|
||||
CMD_INTROSPECTION_SEARCH_RESPONSE = 6,
|
||||
CMD_CREATE_CHANNEL = 7,
|
||||
CMD_DESTROY_CHANNEL = 8,
|
||||
CMD_RESERVED0 = 9,
|
||||
CMD_GET = 10,
|
||||
CMD_PUT = 11,
|
||||
CMD_PUT_GET = 12,
|
||||
CMD_MONITOR = 13,
|
||||
CMD_ARRAY = 14,
|
||||
CMD_CANCEL_REQUEST = 15,
|
||||
CMD_PROCESS = 16,
|
||||
CMD_GET_FIELD = 17,
|
||||
CMD_MESSAGE = 18,
|
||||
CMD_MULTIPLE_DATA = 19,
|
||||
CMD_RPC = 20
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface defining transport send control.
|
||||
* @author <a href="mailto:matej.sekoranjaATcosylab.com">Matej Sekoranja</a>
|
||||
*/
|
||||
class TransportSendControl : public epics::pvData::SerializableControl {
|
||||
public:
|
||||
virtual ~TransportSendControl() {
|
||||
}
|
||||
typedef std::tr1::shared_ptr<TransportSendControl> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const TransportSendControl> const_shared_pointer;
|
||||
|
||||
virtual ~TransportSendControl() {}
|
||||
|
||||
virtual void startMessage(int8 command, int ensureCapacity) =0;
|
||||
virtual void endMessage() =0;
|
||||
virtual void startMessage(int8 command, int ensureCapacity) = 0;
|
||||
virtual void endMessage() = 0;
|
||||
|
||||
virtual void flush(bool lastMessageCompleted) =0;
|
||||
virtual void flush(bool lastMessageCompleted) = 0;
|
||||
|
||||
virtual void setRecipient(const osiSockAddr& sendTo) =0;
|
||||
virtual void setRecipient(const osiSockAddr& sendTo) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Reference counting instance.
|
||||
*/
|
||||
class ReferenceCountingInstance {
|
||||
public:
|
||||
virtual void acquire() =0;
|
||||
virtual void release() =0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface defining transport sender (instance sending data over transport).
|
||||
* @author <a href="mailto:matej.sekoranjaATcosylab.com">Matej Sekoranja</a>
|
||||
* @version $Id: TransportSender.java,v 1.1 2010/05/03 14:45:39 mrkraimer Exp $
|
||||
*/
|
||||
class TransportSender : virtual public ReferenceCountingInstance {
|
||||
class TransportSender {
|
||||
public:
|
||||
virtual ~TransportSender() {
|
||||
}
|
||||
typedef std::tr1::shared_ptr<TransportSender> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const TransportSender> const_shared_pointer;
|
||||
|
||||
virtual ~TransportSender() {}
|
||||
|
||||
/**
|
||||
* Called by transport.
|
||||
@@ -126,40 +129,33 @@ namespace epics {
|
||||
* of this method.
|
||||
* NOTE: these limitations allows efficient implementation.
|
||||
*/
|
||||
virtual void send(epics::pvData::ByteBuffer* buffer,
|
||||
TransportSendControl* control) =0;
|
||||
virtual void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control) = 0;
|
||||
|
||||
virtual void lock() =0;
|
||||
virtual void unlock() =0;
|
||||
virtual void lock() = 0;
|
||||
virtual void unlock() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface defining transport (connection).
|
||||
* @author <a href="mailto:matej.sekoranjaATcosylab.com">Matej Sekoranja</a>
|
||||
* @version $Id: Transport.java,v 1.1 2010/05/03 14:45:39 mrkraimer Exp $
|
||||
*/
|
||||
class Transport : public epics::pvData::DeserializableControl {
|
||||
public:
|
||||
virtual ~Transport() {
|
||||
}
|
||||
typedef std::tr1::shared_ptr<Transport> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const Transport> const_shared_pointer;
|
||||
|
||||
virtual ~Transport() {}
|
||||
|
||||
/**
|
||||
* Get remote address.
|
||||
* @return remote address.
|
||||
* @return remote address, can be null.
|
||||
*/
|
||||
virtual const osiSockAddr* getRemoteAddress() const =0;
|
||||
virtual const osiSockAddr* getRemoteAddress() const = 0;
|
||||
|
||||
/**
|
||||
* Get protocol type (tcp, udp, ssl, etc.).
|
||||
* @return protocol type.
|
||||
*/
|
||||
virtual const String getType() const =0;
|
||||
|
||||
/**
|
||||
* Get context transport is living in.
|
||||
* @return context transport is living in.
|
||||
*/
|
||||
//public Context getContext();
|
||||
virtual const String getType() const = 0;
|
||||
|
||||
/**
|
||||
* Transport protocol major revision.
|
||||
@@ -181,84 +177,82 @@ namespace epics {
|
||||
* Get receive buffer size.
|
||||
* @return receive buffer size.
|
||||
*/
|
||||
virtual int getReceiveBufferSize() const =0;
|
||||
virtual int getReceiveBufferSize() const = 0;
|
||||
|
||||
/**
|
||||
* Get socket receive buffer size.
|
||||
* @return socket receive buffer size.
|
||||
*/
|
||||
virtual int getSocketReceiveBufferSize() const =0;
|
||||
virtual int getSocketReceiveBufferSize() const = 0;
|
||||
|
||||
/**
|
||||
* Transport priority.
|
||||
* @return protocol priority.
|
||||
*/
|
||||
virtual int16 getPriority() const =0;
|
||||
virtual int16 getPriority() const = 0;
|
||||
|
||||
/**
|
||||
* Set remote transport protocol minor revision.
|
||||
* @param minor protocol minor revision.
|
||||
*/
|
||||
virtual void setRemoteMinorRevision(int8 minor) =0;
|
||||
virtual void setRemoteMinorRevision(int8 minor) = 0;
|
||||
|
||||
/**
|
||||
* Set remote transport receive buffer size.
|
||||
* @param receiveBufferSize receive buffer size.
|
||||
*/
|
||||
virtual void setRemoteTransportReceiveBufferSize(
|
||||
int receiveBufferSize) =0;
|
||||
virtual void setRemoteTransportReceiveBufferSize(int receiveBufferSize) = 0;
|
||||
|
||||
/**
|
||||
* Set remote transport socket receive buffer size.
|
||||
* @param socketReceiveBufferSize remote socket receive buffer size.
|
||||
*/
|
||||
virtual void setRemoteTransportSocketReceiveBufferSize(
|
||||
int socketReceiveBufferSize) =0;
|
||||
virtual void setRemoteTransportSocketReceiveBufferSize(int socketReceiveBufferSize) = 0;
|
||||
|
||||
/**
|
||||
* Notification transport that is still alive.
|
||||
*/
|
||||
virtual void aliveNotification() =0;
|
||||
virtual void aliveNotification() = 0;
|
||||
|
||||
/**
|
||||
* Notification that transport has changed.
|
||||
*/
|
||||
virtual void changedTransport() =0;
|
||||
virtual void changedTransport() = 0;
|
||||
|
||||
/**
|
||||
* Get introspection registry for transport.
|
||||
* @return <code>IntrospectionRegistry</code> instance.
|
||||
* @return <code>IntrospectionRegistry</code> instance, can be <code>null</code>.
|
||||
*/
|
||||
virtual IntrospectionRegistry* getIntrospectionRegistry() =0;
|
||||
virtual IntrospectionRegistry* getIntrospectionRegistry() = 0;
|
||||
|
||||
/**
|
||||
* Close transport.
|
||||
* @param force flag indicating force-full (e.g. remote disconnect) close.
|
||||
*/
|
||||
virtual void close(bool force) =0;
|
||||
virtual void close(bool force) = 0;
|
||||
|
||||
/**
|
||||
* Check connection status.
|
||||
* @return <code>true</code> if connected.
|
||||
*/
|
||||
virtual bool isClosed() =0;
|
||||
virtual bool isClosed() = 0;
|
||||
|
||||
/**
|
||||
* Get transport verification status.
|
||||
* @return verification flag.
|
||||
*/
|
||||
virtual bool isVerified() =0;
|
||||
virtual bool isVerified() = 0;
|
||||
|
||||
/**
|
||||
* Notify transport that it is has been verified.
|
||||
*/
|
||||
virtual void verified() =0;
|
||||
virtual void verified() = 0;
|
||||
|
||||
/**
|
||||
* Enqueue send request.
|
||||
* @param sender
|
||||
*/
|
||||
virtual void enqueueSendRequest(TransportSender* sender) =0;
|
||||
virtual void enqueueSendRequest(TransportSender::shared_pointer& sender) = 0;
|
||||
|
||||
};
|
||||
|
||||
@@ -267,37 +261,39 @@ namespace epics {
|
||||
/**
|
||||
* Not public IF, used by Transports, etc.
|
||||
*/
|
||||
class Context : public ReferenceCountingInstance {
|
||||
class Context {
|
||||
public:
|
||||
virtual ~Context() {
|
||||
}
|
||||
/**
|
||||
* Get timer.
|
||||
* @return timer.
|
||||
*/
|
||||
virtual Timer* getTimer() = 0;
|
||||
typedef std::tr1::shared_ptr<Context> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const Context> const_shared_pointer;
|
||||
typedef std::tr1::weak_ptr<Context> weak_pointer;
|
||||
typedef std::tr1::weak_ptr<const Context> const_weak_pointer;
|
||||
|
||||
/**
|
||||
* Get transport (virtual circuit) registry.
|
||||
* @return transport (virtual circuit) registry.
|
||||
*/
|
||||
virtual TransportRegistry* getTransportRegistry() = 0;
|
||||
virtual ~Context() {}
|
||||
|
||||
virtual Channel* getChannel(pvAccessID id) = 0;
|
||||
virtual std::tr1::shared_ptr<Channel> getChannel(pvAccessID id) = 0;
|
||||
|
||||
virtual Transport::shared_pointer getSearchTransport() = 0;
|
||||
|
||||
virtual Transport* getSearchTransport() = 0;
|
||||
|
||||
virtual Configuration* getConfiguration() = 0;
|
||||
|
||||
virtual Timer::shared_pointer getTimer() = 0;
|
||||
|
||||
//virtual TransportRegistry::shared_pointer getTransportRegistry() = 0;
|
||||
virtual std::tr1::shared_ptr<TransportRegistry> getTransportRegistry() = 0;
|
||||
|
||||
virtual Configuration::shared_pointer getConfiguration() = 0;
|
||||
|
||||
virtual void beaconAnomalyNotify() = 0;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface defining response handler.
|
||||
* @author <a href="mailto:matej.sekoranjaATcosylab.com">Matej Sekoranja</a>
|
||||
* @version $Id: ResponseHandler.java,v 1.1 2010/05/03 14:45:39 mrkraimer Exp $
|
||||
*/
|
||||
class ResponseHandler {
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<ResponseHandler> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ResponseHandler> const_shared_pointer;
|
||||
|
||||
virtual ~ResponseHandler() {}
|
||||
|
||||
/**
|
||||
@@ -311,15 +307,13 @@ namespace epics {
|
||||
* Code must not manipulate buffer.
|
||||
*/
|
||||
virtual void
|
||||
handleResponse(osiSockAddr* responseFrom, Transport* transport,
|
||||
handleResponse(osiSockAddr* responseFrom, Transport::shared_pointer& transport,
|
||||
int8 version, int8 command, int payloadSize,
|
||||
epics::pvData::ByteBuffer* payloadBuffer) =0;
|
||||
epics::pvData::ByteBuffer* payloadBuffer) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Base (abstract) channel access response handler.
|
||||
* @author <a href="mailto:matej.sekoranjaATcosylab.com">Matej Sekoranja</a>
|
||||
* @version $Id: AbstractResponseHandler.java,v 1.1 2010/05/03 14:45:39 mrkraimer Exp $
|
||||
*/
|
||||
class AbstractResponseHandler : public ResponseHandler {
|
||||
public:
|
||||
@@ -331,12 +325,11 @@ namespace epics {
|
||||
_debug(context->getConfiguration()->getPropertyAsBoolean("PVACCESS_DEBUG", false)) {
|
||||
}
|
||||
|
||||
virtual ~AbstractResponseHandler() {
|
||||
}
|
||||
virtual ~AbstractResponseHandler() {}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport* transport, int8 version, int8 command,
|
||||
int payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
virtual void handleResponse(osiSockAddr* responseFrom, Transport::shared_pointer& transport,
|
||||
int8 version, int8 command, int payloadSize,
|
||||
epics::pvData::ByteBuffer* payloadBuffer);
|
||||
|
||||
protected:
|
||||
/**
|
||||
@@ -352,47 +345,50 @@ namespace epics {
|
||||
|
||||
/**
|
||||
* Client (user) of the transport.
|
||||
* @author <a href="mailto:matej.sekoranjaATcosylab.com">Matej Sekoranja</a>
|
||||
* @version $Id: TransportClient.java,v 1.1 2010/05/03 14:45:39 mrkraimer Exp $
|
||||
*/
|
||||
class TransportClient : public ReferenceCountingInstance {
|
||||
class TransportClient {
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<TransportClient> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const TransportClient> const_shared_pointer;
|
||||
typedef std::tr1::weak_ptr<TransportClient> weak_pointer;
|
||||
typedef std::tr1::weak_ptr<const TransportClient> const_weak_pointer;
|
||||
|
||||
virtual ~TransportClient() {
|
||||
}
|
||||
|
||||
// ID used to allow fast/efficient lookup
|
||||
virtual pvAccessID getID() = 0;
|
||||
|
||||
/**
|
||||
* Notification of unresponsive transport (e.g. no heartbeat detected) .
|
||||
*/
|
||||
virtual void transportUnresponsive() =0;
|
||||
virtual void transportUnresponsive() = 0;
|
||||
|
||||
/**
|
||||
* Notification of responsive transport (e.g. heartbeat detected again),
|
||||
* called to discard <code>transportUnresponsive</code> notification.
|
||||
* @param transport responsive transport.
|
||||
*/
|
||||
virtual void transportResponsive(Transport* transport) =0;
|
||||
virtual void transportResponsive(Transport::shared_pointer& transport) = 0;
|
||||
|
||||
/**
|
||||
* Notification of network change (server restarted).
|
||||
*/
|
||||
virtual void transportChanged() =0;
|
||||
virtual void transportChanged() = 0;
|
||||
|
||||
/**
|
||||
* Notification of forcefully closed transport.
|
||||
*/
|
||||
virtual void transportClosed() =0;
|
||||
virtual void transportClosed() = 0;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface defining socket connector (Connector-Transport pattern).
|
||||
* @author <a href="mailto:matej.sekoranjaATcosylab.com">Matej Sekoranja</a>
|
||||
* @version $Id: Connector.java,v 1.1 2010/05/03 14:45:39 mrkraimer Exp $
|
||||
*/
|
||||
class Connector {
|
||||
public:
|
||||
virtual ~Connector() {
|
||||
}
|
||||
virtual ~Connector() {}
|
||||
|
||||
/**
|
||||
* Connect.
|
||||
@@ -402,18 +398,15 @@ namespace epics {
|
||||
* @param[in] transportRevision transport revision to be used.
|
||||
* @param[in] priority process priority.
|
||||
* @return transport instance.
|
||||
* @throws ConnectionException
|
||||
*/
|
||||
virtual Transport* connect(TransportClient* client,
|
||||
ResponseHandler* responseHandler, osiSockAddr& address,
|
||||
short transportRevision, int16 priority) =0;
|
||||
virtual Transport::shared_pointer connect(TransportClient::shared_pointer& client,
|
||||
std::auto_ptr<ResponseHandler>& responseHandler, osiSockAddr& address,
|
||||
short transportRevision, int16 priority) = 0;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface defining reference counting transport IF.
|
||||
* @author <a href="mailto:matej.sekoranjaATcosylab.com">Matej Sekoranja</a>
|
||||
* @version $Id: ReferenceCountingTransport.java,v 1.1 2010/05/03 14:45:39 mrkraimer Exp $
|
||||
*/
|
||||
class ReferenceCountingTransport {
|
||||
public:
|
||||
@@ -425,103 +418,108 @@ namespace epics {
|
||||
* @param client client (channel) acquiring the transport
|
||||
* @return <code>true</code> if transport was granted, <code>false</code> otherwise.
|
||||
*/
|
||||
virtual bool acquire(TransportClient* client) =0;
|
||||
virtual bool acquire(TransportClient::shared_pointer& client) = 0;
|
||||
|
||||
/**
|
||||
* Releases transport.
|
||||
* @param client client (channel) releasing the transport
|
||||
*/
|
||||
virtual void release(TransportClient* client) =0;
|
||||
virtual void release(pvAccessID clientId) = 0;
|
||||
//virtual void release(TransportClient::shared_pointer& client) = 0;
|
||||
};
|
||||
|
||||
class ServerChannel {
|
||||
public:
|
||||
virtual ~ServerChannel() {
|
||||
}
|
||||
typedef std::tr1::shared_ptr<ServerChannel> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ServerChannel> const_shared_pointer;
|
||||
|
||||
virtual ~ServerChannel() {}
|
||||
/**
|
||||
* Get channel SID.
|
||||
* @return channel SID.
|
||||
*/
|
||||
virtual pvAccessID getSID() =0;
|
||||
virtual pvAccessID getSID() const = 0;
|
||||
|
||||
/**
|
||||
* Destroy server channel.
|
||||
* This method MUST BE called if overriden.
|
||||
*/
|
||||
virtual void destroy() =0;
|
||||
virtual void destroy() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface defining a transport that hosts channels.
|
||||
* @author <a href="mailto:matej.sekoranjaATcosylab.com">Matej Sekoranja</a>
|
||||
* @version $Id: ChannelHostingTransport.java,v 1.1 2010/05/03 14:45:39 mrkraimer Exp $
|
||||
* Interface defining a transport that hosts server channels.
|
||||
*/
|
||||
class ChannelHostingTransport {
|
||||
public:
|
||||
virtual ~ChannelHostingTransport() {
|
||||
}
|
||||
typedef std::tr1::shared_ptr<ChannelHostingTransport> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ChannelHostingTransport> const_shared_pointer;
|
||||
|
||||
virtual ~ChannelHostingTransport() {}
|
||||
|
||||
/**
|
||||
* Get security token.
|
||||
* @return security token, can be <code>null</code>.
|
||||
*/
|
||||
virtual epics::pvData::PVField* getSecurityToken() =0;
|
||||
virtual epics::pvData::PVField::shared_pointer getSecurityToken() = 0;
|
||||
|
||||
/**
|
||||
* Preallocate new channel SID.
|
||||
* @return new channel server id (SID).
|
||||
*/
|
||||
virtual pvAccessID preallocateChannelSID() =0;
|
||||
virtual pvAccessID preallocateChannelSID() = 0;
|
||||
|
||||
/**
|
||||
* De-preallocate new channel SID.
|
||||
* @param sid preallocated channel SID.
|
||||
*/
|
||||
virtual void depreallocateChannelSID(pvAccessID sid) =0;
|
||||
virtual void depreallocateChannelSID(pvAccessID sid) = 0;
|
||||
|
||||
/**
|
||||
* Register a new channel.
|
||||
* @param sid preallocated channel SID.
|
||||
* @param channel channel to register.
|
||||
*/
|
||||
virtual void
|
||||
registerChannel(pvAccessID sid, ServerChannel* channel) =0;
|
||||
virtual void registerChannel(pvAccessID sid, ServerChannel::shared_pointer& channel) =0;
|
||||
|
||||
/**
|
||||
* Unregister a new channel (and deallocates its handle).
|
||||
* @param sid SID
|
||||
*/
|
||||
virtual void unregisterChannel(pvAccessID sid) =0;
|
||||
virtual void unregisterChannel(pvAccessID sid) = 0;
|
||||
|
||||
/**
|
||||
* Get channel by its SID.
|
||||
* @param sid channel SID
|
||||
* @return channel with given SID, <code>null</code> otherwise
|
||||
*/
|
||||
virtual ServerChannel* getChannel(pvAccessID sid) =0;
|
||||
virtual ServerChannel::shared_pointer getChannel(pvAccessID sid) = 0;
|
||||
|
||||
/**
|
||||
* Get channel count.
|
||||
* @return channel count.
|
||||
*/
|
||||
virtual int getChannelCount() =0;
|
||||
virtual int getChannelCount() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* A request that expects an response.
|
||||
* Responses identified by its I/O ID.
|
||||
* This interface needs to be extended (to provide method called on response).
|
||||
* @author <a href="mailto:matej.sekoranjaATcosylab.com">Matej Sekoranja</a>
|
||||
*/
|
||||
class ResponseRequest : public ReferenceCountingInstance {
|
||||
class ResponseRequest {
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<ResponseRequest> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ResponseRequest> const_shared_pointer;
|
||||
typedef std::tr1::weak_ptr<ResponseRequest> weak_pointer;
|
||||
typedef std::tr1::weak_ptr<const ResponseRequest> const_weak_pointer;
|
||||
|
||||
virtual ~ResponseRequest() {}
|
||||
|
||||
/**
|
||||
* Get I/O ID.
|
||||
* @return ioid
|
||||
*/
|
||||
virtual pvAccessID getIOID() = 0;
|
||||
virtual pvAccessID getIOID() const = 0;
|
||||
|
||||
/**
|
||||
* Timeout notification.
|
||||
@@ -543,7 +541,7 @@ namespace epics {
|
||||
* Get request requester.
|
||||
* @return request requester.
|
||||
*/
|
||||
virtual epics::pvData::Requester* getRequester() = 0;
|
||||
virtual std::tr1::shared_ptr<epics::pvData::Requester> getRequester() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -552,6 +550,9 @@ namespace epics {
|
||||
*/
|
||||
class DataResponse : public ResponseRequest {
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<DataResponse> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const DataResponse> const_shared_pointer;
|
||||
|
||||
virtual ~DataResponse() {}
|
||||
|
||||
/**
|
||||
@@ -560,7 +561,7 @@ namespace epics {
|
||||
* @param version
|
||||
* @param payloadBuffer
|
||||
*/
|
||||
virtual void response(Transport* transport, int8 version, ByteBuffer* payloadBuffer) = 0;
|
||||
virtual void response(Transport::shared_pointer& transport, int8 version, ByteBuffer* payloadBuffer) = 0;
|
||||
|
||||
};
|
||||
|
||||
@@ -573,6 +574,9 @@ namespace epics {
|
||||
*/
|
||||
class SubscriptionRequest /*: public ResponseRequest*/ {
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<SubscriptionRequest> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const SubscriptionRequest> const_shared_pointer;
|
||||
|
||||
virtual ~SubscriptionRequest() {}
|
||||
|
||||
/**
|
||||
@@ -584,7 +588,7 @@ namespace epics {
|
||||
* Rescubscribe (e.g. when server was restarted)
|
||||
* @param transport new transport to be used.
|
||||
*/
|
||||
virtual void resubscribeSubscription(Transport* transport) = 0;
|
||||
virtual void resubscribeSubscription(Transport::shared_pointer& transport) = 0;
|
||||
};
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,8 +10,11 @@
|
||||
|
||||
#include <pvAccess.h>
|
||||
#include <remote.h>
|
||||
#include <sharedPtr.h>
|
||||
#include <channelSearchManager.h>
|
||||
|
||||
class ChannelSearchManager;
|
||||
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
@@ -25,17 +28,22 @@ namespace epics {
|
||||
public BaseSearchInstance
|
||||
{
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<ChannelImpl> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ChannelImpl> const_shared_pointer;
|
||||
typedef std::tr1::weak_ptr<ChannelImpl> weak_pointer;
|
||||
typedef std::tr1::weak_ptr<const ChannelImpl> const_weak_pointer;
|
||||
|
||||
virtual pvAccessID getChannelID() = 0;
|
||||
virtual void destroyChannel(bool force) = 0;
|
||||
virtual void connectionCompleted(pvAccessID sid/*, rights*/) = 0;
|
||||
virtual void createChannelFailed() = 0;
|
||||
virtual ClientContextImpl* getContext() = 0;
|
||||
virtual std::tr1::shared_ptr<ClientContextImpl> getContext() = 0;
|
||||
|
||||
virtual pvAccessID getServerChannelID() = 0;
|
||||
virtual void registerResponseRequest(ResponseRequest* responseRequest) = 0;
|
||||
virtual void unregisterResponseRequest(ResponseRequest* responseRequest) = 0;
|
||||
virtual Transport* checkAndGetTransport() = 0;
|
||||
virtual Transport* getTransport() = 0;
|
||||
virtual void registerResponseRequest(ResponseRequest::shared_pointer& responseRequest) = 0;
|
||||
virtual void unregisterResponseRequest(pvAccessID ioid) = 0;
|
||||
virtual Transport::shared_pointer checkAndGetTransport() = 0;
|
||||
virtual Transport::shared_pointer getTransport() = 0;
|
||||
|
||||
static Status channelDestroyed;
|
||||
static Status channelDisconnected;
|
||||
@@ -45,29 +53,34 @@ namespace epics {
|
||||
class ClientContextImpl : public ClientContext, public Context
|
||||
{
|
||||
public:
|
||||
virtual ChannelSearchManager* getChannelSearchManager() = 0;
|
||||
typedef std::tr1::shared_ptr<ClientContextImpl> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ClientContextImpl> const_shared_pointer;
|
||||
typedef std::tr1::weak_ptr<ClientContextImpl> weak_pointer;
|
||||
typedef std::tr1::weak_ptr<const ClientContextImpl> const_weak_pointer;
|
||||
|
||||
virtual ChannelSearchManager::shared_pointer getChannelSearchManager() = 0;
|
||||
virtual void checkChannelName(String& name) = 0;
|
||||
|
||||
virtual void registerChannel(ChannelImpl* channel) = 0;
|
||||
virtual void unregisterChannel(ChannelImpl* channel) = 0;
|
||||
virtual void registerChannel(ChannelImpl::shared_pointer& channel) = 0;
|
||||
virtual void unregisterChannel(ChannelImpl::shared_pointer& channel) = 0;
|
||||
|
||||
virtual void destroyChannel(ChannelImpl* channel, bool force) = 0;
|
||||
virtual ChannelImpl* createChannelInternal(String name, ChannelRequester* requester, short priority, InetAddrVector* addresses) = 0;
|
||||
virtual void destroyChannel(ChannelImpl::shared_pointer& channel, bool force) = 0;
|
||||
virtual ChannelImpl::shared_pointer createChannelInternal(String name, ChannelRequester::shared_pointer& requester, short priority, std::auto_ptr<InetAddrVector>& addresses) = 0;
|
||||
|
||||
virtual ResponseRequest* getResponseRequest(pvAccessID ioid) = 0;
|
||||
virtual pvAccessID registerResponseRequest(ResponseRequest* request) = 0;
|
||||
virtual ResponseRequest* unregisterResponseRequest(ResponseRequest* request) = 0;
|
||||
virtual ResponseRequest::shared_pointer getResponseRequest(pvAccessID ioid) = 0;
|
||||
virtual pvAccessID registerResponseRequest(ResponseRequest::shared_pointer& request) = 0;
|
||||
virtual ResponseRequest::shared_pointer unregisterResponseRequest(pvAccessID ioid) = 0;
|
||||
|
||||
|
||||
virtual Transport* getTransport(TransportClient* client, osiSockAddr* serverAddress, int16 minorRevision, int16 priority) = 0;
|
||||
virtual Transport::shared_pointer getTransport(TransportClient::shared_pointer& client, osiSockAddr* serverAddress, int16 minorRevision, int16 priority) = 0;
|
||||
|
||||
virtual void beaconAnomalyNotify() = 0;
|
||||
|
||||
virtual BeaconHandler* getBeaconHandler(osiSockAddr* responseFrom) = 0;
|
||||
virtual std::tr1::shared_ptr<BeaconHandler> getBeaconHandler(osiSockAddr* responseFrom) = 0;
|
||||
|
||||
};
|
||||
|
||||
extern ClientContextImpl* createClientContextImpl();
|
||||
extern ClientContextImpl::shared_pointer createClientContextImpl();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,11 @@ const Status BaseChannelRequester::otherRequestPendingStatus = Status(Status::ST
|
||||
|
||||
const int32 BaseChannelRequester::NULL_REQUEST = -1;
|
||||
|
||||
BaseChannelRequester::BaseChannelRequester(ServerContextImpl* context, ServerChannelImpl* channel,const pvAccessID ioid, Transport* transport) :
|
||||
BaseChannelRequester::BaseChannelRequester(
|
||||
ServerContextImpl::shared_pointer& context,
|
||||
ServerChannelImpl::shared_pointer& channel,
|
||||
const pvAccessID ioid,
|
||||
Transport::shared_pointer& transport) :
|
||||
_ioid(ioid),
|
||||
_transport(transport),
|
||||
_channel(channel),
|
||||
@@ -63,14 +67,16 @@ void BaseChannelRequester::message(const String message, const epics::pvData::Me
|
||||
BaseChannelRequester::message(_transport, _ioid, message, messageType);
|
||||
}
|
||||
|
||||
void BaseChannelRequester::message(Transport* transport, const pvAccessID ioid, const String message, const MessageType messageType)
|
||||
void BaseChannelRequester::message(Transport::shared_pointer& transport, const pvAccessID ioid, const String message, const MessageType messageType)
|
||||
{
|
||||
transport->enqueueSendRequest(new BaseChannelRequesterMessageTransportSender(ioid, message, messageType));
|
||||
TransportSender::shared_pointer sender(new BaseChannelRequesterMessageTransportSender(ioid, message, messageType));
|
||||
transport->enqueueSendRequest(sender);
|
||||
}
|
||||
|
||||
void BaseChannelRequester::sendFailureMessage(const int8 command, Transport* transport, const pvAccessID ioid, const int8 qos, const Status status)
|
||||
void BaseChannelRequester::sendFailureMessage(const int8 command, Transport::shared_pointer& transport, const pvAccessID ioid, const int8 qos, const Status status)
|
||||
{
|
||||
transport->enqueueSendRequest(new BaseChannelRequesterFailureMessageTransportSender(command, transport, ioid, qos, status));
|
||||
TransportSender::shared_pointer sender(new BaseChannelRequesterFailureMessageTransportSender(command, transport, ioid, qos, status));
|
||||
transport->enqueueSendRequest(sender);
|
||||
}
|
||||
|
||||
BaseChannelRequesterMessageTransportSender::BaseChannelRequesterMessageTransportSender(const pvAccessID ioid, const String message,const epics::pvData::MessageType messageType):
|
||||
@@ -98,18 +104,8 @@ void BaseChannelRequesterMessageTransportSender::unlock()
|
||||
// noop
|
||||
}
|
||||
|
||||
void BaseChannelRequesterMessageTransportSender::release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
void BaseChannelRequesterMessageTransportSender::acquire()
|
||||
{
|
||||
// noop
|
||||
}
|
||||
|
||||
BaseChannelRequesterFailureMessageTransportSender::BaseChannelRequesterFailureMessageTransportSender(const int8 command,
|
||||
Transport* transport, const pvAccessID ioid, const int8 qos, const Status status) :
|
||||
Transport::shared_pointer& transport, const pvAccessID ioid, const int8 qos, const Status& status) :
|
||||
_command(command),
|
||||
_ioid(ioid),
|
||||
_qos(qos),
|
||||
@@ -136,15 +132,6 @@ void BaseChannelRequesterFailureMessageTransportSender::unlock()
|
||||
// noop
|
||||
}
|
||||
|
||||
void BaseChannelRequesterFailureMessageTransportSender::release()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
void BaseChannelRequesterFailureMessageTransportSender::acquire()
|
||||
{
|
||||
// noop
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,16 +17,17 @@ namespace pvAccess {
|
||||
class BaseChannelRequester : virtual public epics::pvData::Requester, public epics::pvData::Destroyable
|
||||
{
|
||||
public:
|
||||
BaseChannelRequester(ServerContextImpl* context, ServerChannelImpl* channel,const pvAccessID ioid, Transport* transport);
|
||||
~BaseChannelRequester() {};
|
||||
BaseChannelRequester(ServerContextImpl::shared_pointer& context, ServerChannelImpl::shared_pointer& channel,
|
||||
const pvAccessID ioid, Transport::shared_pointer& transport);
|
||||
virtual ~BaseChannelRequester() {};
|
||||
|
||||
boolean startRequest(int32 qos);
|
||||
bool startRequest(int32 qos);
|
||||
void stopRequest();
|
||||
int32 getPendingRequest();
|
||||
String getRequesterName();
|
||||
void message(const String message, const epics::pvData::MessageType messageType);
|
||||
static void message(Transport* transport, const pvAccessID ioid, const String message, const epics::pvData::MessageType messageType);
|
||||
static void sendFailureMessage(const int8 command, Transport* transport, const pvAccessID ioid, const int8 qos, const Status status);
|
||||
static void message(Transport::shared_pointer& transport, const pvAccessID ioid, const String message, const epics::pvData::MessageType messageType);
|
||||
static void sendFailureMessage(const int8 command, Transport::shared_pointer& transport, const pvAccessID ioid, const int8 qos, const Status status);
|
||||
|
||||
static const Status okStatus;
|
||||
static const Status badCIDStatus;
|
||||
@@ -37,11 +38,11 @@ public:
|
||||
static const Status otherRequestPendingStatus;
|
||||
protected:
|
||||
const pvAccessID _ioid;
|
||||
Transport* _transport;
|
||||
ServerChannelImpl* _channel;
|
||||
Transport::shared_pointer _transport;
|
||||
ServerChannelImpl::shared_pointer _channel;
|
||||
epics::pvData::Mutex _mutex;
|
||||
private:
|
||||
ServerContextImpl* _context;
|
||||
ServerContextImpl::shared_pointer _context;
|
||||
static const int32 NULL_REQUEST;
|
||||
int32 _pendingRequest;
|
||||
};
|
||||
@@ -53,8 +54,6 @@ public:
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control);
|
||||
void lock();
|
||||
void unlock();
|
||||
void release();
|
||||
void acquire();
|
||||
private:
|
||||
const pvAccessID _ioid;
|
||||
const String _message;
|
||||
@@ -64,19 +63,17 @@ private:
|
||||
class BaseChannelRequesterFailureMessageTransportSender : public TransportSender
|
||||
{
|
||||
public:
|
||||
BaseChannelRequesterFailureMessageTransportSender(const int8 command, Transport* transport, const pvAccessID ioid, const int8 qos, const Status status);
|
||||
BaseChannelRequesterFailureMessageTransportSender(const int8 command, Transport::shared_pointer& transport, const pvAccessID ioid, const int8 qos, const Status& status);
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control);
|
||||
void lock();
|
||||
void unlock();
|
||||
void release();
|
||||
void acquire();
|
||||
|
||||
private:
|
||||
const int8 _command;
|
||||
const pvAccessID _ioid;
|
||||
const int8 _qos;
|
||||
const Status _status;
|
||||
Transport* _transport;
|
||||
Transport::shared_pointer _transport;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
146
pvAccessApp/server/beaconEmitter.cpp
Normal file
146
pvAccessApp/server/beaconEmitter.cpp
Normal file
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* beaconEmitter.cpp
|
||||
*/
|
||||
|
||||
#include "beaconEmitter.h"
|
||||
|
||||
#include <introspectionRegistry.h>
|
||||
|
||||
#include <errlog.h>
|
||||
#include <algorithm>
|
||||
|
||||
#include <serverContext.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
namespace epics { namespace pvAccess {
|
||||
|
||||
const float BeaconEmitter::EPICS_CA_MIN_BEACON_PERIOD = 1.0;
|
||||
const float BeaconEmitter::EPICS_CA_MIN_BEACON_COUNT_LIMIT = 3.0;
|
||||
|
||||
//BeaconEmitter::BeaconEmitter(Transport::shared_pointer& transport, ServerContextImpl::shared_pointer& context) :
|
||||
BeaconEmitter::BeaconEmitter(Transport::shared_pointer& transport, std::tr1::shared_ptr<ServerContextImpl>& context) :
|
||||
_transport(transport),
|
||||
_beaconSequenceID(0),
|
||||
_startupTime(),
|
||||
_fastBeaconPeriod(std::max(context->getBeaconPeriod(), EPICS_CA_MIN_BEACON_PERIOD)),
|
||||
_slowBeaconPeriod(std::max(180.0, _fastBeaconPeriod)), // TODO configurable
|
||||
_beaconCountLimit((int16)std::max(10.0f, EPICS_CA_MIN_BEACON_COUNT_LIMIT)), // TODO configurable
|
||||
_serverAddress(*(context->getServerInetAddress())),
|
||||
_serverPort(context->getServerPort()),
|
||||
_serverStatusProvider(context->getBeaconServerStatusProvider()),
|
||||
_timer(context->getTimer()),
|
||||
_timerNode(*this)
|
||||
{
|
||||
_startupTime.getCurrent();
|
||||
}
|
||||
|
||||
BeaconEmitter::BeaconEmitter(Transport::shared_pointer& transport, const osiSockAddr& serverAddress) :
|
||||
_transport(transport),
|
||||
_beaconSequenceID(0),
|
||||
_startupTime(),
|
||||
_fastBeaconPeriod(EPICS_CA_MIN_BEACON_PERIOD),
|
||||
_slowBeaconPeriod(180.0),
|
||||
_beaconCountLimit(10),
|
||||
_serverAddress(serverAddress),
|
||||
_serverPort(serverAddress.ia.sin_port),
|
||||
_serverStatusProvider(),
|
||||
_timer(new Timer("pvAccess-server timer", lowPriority)),
|
||||
_timerNode(*this)
|
||||
{
|
||||
_startupTime.getCurrent();
|
||||
}
|
||||
|
||||
BeaconEmitter::~BeaconEmitter()
|
||||
{
|
||||
destroy();
|
||||
}
|
||||
|
||||
void BeaconEmitter::lock()
|
||||
{
|
||||
//noop
|
||||
}
|
||||
|
||||
void BeaconEmitter::unlock()
|
||||
{
|
||||
//noop
|
||||
}
|
||||
|
||||
void BeaconEmitter::send(ByteBuffer* buffer, TransportSendControl* control)
|
||||
{
|
||||
// get server status
|
||||
PVField::shared_pointer serverStatus;
|
||||
if(_serverStatusProvider.get())
|
||||
{
|
||||
try
|
||||
{
|
||||
serverStatus = _serverStatusProvider->getServerStatusData();
|
||||
}
|
||||
catch (...) {
|
||||
// we have to proctect internal code from external implementation...
|
||||
errlogSevPrintf(errlogMinor, "BeaconServerStatusProvider implementation thrown an exception.");
|
||||
}
|
||||
}
|
||||
|
||||
// send beacon
|
||||
control->startMessage((int8)0, (sizeof(int16)+2*sizeof(int32)+128+sizeof(int16))/sizeof(int8));
|
||||
|
||||
buffer->putShort(_beaconSequenceID);
|
||||
buffer->putLong((int64)_startupTime.getSecondsPastEpoch());
|
||||
buffer->putInt((int32)_startupTime.getNanoSeconds());
|
||||
|
||||
// NOTE: is it possible (very likely) that address is any local address ::ffff:0.0.0.0
|
||||
encodeAsIPv6Address(buffer, &_serverAddress);
|
||||
buffer->putShort((int16)_serverPort);
|
||||
|
||||
if (serverStatus)
|
||||
{
|
||||
// introspection interface + data
|
||||
IntrospectionRegistry::serializeFull(serverStatus->getField(), buffer, control);
|
||||
serverStatus->serialize(buffer, control);
|
||||
}
|
||||
else
|
||||
{
|
||||
IntrospectionRegistry::serializeFull(FieldConstPtr(), buffer, control);
|
||||
}
|
||||
control->flush(true);
|
||||
|
||||
// increment beacon sequence ID
|
||||
_beaconSequenceID++;
|
||||
|
||||
reschedule();
|
||||
}
|
||||
|
||||
void BeaconEmitter::timerStopped()
|
||||
{
|
||||
//noop
|
||||
}
|
||||
|
||||
void BeaconEmitter::destroy()
|
||||
{
|
||||
_timerNode.cancel();
|
||||
}
|
||||
|
||||
void BeaconEmitter::start()
|
||||
{
|
||||
_timer->scheduleAfterDelay(_timerNode, 0.0);
|
||||
}
|
||||
|
||||
void BeaconEmitter::reschedule()
|
||||
{
|
||||
const double period = (_beaconSequenceID >= _beaconCountLimit) ? _slowBeaconPeriod : _fastBeaconPeriod;
|
||||
if (period > 0)
|
||||
{
|
||||
_timer->scheduleAfterDelay(_timerNode, period);
|
||||
}
|
||||
}
|
||||
|
||||
void BeaconEmitter::callback()
|
||||
{
|
||||
// requires this instance has already a valid pointer to this
|
||||
TransportSender::shared_pointer thisSender = shared_from_this();
|
||||
_transport->enqueueSendRequest(thisSender);
|
||||
}
|
||||
|
||||
}}
|
||||
|
||||
@@ -5,83 +5,76 @@
|
||||
#ifndef BEACONEMITTER_H
|
||||
#define BEACONEMITTER_H
|
||||
|
||||
#include "timer.h"
|
||||
#include "remote.h"
|
||||
#include "beaconServerStatusProvider.h"
|
||||
#include "inetAddressUtil.h"
|
||||
#include "introspectionRegistry.h"
|
||||
#include "serverContext.h"
|
||||
|
||||
|
||||
#include <timer.h>
|
||||
#include <timeStamp.h>
|
||||
#include <remote.h>
|
||||
|
||||
#include <osiSock.h>
|
||||
#include <errlog.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <iostream>
|
||||
|
||||
using namespace epics::pvData;
|
||||
#include <beaconServerStatusProvider.h>
|
||||
//#include <serverContext.h>
|
||||
#include <sharedPtr.h>
|
||||
|
||||
namespace epics { namespace pvAccess {
|
||||
|
||||
class ServerContextImpl;
|
||||
class ServerContextImpl;
|
||||
|
||||
/**
|
||||
* BeaconEmitter
|
||||
*
|
||||
* @author gjansa
|
||||
*/
|
||||
class BeaconEmitter: public TransportSender, public TimerCallback
|
||||
class BeaconEmitter:
|
||||
public TransportSender,
|
||||
public epics::pvData::TimerCallback,
|
||||
public std::tr1::enable_shared_from_this<BeaconEmitter>
|
||||
{
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<BeaconEmitter> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const BeaconEmitter> const_shared_pointer;
|
||||
|
||||
/**
|
||||
* Constructor.
|
||||
* @param transport transport to be used to send beacons.
|
||||
* @param context CA context.
|
||||
*/
|
||||
BeaconEmitter(Transport* transport, ServerContextImpl* context);
|
||||
/**
|
||||
// BeaconEmitter(Transport::shared_pointer& transport, ServerContextImpl::shared_pointer& context);
|
||||
BeaconEmitter(Transport::shared_pointer& transport, std::tr1::shared_ptr<ServerContextImpl>& context);
|
||||
|
||||
/**
|
||||
* Test Constructor (ohne context)
|
||||
* @param transport transport to be used to send beacons.
|
||||
*/
|
||||
BeaconEmitter(Transport* transport,const osiSockAddr* serverAddress);
|
||||
BeaconEmitter(Transport::shared_pointer& transport, const osiSockAddr& serverAddress);
|
||||
|
||||
virtual ~BeaconEmitter();
|
||||
|
||||
/*
|
||||
* @see TransportSender#lock()
|
||||
*/
|
||||
void lock();
|
||||
/*
|
||||
* @see TransportSender#unlock()
|
||||
*/
|
||||
void unlock();
|
||||
|
||||
void acquire();
|
||||
void release();
|
||||
|
||||
void send(ByteBuffer* buffer, TransportSendControl* control);
|
||||
/**
|
||||
* noop
|
||||
*/
|
||||
|
||||
void timerStopped();
|
||||
/**
|
||||
* noop
|
||||
*/
|
||||
void destroy();
|
||||
|
||||
/**
|
||||
* Start emitting.
|
||||
*/
|
||||
void start();
|
||||
/**
|
||||
|
||||
/**
|
||||
* Reschedule timer.
|
||||
*/
|
||||
void reschedule();
|
||||
/**
|
||||
|
||||
/**
|
||||
* Timer callback.
|
||||
*/
|
||||
void callback();
|
||||
|
||||
private:
|
||||
void destroy();
|
||||
|
||||
private:
|
||||
|
||||
/**
|
||||
* Minimal (initial) CA beacon period (in seconds).
|
||||
*/
|
||||
@@ -92,15 +85,10 @@ namespace epics { namespace pvAccess {
|
||||
*/
|
||||
static const float EPICS_CA_MIN_BEACON_COUNT_LIMIT;
|
||||
|
||||
/**
|
||||
* Timer.
|
||||
*/
|
||||
Timer* _timer;
|
||||
|
||||
/**
|
||||
* Transport.
|
||||
*/
|
||||
Transport* _transport;
|
||||
Transport::shared_pointer _transport;
|
||||
|
||||
/**
|
||||
* Beacon sequence ID.
|
||||
@@ -110,7 +98,7 @@ namespace epics { namespace pvAccess {
|
||||
/**
|
||||
* Startup timestamp (when clients detect a change, they will consider server restarted).
|
||||
*/
|
||||
TimeStamp* _startupTime;
|
||||
epics::pvData::TimeStamp _startupTime;
|
||||
|
||||
/**
|
||||
* Fast (at startup) beacon period (in sec).
|
||||
@@ -130,7 +118,7 @@ namespace epics { namespace pvAccess {
|
||||
/**
|
||||
* Server address.
|
||||
*/
|
||||
const osiSockAddr* _serverAddress;
|
||||
const osiSockAddr _serverAddress;
|
||||
|
||||
/**
|
||||
* Server port.
|
||||
@@ -140,14 +128,19 @@ namespace epics { namespace pvAccess {
|
||||
/**
|
||||
* Server status provider implementation (optional).
|
||||
*/
|
||||
BeaconServerStatusProvider* _serverStatusProvider;
|
||||
BeaconServerStatusProvider::shared_pointer _serverStatusProvider;
|
||||
|
||||
/**
|
||||
* Timer.
|
||||
*/
|
||||
Timer::shared_pointer _timer;
|
||||
|
||||
/**
|
||||
* Timer task node.
|
||||
*/
|
||||
TimerNode* _timerNode;
|
||||
epics::pvData::TimerNode _timerNode;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /* INTROSPECTIONREGISTRY_H */
|
||||
#endif /* BEACONEMITTER_H */
|
||||
@@ -3,30 +3,23 @@
|
||||
*/
|
||||
|
||||
#include "beaconServerStatusProvider.h"
|
||||
#include <serverContext.h>
|
||||
|
||||
using namespace epics::pvData;
|
||||
|
||||
namespace epics { namespace pvAccess {
|
||||
|
||||
BeaconServerStatusProvider::BeaconServerStatusProvider( ServerContext* context): _context(context)
|
||||
{
|
||||
if(context == NULL)
|
||||
{
|
||||
THROW_BASE_EXCEPTION("null context");
|
||||
}
|
||||
initialize();
|
||||
}
|
||||
|
||||
BeaconServerStatusProvider::BeaconServerStatusProvider()
|
||||
DefaultBeaconServerStatusProvider::DefaultBeaconServerStatusProvider(ServerContext::shared_pointer& context): _context(context)
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
|
||||
BeaconServerStatusProvider::~BeaconServerStatusProvider()
|
||||
DefaultBeaconServerStatusProvider::~DefaultBeaconServerStatusProvider()
|
||||
{
|
||||
}
|
||||
|
||||
void BeaconServerStatusProvider::initialize()
|
||||
void DefaultBeaconServerStatusProvider::initialize()
|
||||
{
|
||||
PVDataCreate* pvDataCreate = getPVDataCreate();
|
||||
FieldCreate* fieldCreate = getFieldCreate();
|
||||
FieldConstPtrArray fields = new FieldConstPtr[6];
|
||||
// TODO hierarchy can be used...
|
||||
@@ -37,13 +30,13 @@ void BeaconServerStatusProvider::initialize()
|
||||
fields[4] = fieldCreate->createScalar("deadlocks",pvInt);
|
||||
fields[5] = fieldCreate->createScalar("averageSystemLoad",pvDouble);
|
||||
|
||||
_status = pvDataCreate->createPVStructure(NULL,"status",6,fields);
|
||||
_status.reset(getPVDataCreate()->createPVStructure(0,"status",6,fields));
|
||||
}
|
||||
|
||||
PVFieldPtr BeaconServerStatusProvider::getServerStatusData()
|
||||
PVField::shared_pointer DefaultBeaconServerStatusProvider::getServerStatusData()
|
||||
{
|
||||
//TODO implement
|
||||
return static_cast<PVFieldPtr>(_status);
|
||||
//TODO implement (fill data)
|
||||
return _status;
|
||||
}
|
||||
|
||||
}}
|
||||
65
pvAccessApp/server/beaconServerStatusProvider.h
Normal file
65
pvAccessApp/server/beaconServerStatusProvider.h
Normal file
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* beaconServerStatusProvider.h
|
||||
*/
|
||||
|
||||
#ifndef BEACONSERVERSTATUSPROVIDER_H
|
||||
#define BEACONSERVERSTATUSPROVIDER_H
|
||||
|
||||
#include <pvData.h>
|
||||
//#include <serverContext.h>
|
||||
#include <sharedPtr.h>
|
||||
|
||||
namespace epics { namespace pvAccess {
|
||||
|
||||
class ServerContext;
|
||||
|
||||
/**
|
||||
* BeaconServerStatusProvider
|
||||
*/
|
||||
class BeaconServerStatusProvider
|
||||
{
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<BeaconServerStatusProvider> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const BeaconServerStatusProvider> const_shared_pointer;
|
||||
|
||||
/**
|
||||
* Gets server status data.
|
||||
*/
|
||||
virtual epics::pvData::PVField::shared_pointer getServerStatusData() = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* DefaultBeaconServerStatusProvider
|
||||
*/
|
||||
class DefaultBeaconServerStatusProvider : public BeaconServerStatusProvider
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
* @param context CA context.
|
||||
*/
|
||||
// DefaultBeaconServerStatusProvider(ServerContext::shared_pointer& context);
|
||||
DefaultBeaconServerStatusProvider(std::tr1::shared_ptr<ServerContext>& context);
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
virtual ~DefaultBeaconServerStatusProvider();
|
||||
|
||||
virtual epics::pvData::PVField::shared_pointer getServerStatusData();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Initialize
|
||||
*/
|
||||
void initialize();
|
||||
|
||||
|
||||
private:
|
||||
epics::pvData::PVStructure::shared_pointer _status;
|
||||
std::tr1::shared_ptr<ServerContext> _context;
|
||||
//ServerContext::shared_pointer _context;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif /* BEACONSERVERSTATUSPROVIDER_H */
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* referencedTransportSender.cpp
|
||||
*/
|
||||
|
||||
#include "referencedTransportSender.h"
|
||||
|
||||
using namespace epics::pvData;
|
||||
|
||||
namespace epics { namespace pvAccess {
|
||||
|
||||
ReferencedTransportSender::ReferencedTransportSender() :
|
||||
_refCount(1)
|
||||
{}
|
||||
|
||||
ReferencedTransportSender::~ReferencedTransportSender()
|
||||
{
|
||||
}
|
||||
|
||||
void ReferencedTransportSender::release()
|
||||
{
|
||||
_refMutex.lock();
|
||||
_refCount--;
|
||||
_refMutex.unlock();
|
||||
if (_refCount == 0)
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
void ReferencedTransportSender::acquire()
|
||||
{
|
||||
Lock guard(_refMutex);
|
||||
_refCount++;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* referencedTransportSender.h
|
||||
*/
|
||||
|
||||
#ifndef REFERENCEDTRANSPORTSENDER_H_
|
||||
#define REFERENCEDTRANSPORTSENDER_H_
|
||||
|
||||
#include "remote.h"
|
||||
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
class ReferencedTransportSender : public TransportSender
|
||||
{
|
||||
public:
|
||||
ReferencedTransportSender();
|
||||
virtual ~ReferencedTransportSender();
|
||||
void release();
|
||||
void acquire();
|
||||
private:
|
||||
epics::pvData::Mutex _refMutex;
|
||||
int32 _refCount;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#endif /* REFERENCEDTRANSPORTSENDER_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,36 +1,26 @@
|
||||
/*
|
||||
* responseHandlers.h
|
||||
*
|
||||
* Created on: Jan 5, 2011
|
||||
* Author: user
|
||||
*/
|
||||
|
||||
#ifndef RESPONSEHANDLERS_H_
|
||||
#define RESPONSEHANDLERS_H_
|
||||
|
||||
#include "serverContext.h"
|
||||
#include "remote.h"
|
||||
#include <remote.h>
|
||||
#include "serverChannelImpl.h"
|
||||
#include "baseChannelRequester.h"
|
||||
#include "referencedTransportSender.h"
|
||||
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
/**
|
||||
* @author <a href="mailto:matej.sekoranjaATcosylab.com">Matej Sekoranja</a>
|
||||
* @version $Id: AbstractServerResponseHandler.java,v 1.1 2010/05/03 14:45:39 mrkraimer Exp $
|
||||
*/
|
||||
class AbstractServerResponseHandler : public AbstractResponseHandler {
|
||||
protected:
|
||||
ServerContextImpl* _context;
|
||||
ServerContextImpl::shared_pointer _context;
|
||||
public:
|
||||
/**
|
||||
* @param context
|
||||
* @param description
|
||||
*/
|
||||
AbstractServerResponseHandler(ServerContextImpl* context, String description) :
|
||||
AbstractResponseHandler(context, description), _context(context) {
|
||||
AbstractServerResponseHandler(ServerContextImpl::shared_pointer& context, String description) :
|
||||
AbstractResponseHandler(context.get(), description), _context(context) {
|
||||
}
|
||||
|
||||
virtual ~AbstractServerResponseHandler() {
|
||||
@@ -39,15 +29,10 @@ namespace epics {
|
||||
|
||||
/**
|
||||
* Bad request handler.
|
||||
* @author <a href="mailto:matej.sekoranjaATcosylab.com">Matej Sekoranja</a>
|
||||
* @version $Id: BadResponse.java,v 1.1 2010/05/03 14:45:39 mrkraimer Exp $
|
||||
*/
|
||||
class ServerBadResponse : public AbstractServerResponseHandler {
|
||||
public:
|
||||
/**
|
||||
* @param context
|
||||
*/
|
||||
ServerBadResponse(ServerContextImpl* context) :
|
||||
ServerBadResponse(ServerContextImpl::shared_pointer& context) :
|
||||
AbstractServerResponseHandler(context, "Bad request") {
|
||||
}
|
||||
|
||||
@@ -55,97 +40,78 @@ namespace epics {
|
||||
}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport* transport, int8 version, int8 command,
|
||||
Transport::shared_pointer& transport, int8 version, int8 command,
|
||||
int payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
};
|
||||
|
||||
/**
|
||||
* CAS request handler - main handler which dispatches requests to appropriate handlers.
|
||||
* @author <a href="mailto:matej.sekoranjaATcosylab.com">Matej Sekoranja</a>
|
||||
* @version $Id: ServerResponseHandler.java,v 1.1 2010/05/03 14:45:48 mrkraimer Exp $
|
||||
*/
|
||||
class ServerResponseHandler : public ResponseHandler {
|
||||
public:
|
||||
ServerResponseHandler(ServerContextImpl* context);
|
||||
ServerResponseHandler(ServerContextImpl::shared_pointer& context);
|
||||
|
||||
virtual ~ServerResponseHandler();
|
||||
virtual ~ServerResponseHandler() {
|
||||
}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport* transport, int8 version, int8 command,
|
||||
Transport::shared_pointer& transport, int8 version, int8 command,
|
||||
int payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
private:
|
||||
static const int HANDLER_TABLE_LENGTH = 28;
|
||||
/**
|
||||
* Bad response handlers.
|
||||
*/
|
||||
ServerBadResponse *_badResponse;
|
||||
/**
|
||||
* Table of response handlers for each command ID.
|
||||
*/
|
||||
ResponseHandler** _handlerTable;
|
||||
vector<ResponseHandler::shared_pointer> m_handlerTable;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* Connection validation message handler.
|
||||
* @author <a href="mailto:matej.sekoranjaATcosylab.com">Matej Sekoranja</a>
|
||||
* @version $Id: ConnectionValidationHandler.java,v 1.1 2010/05/03 14:45:39 mrkraimer Exp $
|
||||
*/
|
||||
class ServerConnectionValidationHandler : public AbstractServerResponseHandler {
|
||||
public:
|
||||
/**
|
||||
* @param context
|
||||
*/
|
||||
ServerConnectionValidationHandler(ServerContextImpl* context) :
|
||||
ServerConnectionValidationHandler(ServerContextImpl::shared_pointer& context) :
|
||||
AbstractServerResponseHandler(context, "Connection validation") {
|
||||
}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport* transport, int8 version, int8 command,
|
||||
Transport::shared_pointer& transport, int8 version, int8 command,
|
||||
int payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
};
|
||||
|
||||
/**
|
||||
* NOOP response.
|
||||
* @author <a href="mailto:matej.sekoranjaATcosylab.com">Matej Sekoranja</a>
|
||||
* @version $Id: NoopResponse.java,v 1.1 2010/05/03 14:45:39 mrkraimer Exp $
|
||||
*/
|
||||
class ServerNoopResponse : public AbstractServerResponseHandler {
|
||||
public:
|
||||
/**
|
||||
* @param context
|
||||
* @param description
|
||||
*/
|
||||
ServerNoopResponse(ServerContextImpl* context, String description) :
|
||||
ServerNoopResponse(ServerContextImpl::shared_pointer& context, String description) :
|
||||
AbstractServerResponseHandler(context, description) {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Echo request handler.
|
||||
* @author <a href="mailto:matej.sekoranjaATcosylab.com">Matej Sekoranja</a>
|
||||
* @version $Id: EchoHandler.java,v 1.1 2010/05/03 14:45:39 mrkraimer Exp $
|
||||
*/
|
||||
class ServerEchoHandler : public AbstractServerResponseHandler {
|
||||
public:
|
||||
/**
|
||||
* @param context
|
||||
*/
|
||||
ServerEchoHandler(ServerContextImpl* context) :
|
||||
ServerEchoHandler(ServerContextImpl::shared_pointer& context) :
|
||||
AbstractServerResponseHandler(context, "Echo request") {
|
||||
}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport* transport, int8 version, int8 command,
|
||||
Transport::shared_pointer& transport, int8 version, int8 command,
|
||||
int payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
};
|
||||
|
||||
class EchoTransportSender : public ReferencedTransportSender {
|
||||
class EchoTransportSender : public TransportSender {
|
||||
public:
|
||||
EchoTransportSender(osiSockAddr* echoFrom) {
|
||||
memcpy(&_echoFrom, echoFrom, sizeof(osiSockAddr));
|
||||
}
|
||||
|
||||
virtual ~EchoTransportSender() {
|
||||
}
|
||||
|
||||
virtual void send(ByteBuffer* buffer, TransportSendControl* control) {
|
||||
control->startMessage(CMD_ECHO, 0);
|
||||
control->setRecipient(_echoFrom);
|
||||
@@ -160,9 +126,6 @@ namespace epics {
|
||||
|
||||
private:
|
||||
osiSockAddr _echoFrom;
|
||||
|
||||
virtual ~EchoTransportSender() {
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -171,15 +134,12 @@ namespace epics {
|
||||
class ServerIntrospectionSearchHandler : public AbstractServerResponseHandler
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @param context
|
||||
*/
|
||||
ServerIntrospectionSearchHandler(ServerContextImpl* context) :
|
||||
ServerIntrospectionSearchHandler(ServerContextImpl::shared_pointer& context) :
|
||||
AbstractServerResponseHandler(context, "Search request") {
|
||||
}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport* transport, int8 version, int8 command,
|
||||
Transport::shared_pointer& transport, int8 version, int8 command,
|
||||
int payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
};
|
||||
|
||||
@@ -187,33 +147,32 @@ namespace epics {
|
||||
/**
|
||||
* Search channel request handler.
|
||||
*/
|
||||
class ServerChannelFindRequesterImplObjectPool;
|
||||
// TODO object pool!!!
|
||||
class ServerSearchHandler : public AbstractServerResponseHandler
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @param context
|
||||
*/
|
||||
ServerSearchHandler(ServerContextImpl* context);
|
||||
~ServerSearchHandler();
|
||||
ServerSearchHandler(ServerContextImpl::shared_pointer& context);
|
||||
virtual ~ServerSearchHandler();
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport* transport, int8 version, int8 command,
|
||||
Transport::shared_pointer& transport, int8 version, int8 command,
|
||||
int payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
|
||||
private:
|
||||
ChannelProvider* _provider;
|
||||
ServerChannelFindRequesterImplObjectPool* _objectPool;
|
||||
ChannelProvider::shared_pointer _provider;
|
||||
};
|
||||
|
||||
|
||||
class ServerChannelFindRequesterImpl: public ChannelFindRequester, public ReferencedTransportSender
|
||||
class ServerChannelFindRequesterImpl:
|
||||
public ChannelFindRequester,
|
||||
public TransportSender,
|
||||
public std::tr1::enable_shared_from_this<ServerChannelFindRequesterImpl>
|
||||
{
|
||||
public:
|
||||
ServerChannelFindRequesterImpl(ServerContextImpl* context, ServerChannelFindRequesterImplObjectPool* objectPool);
|
||||
ServerChannelFindRequesterImpl(ServerContextImpl::shared_pointer& context);
|
||||
void clear();
|
||||
ServerChannelFindRequesterImpl* set(int32 searchSequenceId, int32 cid, osiSockAddr* sendTo, boolean responseRequired);
|
||||
void channelFindResult(const epics::pvData::Status& status, ChannelFind* channelFind, boolean wasFound);
|
||||
void channelFindResult(const epics::pvData::Status& status, ChannelFind::shared_pointer& channelFind, boolean wasFound);
|
||||
void lock();
|
||||
void unlock();
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control);
|
||||
@@ -223,24 +182,10 @@ namespace epics {
|
||||
osiSockAddr* _sendTo;
|
||||
boolean _responseRequired;
|
||||
boolean _wasFound;
|
||||
ServerContextImpl* _context;
|
||||
epics::pvData::Mutex _mutex;
|
||||
ServerChannelFindRequesterImplObjectPool* _objectPool;
|
||||
};
|
||||
|
||||
class ServerChannelFindRequesterImplObjectPool
|
||||
{
|
||||
public:
|
||||
ServerChannelFindRequesterImplObjectPool(ServerContextImpl* context);
|
||||
~ServerChannelFindRequesterImplObjectPool();
|
||||
ServerChannelFindRequesterImpl* get();
|
||||
void put(ServerChannelFindRequesterImpl* element);
|
||||
|
||||
private:
|
||||
std::vector<ServerChannelFindRequesterImpl*> _elements;
|
||||
ServerContextImpl* _context;
|
||||
ServerContextImpl::shared_pointer _context;
|
||||
epics::pvData::Mutex _mutex;
|
||||
};
|
||||
|
||||
/****************************************************************************************/
|
||||
/**
|
||||
* Create channel request handler.
|
||||
@@ -248,43 +193,45 @@ namespace epics {
|
||||
class ServerCreateChannelHandler : public AbstractServerResponseHandler
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @param context
|
||||
*/
|
||||
ServerCreateChannelHandler(ServerContextImpl* context) :
|
||||
ServerCreateChannelHandler(ServerContextImpl::shared_pointer& context) :
|
||||
AbstractServerResponseHandler(context, "Create channel request") {
|
||||
_provider = context->getChannelProvider();
|
||||
}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport* transport, int8 version, int8 command,
|
||||
Transport::shared_pointer& transport, int8 version, int8 command,
|
||||
int payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
|
||||
private:
|
||||
/**
|
||||
* Disconnect.
|
||||
*/
|
||||
void disconnect(Transport* transport);
|
||||
ChannelProvider* _provider;
|
||||
void disconnect(Transport::shared_pointer& transport);
|
||||
ChannelProvider::shared_pointer _provider;
|
||||
};
|
||||
|
||||
class ServerChannelRequesterImpl : public ChannelRequester, public ReferencedTransportSender
|
||||
class ServerChannelRequesterImpl :
|
||||
public ChannelRequester,
|
||||
public TransportSender,
|
||||
public std::tr1::enable_shared_from_this<ServerChannelRequesterImpl>
|
||||
{
|
||||
public:
|
||||
ServerChannelRequesterImpl(Transport* transport, const String channelName, const pvAccessID cid);
|
||||
void channelCreated(const epics::pvData::Status& status, Channel* channel);
|
||||
void channelStateChange(Channel* c, const Channel::ConnectionState isConnected);
|
||||
typedef std::tr1::shared_ptr<ServerChannelRequesterImpl> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ServerChannelRequesterImpl> const_shared_pointer;
|
||||
protected:
|
||||
ServerChannelRequesterImpl(Transport::shared_pointer& transport, const String channelName, const pvAccessID cid);
|
||||
public:
|
||||
static ChannelRequester::shared_pointer create(ChannelProvider::shared_pointer& provider, Transport::shared_pointer& transport, const String channelName, const pvAccessID cid);
|
||||
void channelCreated(const epics::pvData::Status& status, Channel::shared_pointer& channel);
|
||||
void channelStateChange(Channel::shared_pointer& c, const Channel::ConnectionState isConnected);
|
||||
String getRequesterName();
|
||||
void message(const String message, const epics::pvData::MessageType messageType);
|
||||
void lock();
|
||||
void unlock();
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control);
|
||||
private:
|
||||
Transport* _transport;
|
||||
Transport::shared_pointer _transport;
|
||||
const String _channelName;
|
||||
const pvAccessID _cid;
|
||||
epics::pvData::Status _status;
|
||||
Channel* _channel;
|
||||
Channel::shared_pointer _channel;
|
||||
epics::pvData::Mutex _mutex;
|
||||
void createChannelFailedResponse(epics::pvData::ByteBuffer* buffer, TransportSendControl* control, const epics::pvData::Status& status);
|
||||
};
|
||||
@@ -296,28 +243,24 @@ namespace epics {
|
||||
class ServerDestroyChannelHandler : public AbstractServerResponseHandler
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @param context
|
||||
*/
|
||||
ServerDestroyChannelHandler(ServerContextImpl* context) :
|
||||
ServerDestroyChannelHandler(ServerContextImpl::shared_pointer& context) :
|
||||
AbstractServerResponseHandler(context, "Destroy channel request") {
|
||||
}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport* transport, int8 version, int8 command,
|
||||
Transport::shared_pointer& transport, int8 version, int8 command,
|
||||
int payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
};
|
||||
|
||||
|
||||
class ServerDestroyChannelHandlerTransportSender : public ReferencedTransportSender
|
||||
class ServerDestroyChannelHandlerTransportSender : public TransportSender
|
||||
{
|
||||
public:
|
||||
ServerDestroyChannelHandlerTransportSender(pvAccessID cid, pvAccessID sid): _cid(cid), _sid(sid) {
|
||||
|
||||
}
|
||||
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control) {
|
||||
control->startMessage((int8)8, 2*sizeof(int32)/sizeof(int8));
|
||||
control->startMessage((int8)CMD_DESTROY_CHANNEL, 2*sizeof(int32)/sizeof(int8));
|
||||
buffer->putInt(_sid);
|
||||
buffer->putInt(_cid);
|
||||
}
|
||||
@@ -342,38 +285,48 @@ namespace epics {
|
||||
class ServerGetHandler : public AbstractServerResponseHandler
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @param context
|
||||
*/
|
||||
ServerGetHandler(ServerContextImpl* context) :
|
||||
ServerGetHandler(ServerContextImpl::shared_pointer& context) :
|
||||
AbstractServerResponseHandler(context, "Get request") {
|
||||
}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport* transport, int8 version, int8 command,
|
||||
Transport::shared_pointer& transport, int8 version, int8 command,
|
||||
int payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
};
|
||||
|
||||
class ServerChannelGetRequesterImpl : public BaseChannelRequester, public ChannelGetRequester, public ReferencedTransportSender
|
||||
class ServerChannelGetRequesterImpl :
|
||||
public BaseChannelRequester,
|
||||
public ChannelGetRequester,
|
||||
public TransportSender,
|
||||
public std::tr1::enable_shared_from_this<ServerChannelGetRequesterImpl>
|
||||
{
|
||||
public:
|
||||
ServerChannelGetRequesterImpl(ServerContextImpl* context, ServerChannelImpl* channel, const pvAccessID ioid, Transport* transport,
|
||||
epics::pvData::PVStructurePtr pvRequest);
|
||||
void channelGetConnect(const epics::pvData::Status& status, ChannelGet* channelGet, epics::pvData::PVStructurePtr pvStructure,
|
||||
epics::pvData::BitSet* bitSet);
|
||||
typedef std::tr1::shared_ptr<ServerChannelGetRequesterImpl> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ServerChannelGetRequesterImpl> const_shared_pointer;
|
||||
protected:
|
||||
ServerChannelGetRequesterImpl(ServerContextImpl::shared_pointer& context,
|
||||
ServerChannelImpl::shared_pointer& channel, const pvAccessID ioid,
|
||||
Transport::shared_pointer& transport);
|
||||
void activate(epics::pvData::PVStructure::shared_pointer& pvRequest);
|
||||
public:
|
||||
static ChannelGetRequester::shared_pointer create(ServerContextImpl::shared_pointer& context,
|
||||
ServerChannelImpl::shared_pointer& channel, const pvAccessID ioid,
|
||||
Transport::shared_pointer& transport,
|
||||
epics::pvData::PVStructure::shared_pointer& pvRequest);
|
||||
void channelGetConnect(const epics::pvData::Status& status, ChannelGet::shared_pointer& channelGet,
|
||||
epics::pvData::PVStructure::shared_pointer& pvStructure, epics::pvData::BitSet::shared_pointer& bitSet);
|
||||
void getDone(const epics::pvData::Status& status);
|
||||
void destroy();
|
||||
/**
|
||||
* @return the channelGet
|
||||
*/
|
||||
ChannelGet* getChannelGet();
|
||||
|
||||
ChannelGet::shared_pointer getChannelGet();
|
||||
|
||||
void lock();
|
||||
void unlock();
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control);
|
||||
private:
|
||||
ChannelGet* _channelGet;
|
||||
epics::pvData::BitSet* _bitSet;
|
||||
epics::pvData::PVStructurePtr _pvStructure;
|
||||
ChannelGet::shared_pointer _channelGet;
|
||||
epics::pvData::BitSet::shared_pointer _bitSet;
|
||||
epics::pvData::PVStructure::shared_pointer _pvStructure;
|
||||
epics::pvData::Status _status;
|
||||
};
|
||||
|
||||
@@ -385,45 +338,49 @@ namespace epics {
|
||||
class ServerPutHandler : public AbstractServerResponseHandler
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @param context
|
||||
*/
|
||||
ServerPutHandler(ServerContextImpl* context) :
|
||||
ServerPutHandler(ServerContextImpl::shared_pointer context) :
|
||||
AbstractServerResponseHandler(context, "Put request") {
|
||||
}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport* transport, int8 version, int8 command,
|
||||
Transport::shared_pointer& transport, int8 version, int8 command,
|
||||
int payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
};
|
||||
|
||||
class ServerChannelPutRequesterImpl : public BaseChannelRequester, public ChannelPutRequester, public ReferencedTransportSender
|
||||
class ServerChannelPutRequesterImpl :
|
||||
public BaseChannelRequester,
|
||||
public ChannelPutRequester,
|
||||
public TransportSender,
|
||||
public std::tr1::enable_shared_from_this<ServerChannelPutRequesterImpl>
|
||||
{
|
||||
public:
|
||||
ServerChannelPutRequesterImpl(ServerContextImpl* context, ServerChannelImpl* channel, const pvAccessID ioid, Transport* transport,epics::pvData::PVStructure* pvRequest);
|
||||
void channelPutConnect(const epics::pvData::Status& status, ChannelPut* channelPut, epics::pvData::PVStructure* pvStructure, epics::pvData::BitSet* bitSet);
|
||||
typedef std::tr1::shared_ptr<ServerChannelPutRequesterImpl> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ServerChannelPutRequesterImpl> const_shared_pointer;
|
||||
protected:
|
||||
ServerChannelPutRequesterImpl(ServerContextImpl::shared_pointer& context,
|
||||
ServerChannelImpl::shared_pointer& channel, const pvAccessID ioid,
|
||||
Transport::shared_pointer& transport);
|
||||
void activate(epics::pvData::PVStructure::shared_pointer& pvRequest);
|
||||
public:
|
||||
static ChannelPutRequester::shared_pointer create(ServerContextImpl::shared_pointer& context,
|
||||
ServerChannelImpl::shared_pointer& channel, const pvAccessID ioid,
|
||||
Transport::shared_pointer& transport,epics::pvData::PVStructure::shared_pointer& pvRequest);
|
||||
|
||||
void channelPutConnect(const epics::pvData::Status& status, ChannelPut::shared_pointer& channelPut, epics::pvData::PVStructure::shared_pointer& pvStructure, epics::pvData::BitSet::shared_pointer& bitSet);
|
||||
void putDone(const epics::pvData::Status& status);
|
||||
void getDone(const epics::pvData::Status& status);
|
||||
void lock();
|
||||
void unlock();
|
||||
void destroy();
|
||||
/**
|
||||
* @return the channelPut
|
||||
*/
|
||||
ChannelPut* getChannelPut();
|
||||
/**
|
||||
* @return the bitSet
|
||||
*/
|
||||
BitSet* getBitSet();
|
||||
/**
|
||||
* @return the pvStructure
|
||||
*/
|
||||
PVStructure* getPVStructure();
|
||||
|
||||
ChannelPut::shared_pointer getChannelPut();
|
||||
BitSet::shared_pointer getBitSet();
|
||||
PVStructure::shared_pointer getPVStructure();
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control);
|
||||
private:
|
||||
ChannelPut* _channelPut;
|
||||
epics::pvData::BitSet* _bitSet;
|
||||
epics::pvData::PVStructure* _pvStructure;
|
||||
ChannelPut::shared_pointer _channelPut;
|
||||
epics::pvData::BitSet::shared_pointer _bitSet;
|
||||
epics::pvData::PVStructure::shared_pointer _pvStructure;
|
||||
epics::pvData::Status _status;
|
||||
};
|
||||
|
||||
@@ -434,42 +391,49 @@ namespace epics {
|
||||
class ServerPutGetHandler : public AbstractServerResponseHandler
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @param context
|
||||
*/
|
||||
ServerPutGetHandler(ServerContextImpl* context) :
|
||||
ServerPutGetHandler(ServerContextImpl::shared_pointer& context) :
|
||||
AbstractServerResponseHandler(context, "Put-get request") {
|
||||
}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport* transport, int8 version, int8 command,
|
||||
Transport::shared_pointer& transport, int8 version, int8 command,
|
||||
int payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
};
|
||||
|
||||
class ServerChannelPutGetRequesterImpl : public BaseChannelRequester, public ChannelPutGetRequester, public ReferencedTransportSender
|
||||
class ServerChannelPutGetRequesterImpl :
|
||||
public BaseChannelRequester,
|
||||
public ChannelPutGetRequester,
|
||||
public TransportSender,
|
||||
public std::tr1::enable_shared_from_this<ServerChannelPutGetRequesterImpl>
|
||||
{
|
||||
public:
|
||||
ServerChannelPutGetRequesterImpl(ServerContextImpl* context, ServerChannelImpl* channel, const pvAccessID ioid, Transport* transport,epics::pvData::PVStructure* pvRequest);
|
||||
void channelPutGetConnect(const epics::pvData::Status& status, ChannelPutGet* channelPutGet, epics::pvData::PVStructure* pvPutStructure, epics::pvData::PVStructure* pvGetStructure);
|
||||
typedef std::tr1::shared_ptr<ServerChannelPutGetRequesterImpl> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ServerChannelPutGetRequesterImpl> const_shared_pointer;
|
||||
protected:
|
||||
ServerChannelPutGetRequesterImpl(ServerContextImpl::shared_pointer& context,
|
||||
ServerChannelImpl::shared_pointer& channel, const pvAccessID ioid,
|
||||
Transport::shared_pointer& transport);
|
||||
void activate(epics::pvData::PVStructure::shared_pointer& pvRequest);
|
||||
public:
|
||||
static ChannelPutGetRequester::shared_pointer create(ServerContextImpl::shared_pointer& context,
|
||||
ServerChannelImpl::shared_pointer& channel, const pvAccessID ioid,
|
||||
Transport::shared_pointer& transport,epics::pvData::PVStructure::shared_pointer& pvRequest);
|
||||
|
||||
void channelPutGetConnect(const epics::pvData::Status& status, ChannelPutGet::shared_pointer& channelPutGet, epics::pvData::PVStructure::shared_pointer& pvPutStructure, epics::pvData::PVStructure::shared_pointer& pvGetStructure);
|
||||
void getGetDone(const epics::pvData::Status& status);
|
||||
void getPutDone(const epics::pvData::Status& status);
|
||||
void putGetDone(const epics::pvData::Status& status);
|
||||
void lock();
|
||||
void unlock();
|
||||
void destroy();
|
||||
/**
|
||||
* @return the channelPutGet
|
||||
*/
|
||||
ChannelPutGet* getChannelPutGet();
|
||||
/**
|
||||
* @return the pvPutStructure
|
||||
*/
|
||||
PVStructure* getPVPutStructure();
|
||||
|
||||
ChannelPutGet::shared_pointer getChannelPutGet();
|
||||
PVStructure::shared_pointer getPVPutStructure();
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control);
|
||||
private:
|
||||
ChannelPutGet* _channelPutGet;
|
||||
epics::pvData::PVStructure* _pvPutStructure;
|
||||
epics::pvData::PVStructure* _pvGetStructure;
|
||||
ChannelPutGet::shared_pointer _channelPutGet;
|
||||
epics::pvData::PVStructure::shared_pointer _pvPutStructure;
|
||||
epics::pvData::PVStructure::shared_pointer _pvGetStructure;
|
||||
epics::pvData::Status _status;
|
||||
};
|
||||
|
||||
@@ -481,38 +445,48 @@ namespace epics {
|
||||
class ServerMonitorHandler : public AbstractServerResponseHandler
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @param context
|
||||
*/
|
||||
ServerMonitorHandler(ServerContextImpl* context) :
|
||||
ServerMonitorHandler(ServerContextImpl::shared_pointer& context) :
|
||||
AbstractServerResponseHandler(context, "Monitor request") {
|
||||
}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport* transport, int8 version, int8 command,
|
||||
Transport::shared_pointer& transport, int8 version, int8 command,
|
||||
int payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
};
|
||||
|
||||
|
||||
class ServerMonitorRequesterImpl : public BaseChannelRequester, public MonitorRequester, public ReferencedTransportSender
|
||||
class ServerMonitorRequesterImpl :
|
||||
public BaseChannelRequester,
|
||||
public MonitorRequester,
|
||||
public TransportSender,
|
||||
public std::tr1::enable_shared_from_this<ServerMonitorRequesterImpl>
|
||||
{
|
||||
public:
|
||||
ServerMonitorRequesterImpl(ServerContextImpl* context, ServerChannelImpl* channel, const pvAccessID ioid, Transport* transport,epics::pvData::PVStructure* pvRequest);
|
||||
void monitorConnect(const epics::pvData::Status& status, epics::pvData::Monitor* monitor, epics::pvData::StructureConstPtr structure);
|
||||
void unlisten(epics::pvData::Monitor* monitor);
|
||||
void monitorEvent(epics::pvData::Monitor* monitor);
|
||||
typedef std::tr1::shared_ptr<ServerMonitorRequesterImpl> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ServerMonitorRequesterImpl> const_shared_pointer;
|
||||
protected:
|
||||
ServerMonitorRequesterImpl(ServerContextImpl::shared_pointer& context,
|
||||
ServerChannelImpl::shared_pointer& channel, const pvAccessID ioid,
|
||||
Transport::shared_pointer& transport);
|
||||
void activate(epics::pvData::PVStructure::shared_pointer& pvRequest);
|
||||
public:
|
||||
static MonitorRequester::shared_pointer create(ServerContextImpl::shared_pointer& context,
|
||||
ServerChannelImpl::shared_pointer& channel, const pvAccessID ioid,
|
||||
Transport::shared_pointer& transport,epics::pvData::PVStructure::shared_pointer& pvRequest);
|
||||
|
||||
void monitorConnect(const epics::pvData::Status& status, epics::pvData::Monitor::shared_pointer& monitor, epics::pvData::StructureConstPtr& structure);
|
||||
void unlisten(epics::pvData::Monitor::shared_pointer& monitor);
|
||||
void monitorEvent(epics::pvData::Monitor::shared_pointer& monitor);
|
||||
void lock();
|
||||
void unlock();
|
||||
void destroy();
|
||||
/**
|
||||
* @return the channelMonitor
|
||||
*/
|
||||
epics::pvData::Monitor* getChannelMonitor();
|
||||
|
||||
epics::pvData::Monitor::shared_pointer getChannelMonitor();
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control);
|
||||
private:
|
||||
epics::pvData::Monitor* _monitor;
|
||||
epics::pvData::Monitor* _channelMonitor;
|
||||
epics::pvData::StructureConstPtr _structure;
|
||||
epics::pvData::Monitor::shared_pointer _monitor;
|
||||
epics::pvData::Monitor::shared_pointer _channelMonitor;
|
||||
epics::pvData::StructureConstPtr _structure;
|
||||
epics::pvData::Status _status;
|
||||
};
|
||||
|
||||
@@ -524,41 +498,50 @@ namespace epics {
|
||||
class ServerArrayHandler : public AbstractServerResponseHandler
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @param context
|
||||
*/
|
||||
ServerArrayHandler(ServerContextImpl* context) :
|
||||
ServerArrayHandler(ServerContextImpl::shared_pointer& context) :
|
||||
AbstractServerResponseHandler(context, "Array request") {
|
||||
}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport* transport, int8 version, int8 command,
|
||||
Transport::shared_pointer& transport, int8 version, int8 command,
|
||||
int payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
};
|
||||
|
||||
class ServerChannelArrayRequesterImpl : public BaseChannelRequester, public ChannelArrayRequester, public ReferencedTransportSender
|
||||
class ServerChannelArrayRequesterImpl :
|
||||
public BaseChannelRequester,
|
||||
public ChannelArrayRequester,
|
||||
public TransportSender,
|
||||
public std::tr1::enable_shared_from_this<ServerChannelArrayRequesterImpl>
|
||||
{
|
||||
public:
|
||||
ServerChannelArrayRequesterImpl(ServerContextImpl* context, ServerChannelImpl* channel, const pvAccessID ioid, Transport* transport,epics::pvData::PVStructure* pvRequest);
|
||||
void channelArrayConnect(const epics::pvData::Status& status, ChannelArray* channelArray, epics::pvData::PVArray* pvArray);
|
||||
typedef std::tr1::shared_ptr<ServerChannelArrayRequesterImpl> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ServerChannelArrayRequesterImpl> const_shared_pointer;
|
||||
protected:
|
||||
ServerChannelArrayRequesterImpl(ServerContextImpl::shared_pointer& context,
|
||||
ServerChannelImpl::shared_pointer& channel, const pvAccessID ioid,
|
||||
Transport::shared_pointer& transport);
|
||||
void activate(epics::pvData::PVStructure::shared_pointer& pvRequest);
|
||||
public:
|
||||
static ChannelArrayRequester::shared_pointer create(ServerContextImpl::shared_pointer& context,
|
||||
ServerChannelImpl::shared_pointer& channel, const pvAccessID ioid,
|
||||
Transport::shared_pointer& transport,epics::pvData::PVStructure::shared_pointer& pvRequest);
|
||||
|
||||
void channelArrayConnect(const epics::pvData::Status& status, ChannelArray::shared_pointer& channelArray, epics::pvData::PVArray::shared_pointer& pvArray);
|
||||
void getArrayDone(const epics::pvData::Status& status);
|
||||
void putArrayDone(const epics::pvData::Status& status);
|
||||
void setLengthDone(const epics::pvData::Status& status);
|
||||
void lock();
|
||||
void unlock();
|
||||
void destroy();
|
||||
/**
|
||||
* @return the channelArray
|
||||
*/
|
||||
ChannelArray* getChannelArray();
|
||||
/**
|
||||
* @return the pvArray
|
||||
*/
|
||||
epics::pvData::PVArray* getPVArray();
|
||||
|
||||
ChannelArray::shared_pointer getChannelArray();
|
||||
|
||||
epics::pvData::PVArray::shared_pointer getPVArray();
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control);
|
||||
|
||||
private:
|
||||
ChannelArray* _channelArray;
|
||||
epics::pvData::PVArray* _pvArray;
|
||||
ChannelArray::shared_pointer _channelArray;
|
||||
epics::pvData::PVArray::shared_pointer _pvArray;
|
||||
epics::pvData::Status _status;
|
||||
};
|
||||
|
||||
@@ -569,23 +552,16 @@ namespace epics {
|
||||
class ServerCancelRequestHandler : public AbstractServerResponseHandler
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @param context
|
||||
*/
|
||||
ServerCancelRequestHandler(ServerContextImpl* context) :
|
||||
ServerCancelRequestHandler(ServerContextImpl::shared_pointer& context) :
|
||||
AbstractServerResponseHandler(context, "Cancel request") {
|
||||
}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport* transport, int8 version, int8 command,
|
||||
Transport::shared_pointer& transport, int8 version, int8 command,
|
||||
int payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
private:
|
||||
/**
|
||||
* @param transport
|
||||
* @param ioid
|
||||
* @param errorStatus
|
||||
*/
|
||||
void failureResponse(Transport* transport, pvAccessID ioid, const epics::pvData::Status& errorStatus);
|
||||
|
||||
void failureResponse(Transport::shared_pointer& transport, pvAccessID ioid, const epics::pvData::Status& errorStatus);
|
||||
};
|
||||
|
||||
|
||||
@@ -596,34 +572,45 @@ namespace epics {
|
||||
class ServerProcessHandler : public AbstractServerResponseHandler
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @param context
|
||||
*/
|
||||
ServerProcessHandler(ServerContextImpl* context) :
|
||||
ServerProcessHandler(ServerContextImpl::shared_pointer& context) :
|
||||
AbstractServerResponseHandler(context, "Process request") {
|
||||
}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport* transport, int8 version, int8 command,
|
||||
Transport::shared_pointer& transport, int8 version, int8 command,
|
||||
int payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
};
|
||||
|
||||
class ServerChannelProcessRequesterImpl : public BaseChannelRequester, public ChannelProcessRequester, public ReferencedTransportSender
|
||||
class ServerChannelProcessRequesterImpl :
|
||||
public BaseChannelRequester,
|
||||
public ChannelProcessRequester,
|
||||
public TransportSender,
|
||||
public std::tr1::enable_shared_from_this<ServerChannelProcessRequesterImpl>
|
||||
{
|
||||
public:
|
||||
ServerChannelProcessRequesterImpl(ServerContextImpl* context, ServerChannelImpl* channel, const pvAccessID ioid, Transport* transport,epics::pvData::PVStructure* pvRequest);
|
||||
void channelProcessConnect(const epics::pvData::Status& status, ChannelProcess* channelProcess);
|
||||
typedef std::tr1::shared_ptr<ServerChannelProcessRequesterImpl> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ServerChannelProcessRequesterImpl> const_shared_pointer;
|
||||
protected:
|
||||
ServerChannelProcessRequesterImpl(ServerContextImpl::shared_pointer& context,
|
||||
ServerChannelImpl::shared_pointer& channel, const pvAccessID ioid,
|
||||
Transport::shared_pointer& transport);
|
||||
void activate(epics::pvData::PVStructure::shared_pointer& pvRequest);
|
||||
public:
|
||||
static ChannelProcessRequester::shared_pointer create(ServerContextImpl::shared_pointer& context,
|
||||
ServerChannelImpl::shared_pointer& channel, const pvAccessID ioid,
|
||||
Transport::shared_pointer& transport, epics::pvData::PVStructure::shared_pointer& pvRequest);
|
||||
|
||||
void channelProcessConnect(const epics::pvData::Status& status, ChannelProcess::shared_pointer& channelProcess);
|
||||
void processDone(const epics::pvData::Status& status);
|
||||
void lock();
|
||||
void unlock();
|
||||
void destroy();
|
||||
/**
|
||||
* @return the channelProcess
|
||||
*/
|
||||
ChannelProcess* getChannelProcess();
|
||||
|
||||
ChannelProcess::shared_pointer getChannelProcess();
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control);
|
||||
|
||||
private:
|
||||
ChannelProcess* _channelProcess;
|
||||
ChannelProcess::shared_pointer _channelProcess;
|
||||
epics::pvData::Status _status;
|
||||
};
|
||||
|
||||
@@ -634,25 +621,32 @@ namespace epics {
|
||||
class ServerGetFieldHandler : public AbstractServerResponseHandler
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @param context
|
||||
*/
|
||||
ServerGetFieldHandler(ServerContextImpl* context) :
|
||||
ServerGetFieldHandler(ServerContextImpl::shared_pointer& context) :
|
||||
AbstractServerResponseHandler(context, "Get field request") {
|
||||
}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport* transport, int8 version, int8 command,
|
||||
Transport::shared_pointer& transport, int8 version, int8 command,
|
||||
int payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
private:
|
||||
void getFieldFailureResponse(Transport* transport, const pvAccessID ioid, const epics::pvData::Status& errorStatus);
|
||||
void getFieldFailureResponse(Transport::shared_pointer& transport, const pvAccessID ioid, const epics::pvData::Status& errorStatus);
|
||||
};
|
||||
|
||||
class ServerGetFieldRequesterImpl : public BaseChannelRequester, public GetFieldRequester, public ReferencedTransportSender
|
||||
class ServerGetFieldRequesterImpl :
|
||||
public BaseChannelRequester,
|
||||
public GetFieldRequester,
|
||||
public TransportSender,
|
||||
public std::tr1::enable_shared_from_this<ServerGetFieldRequesterImpl>
|
||||
{
|
||||
public:
|
||||
ServerGetFieldRequesterImpl(ServerContextImpl* context, ServerChannelImpl* channel, const pvAccessID ioid, Transport* transport);
|
||||
void getDone(const epics::pvData::Status& status, epics::pvData::FieldConstPtr field);
|
||||
typedef std::tr1::shared_ptr<ServerGetFieldRequesterImpl> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ServerGetFieldRequesterImpl> const_shared_pointer;
|
||||
|
||||
ServerGetFieldRequesterImpl(ServerContextImpl::shared_pointer& context,
|
||||
ServerChannelImpl::shared_pointer& channel, const pvAccessID ioid,
|
||||
Transport::shared_pointer& transport);
|
||||
|
||||
void getDone(const epics::pvData::Status& status, epics::pvData::FieldConstPtr& field);
|
||||
void lock();
|
||||
void unlock();
|
||||
void destroy();
|
||||
@@ -662,16 +656,16 @@ namespace epics {
|
||||
epics::pvData::FieldConstPtr _field;
|
||||
};
|
||||
|
||||
class ServerGetFieldHandlerTransportSender : public ReferencedTransportSender
|
||||
class ServerGetFieldHandlerTransportSender : public TransportSender
|
||||
{
|
||||
public:
|
||||
ServerGetFieldHandlerTransportSender(const pvAccessID ioid,const epics::pvData::Status& status, Transport* transport):
|
||||
ServerGetFieldHandlerTransportSender(const pvAccessID ioid,const epics::pvData::Status& status, Transport::shared_pointer& transport):
|
||||
_ioid(ioid), _status(status), _transport(transport) {
|
||||
|
||||
}
|
||||
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control) {
|
||||
control->startMessage((int8)17, sizeof(int32)/sizeof(int8));
|
||||
control->startMessage((int8)CMD_GET_FIELD, sizeof(int32)/sizeof(int8));
|
||||
buffer->putInt(_ioid);
|
||||
_transport->getIntrospectionRegistry()->serializeStatus(buffer, control, _status);
|
||||
}
|
||||
@@ -686,8 +680,8 @@ namespace epics {
|
||||
|
||||
private:
|
||||
const pvAccessID _ioid;
|
||||
const epics::pvData::Status& _status;
|
||||
Transport* _transport;
|
||||
const epics::pvData::Status _status;
|
||||
Transport::shared_pointer& _transport;
|
||||
};
|
||||
|
||||
|
||||
@@ -699,45 +693,57 @@ namespace epics {
|
||||
class ServerRPCHandler : public AbstractServerResponseHandler
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @param context
|
||||
*/
|
||||
ServerRPCHandler(ServerContextImpl* context) :
|
||||
ServerRPCHandler(ServerContextImpl::shared_pointer& context) :
|
||||
AbstractServerResponseHandler(context, "RPC request") {
|
||||
}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport* transport, int8 version, int8 command,
|
||||
Transport::shared_pointer& transport, int8 version, int8 command,
|
||||
int payloadSize, epics::pvData::ByteBuffer* payloadBuffer);
|
||||
};
|
||||
|
||||
class ServerChannelRPCRequesterImpl : public BaseChannelRequester, public ChannelRPCRequester, public ReferencedTransportSender
|
||||
class ServerChannelRPCRequesterImpl :
|
||||
public BaseChannelRequester,
|
||||
public ChannelRPCRequester,
|
||||
public TransportSender,
|
||||
public std::tr1::enable_shared_from_this<ServerChannelRPCRequesterImpl>
|
||||
{
|
||||
public:
|
||||
ServerChannelRPCRequesterImpl(ServerContextImpl* context, ServerChannelImpl* channel, const pvAccessID ioid, Transport* transport,epics::pvData::PVStructure* pvRequest);
|
||||
void channelRPCConnect(const epics::pvData::Status& status, ChannelRPC* channelRPC, epics::pvData::PVStructure* arguments, epics::pvData::BitSet* bitSet);
|
||||
void requestDone(const epics::pvData::Status& status, epics::pvData::PVStructure* pvResponse);
|
||||
typedef std::tr1::shared_ptr<ServerChannelRPCRequesterImpl> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ServerChannelRPCRequesterImpl> const_shared_pointer;
|
||||
protected:
|
||||
ServerChannelRPCRequesterImpl(ServerContextImpl::shared_pointer& context,
|
||||
ServerChannelImpl::shared_pointer& channel, const pvAccessID ioid,
|
||||
Transport::shared_pointer& transport);
|
||||
void activate(epics::pvData::PVStructure::shared_pointer& pvRequest);
|
||||
public:
|
||||
static ChannelRPCRequester::shared_pointer create(ServerContextImpl::shared_pointer& context,
|
||||
ServerChannelImpl::shared_pointer& channel, const pvAccessID ioid,
|
||||
Transport::shared_pointer& transport,epics::pvData::PVStructure::shared_pointer& pvRequest);
|
||||
|
||||
void channelRPCConnect(const epics::pvData::Status& status, ChannelRPC::shared_pointer& channelRPC, epics::pvData::PVStructure::shared_pointer& arguments, epics::pvData::BitSet::shared_pointer& bitSet);
|
||||
void requestDone(const epics::pvData::Status& status, epics::pvData::PVStructure::shared_pointer& pvResponse);
|
||||
void lock();
|
||||
void unlock();
|
||||
void destroy();
|
||||
/**
|
||||
* @return the channelRPC
|
||||
*/
|
||||
ChannelRPC* getChannelRPC();
|
||||
ChannelRPC::shared_pointer getChannelRPC();
|
||||
/**
|
||||
* @return the pvArguments
|
||||
*/
|
||||
PVStructure* getPvArguments();
|
||||
PVStructure::shared_pointer getPvArguments();
|
||||
/**
|
||||
* @return the agrumentsBitSet
|
||||
*/
|
||||
BitSet* getAgrumentsBitSet();
|
||||
BitSet::shared_pointer getAgrumentsBitSet();
|
||||
void send(epics::pvData::ByteBuffer* buffer, TransportSendControl* control);
|
||||
private:
|
||||
ChannelRPC* _channelRPC;
|
||||
epics::pvData::PVStructure* _pvArguments;
|
||||
epics::pvData::PVStructure* _pvResponse;
|
||||
epics::pvData::BitSet* _argumentsBitSet;
|
||||
ChannelRPC::shared_pointer _channelRPC;
|
||||
epics::pvData::PVStructure::shared_pointer _pvArguments;
|
||||
epics::pvData::PVStructure::shared_pointer _pvResponse;
|
||||
epics::pvData::BitSet::shared_pointer _argumentsBitSet;
|
||||
epics::pvData::Status _status;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -4,36 +4,33 @@
|
||||
|
||||
#include "serverChannelImpl.h"
|
||||
|
||||
// TODO remove
|
||||
#include "responseHandlers.h"
|
||||
|
||||
using namespace epics::pvData;
|
||||
|
||||
namespace epics { namespace pvAccess {
|
||||
|
||||
ServerChannelImpl::ServerChannelImpl(Channel* channel, pvAccessID cid,
|
||||
pvAccessID sid, epics::pvData::PVField* securityToken):
|
||||
ServerChannelImpl::ServerChannelImpl(Channel::shared_pointer& channel, pvAccessID cid, pvAccessID sid, epics::pvData::PVField::shared_pointer& securityToken):
|
||||
_channel(channel),
|
||||
_cid(cid),
|
||||
_sid(cid),
|
||||
_destroyed(false)
|
||||
{
|
||||
if (channel == NULL)
|
||||
if (!channel.get())
|
||||
{
|
||||
THROW_BASE_EXCEPTION("non null local channel required");
|
||||
THROW_BASE_EXCEPTION("non-null channel required");
|
||||
}
|
||||
}
|
||||
|
||||
Channel* ServerChannelImpl::getChannel()
|
||||
Channel::shared_pointer ServerChannelImpl::getChannel()
|
||||
{
|
||||
return _channel;
|
||||
}
|
||||
|
||||
pvAccessID ServerChannelImpl::getCID()
|
||||
pvAccessID ServerChannelImpl::getCID() const
|
||||
{
|
||||
return _cid;
|
||||
}
|
||||
|
||||
pvAccessID ServerChannelImpl::getSID()
|
||||
pvAccessID ServerChannelImpl::getSID() const
|
||||
{
|
||||
return _sid;
|
||||
}
|
||||
@@ -44,13 +41,8 @@ int16 ServerChannelImpl::getAccessRights()
|
||||
return 0;
|
||||
}
|
||||
|
||||
void ServerChannelImpl::registerRequest(const pvAccessID id, Destroyable* request)
|
||||
void ServerChannelImpl::registerRequest(const pvAccessID id, Destroyable::shared_pointer& request)
|
||||
{
|
||||
if (request == NULL)
|
||||
{
|
||||
THROW_BASE_EXCEPTION("request == null");
|
||||
}
|
||||
|
||||
Lock guard(_mutex);
|
||||
_requests[id] = request;
|
||||
}
|
||||
@@ -65,19 +57,18 @@ void ServerChannelImpl::unregisterRequest(const pvAccessID id)
|
||||
}
|
||||
}
|
||||
|
||||
Destroyable* ServerChannelImpl::getRequest(const pvAccessID id)
|
||||
Destroyable::shared_pointer ServerChannelImpl::getRequest(const pvAccessID id)
|
||||
{
|
||||
_iter = _requests.find(id);
|
||||
if(_iter != _requests.end())
|
||||
{
|
||||
return _iter->second;
|
||||
}
|
||||
return NULL;
|
||||
return Destroyable::shared_pointer();
|
||||
}
|
||||
|
||||
void ServerChannelImpl::destroy()
|
||||
{
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
if (_destroyed) return;
|
||||
|
||||
@@ -86,13 +77,9 @@ void ServerChannelImpl::destroy()
|
||||
// destroy all requests
|
||||
destroyAllRequests();
|
||||
|
||||
// now thats ugly!!!
|
||||
(static_cast<ServerChannelRequesterImpl*>(_channel->getChannelRequester()))->release();
|
||||
// TODO make impl that does shares channels (and does ref counting)!!!
|
||||
// try catch?
|
||||
// ... and the channel
|
||||
// TODO try catch
|
||||
_channel->destroy();
|
||||
}
|
||||
delete this;
|
||||
}
|
||||
|
||||
void ServerChannelImpl::printInfo()
|
||||
|
||||
@@ -5,17 +5,19 @@
|
||||
#ifndef SERVERCHANNEL_H_
|
||||
#define SERVERCHANNEL_H_
|
||||
|
||||
#include "remote.h"
|
||||
#include "clientContextImpl.h"
|
||||
#include <remote.h>
|
||||
#include <clientContextImpl.h>
|
||||
|
||||
#include <destroyable.h>
|
||||
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
class ServerChannelImpl : public ServerChannel
|
||||
class ServerChannelImpl : public ServerChannel
|
||||
{
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<ServerChannelImpl> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ServerChannelImpl> const_shared_pointer;
|
||||
/**
|
||||
* Create server channel for given process variable.
|
||||
* @param channel local channel.
|
||||
@@ -23,29 +25,29 @@ public:
|
||||
* @param sid channel SID.
|
||||
* @param securityToken security token.
|
||||
*/
|
||||
ServerChannelImpl(Channel* channel, pvAccessID cid, pvAccessID sid, epics::pvData::PVField* securityToken);
|
||||
ServerChannelImpl(Channel::shared_pointer& channel, pvAccessID cid, pvAccessID sid, epics::pvData::PVField::shared_pointer& securityToken);
|
||||
/*
|
||||
* Destructor.
|
||||
*/
|
||||
~ServerChannelImpl() {};
|
||||
virtual ~ServerChannelImpl() {};
|
||||
|
||||
/**
|
||||
* Get local channel.
|
||||
* @return local channel.
|
||||
*/
|
||||
Channel* getChannel();
|
||||
Channel::shared_pointer getChannel();
|
||||
|
||||
/**
|
||||
* Get channel CID.
|
||||
* @return channel CID.
|
||||
*/
|
||||
pvAccessID getCID();
|
||||
pvAccessID getCID() const;
|
||||
|
||||
/**
|
||||
* Get channel SID.
|
||||
* @return channel SID.
|
||||
*/
|
||||
pvAccessID getSID();
|
||||
pvAccessID getSID() const;
|
||||
|
||||
/**
|
||||
* Get access rights (bit-mask encoded).
|
||||
@@ -59,7 +61,7 @@ public:
|
||||
* @param id request ID.
|
||||
* @param request request to be registered.
|
||||
*/
|
||||
void registerRequest(pvAccessID id, epics::pvData::Destroyable* request);
|
||||
void registerRequest(pvAccessID id, epics::pvData::Destroyable::shared_pointer& request);
|
||||
|
||||
/**
|
||||
* Unregister request.
|
||||
@@ -72,7 +74,7 @@ public:
|
||||
* @param id request ID.
|
||||
* @return request with given ID, <code>null</code> if there is no request with such ID.
|
||||
*/
|
||||
epics::pvData::Destroyable* getRequest(pvAccessID id);
|
||||
epics::pvData::Destroyable::shared_pointer getRequest(pvAccessID id);
|
||||
|
||||
/**
|
||||
* Destroy server channel.
|
||||
@@ -94,7 +96,7 @@ private:
|
||||
/**
|
||||
* Local channel.
|
||||
*/
|
||||
Channel* _channel;
|
||||
Channel::shared_pointer _channel;
|
||||
|
||||
/**
|
||||
* Channel CID.
|
||||
@@ -109,12 +111,13 @@ private:
|
||||
/**
|
||||
* Requests.
|
||||
*/
|
||||
std::map<pvAccessID, epics::pvData::Destroyable*> _requests;
|
||||
std::map<pvAccessID, epics::pvData::Destroyable::shared_pointer> _requests;
|
||||
|
||||
/**
|
||||
* Requests iterator.
|
||||
*/
|
||||
std::map<pvAccessID, epics::pvData::Destroyable*>::iterator _iter;
|
||||
// TODO remove
|
||||
std::map<pvAccessID, epics::pvData::Destroyable::shared_pointer>::iterator _iter;
|
||||
|
||||
/**
|
||||
* Destroy state.
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
#include "serverContext.h"
|
||||
#include "responseHandlers.h"
|
||||
|
||||
using std::tr1::dynamic_pointer_cast;
|
||||
using std::tr1::static_pointer_cast;
|
||||
|
||||
namespace epics { namespace pvAccess {
|
||||
|
||||
const char* ServerContextImpl::StateNames[] = { "NOT_INITIALIZED", "INITIALIZED", "RUNNING", "SHUTDOWN", "DESTROYED"};
|
||||
@@ -28,28 +31,29 @@ ServerContextImpl::ServerContextImpl():
|
||||
_broadcastPort(CA_BROADCAST_PORT),
|
||||
_serverPort(CA_SERVER_PORT),
|
||||
_receiveBufferSize(MAX_TCP_RECV),
|
||||
_timer(NULL),
|
||||
_broadcastTransport(NULL),
|
||||
_beaconEmitter(NULL),
|
||||
_acceptor(NULL),
|
||||
_transportRegistry(NULL),
|
||||
_channelAccess(NULL),
|
||||
_channelProviderName(CAJ_DEFAULT_PROVIDER),
|
||||
_channelProvider(NULL),
|
||||
_beaconServerStatusProvider(NULL)
|
||||
_timer(),
|
||||
_broadcastTransport(),
|
||||
_beaconEmitter(),
|
||||
_acceptor(),
|
||||
_transportRegistry(),
|
||||
_channelAccess(),
|
||||
_channelProviderName(PVACCESS_DEFAULT_PROVIDER),
|
||||
_channelProvider(),
|
||||
_beaconServerStatusProvider()
|
||||
|
||||
{
|
||||
initializeLogger();
|
||||
loadConfiguration();
|
||||
}
|
||||
|
||||
ServerContextImpl::shared_pointer ServerContextImpl::create()
|
||||
{
|
||||
ServerContextImpl::shared_pointer thisPointer(new ServerContextImpl());
|
||||
return thisPointer;
|
||||
}
|
||||
|
||||
ServerContextImpl::~ServerContextImpl()
|
||||
{
|
||||
if(_beaconEmitter) delete _beaconEmitter;
|
||||
if(_broadcastTransport) delete _broadcastTransport;
|
||||
if(_acceptor) delete _acceptor;
|
||||
if(_transportRegistry) delete _transportRegistry;
|
||||
if(_timer) delete _timer;
|
||||
}
|
||||
|
||||
const Version& ServerContextImpl::getVersion()
|
||||
@@ -62,15 +66,23 @@ void ServerContextImpl::initializeLogger()
|
||||
//createFileLogger("serverContextImpl.log");
|
||||
}
|
||||
|
||||
Configuration* ServerContextImpl::getConfiguration()
|
||||
struct noop_deleter
|
||||
{
|
||||
template<class T> void operator()(T * p)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
Configuration::shared_pointer ServerContextImpl::getConfiguration()
|
||||
{
|
||||
ConfigurationProvider* configurationProvider = ConfigurationFactory::getProvider();
|
||||
ConfigurationProvider* configurationProvider = ConfigurationFactory::getProvider();
|
||||
Configuration* config = configurationProvider->getConfiguration("pvAccess-server");
|
||||
if (config == NULL)
|
||||
{
|
||||
config = configurationProvider->getConfiguration("system");
|
||||
}
|
||||
return config;
|
||||
return Configuration::shared_pointer(config, noop_deleter());
|
||||
// TODO cache !!!
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,7 +90,7 @@ Configuration* ServerContextImpl::getConfiguration()
|
||||
*/
|
||||
void ServerContextImpl::loadConfiguration()
|
||||
{
|
||||
Configuration* config = getConfiguration();
|
||||
Configuration::shared_pointer config = getConfiguration();
|
||||
|
||||
_beaconAddressList = config->getPropertyAsString("EPICS4_CA_ADDR_LIST", _beaconAddressList);
|
||||
_beaconAddressList = config->getPropertyAsString("EPICS4_CAS_BEACON_ADDR_LIST", _beaconAddressList);
|
||||
@@ -102,7 +114,7 @@ void ServerContextImpl::loadConfiguration()
|
||||
_channelProviderName = config->getPropertyAsString("EPICS4_CAS_PROVIDER_NAME", _channelProviderName);
|
||||
}
|
||||
|
||||
void ServerContextImpl::initialize(ChannelAccess* channelAccess)
|
||||
void ServerContextImpl::initialize(ChannelAccess::shared_pointer& channelAccess)
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
if (channelAccess == NULL)
|
||||
@@ -133,19 +145,28 @@ void ServerContextImpl::initialize(ChannelAccess* channelAccess)
|
||||
_state = INITIALIZED;
|
||||
}
|
||||
|
||||
std::auto_ptr<ResponseHandler> ServerContextImpl::createResponseHandler()
|
||||
{
|
||||
ServerContextImpl::shared_pointer thisContext = shared_from_this();
|
||||
return std::auto_ptr<ResponseHandler>(new ServerResponseHandler(thisContext));
|
||||
}
|
||||
|
||||
void ServerContextImpl::internalInitialize()
|
||||
{
|
||||
//TODO should be allocated on stack
|
||||
_timer = new Timer("pvAccess-server timer",lowerPriority);
|
||||
_transportRegistry = new TransportRegistry();
|
||||
_timer.reset(new Timer("pvAccess-server timer",lowerPriority));
|
||||
_transportRegistry.reset(new TransportRegistry());
|
||||
|
||||
// setup broadcast UDP transport
|
||||
initializeBroadcastTransport();
|
||||
|
||||
_acceptor = new BlockingTCPAcceptor(this, _serverPort, _receiveBufferSize);
|
||||
Context::shared_pointer thisContext = shared_from_this();
|
||||
ResponseHandlerFactory::shared_pointer thisFactory = shared_from_this();
|
||||
_acceptor.reset(new BlockingTCPAcceptor(thisContext, thisFactory, _serverPort, _receiveBufferSize));
|
||||
_serverPort = ntohs(_acceptor->getBindAddress()->ia.sin_port);
|
||||
|
||||
_beaconEmitter = new BeaconEmitter(_broadcastTransport, this);
|
||||
ServerContextImpl::shared_pointer thisServerContext = shared_from_this();
|
||||
Transport::shared_pointer transport = _broadcastTransport;
|
||||
_beaconEmitter.reset(new BeaconEmitter(transport, thisServerContext));
|
||||
}
|
||||
|
||||
void ServerContextImpl::initializeBroadcastTransport()
|
||||
@@ -168,11 +189,14 @@ void ServerContextImpl::initializeBroadcastTransport()
|
||||
auto_ptr<InetAddrVector> broadcastAddresses(getBroadcastAddresses(socket,_broadcastPort));
|
||||
epicsSocketDestroy(socket);
|
||||
|
||||
TransportClient::shared_pointer nullTransportClient;
|
||||
|
||||
auto_ptr<BlockingUDPConnector> broadcastConnector(new BlockingUDPConnector(true, true));
|
||||
_broadcastTransport = static_cast<BlockingUDPTransport*>(broadcastConnector->connect(
|
||||
NULL, new ServerResponseHandler(this),
|
||||
listenLocalAddress, CA_MINOR_PROTOCOL_REVISION,
|
||||
CA_DEFAULT_PRIORITY));
|
||||
auto_ptr<epics::pvAccess::ResponseHandler> responseHandler = createResponseHandler();
|
||||
_broadcastTransport = static_pointer_cast<BlockingUDPTransport>(broadcastConnector->connect(
|
||||
nullTransportClient, responseHandler,
|
||||
listenLocalAddress, CA_MINOR_PROTOCOL_REVISION,
|
||||
CA_DEFAULT_PRIORITY));
|
||||
_broadcastTransport->setBroadcastAddresses(broadcastAddresses.get());
|
||||
|
||||
// set ignore address list
|
||||
@@ -299,18 +323,21 @@ void ServerContextImpl::internalDestroy()
|
||||
if (_broadcastTransport != NULL)
|
||||
{
|
||||
_broadcastTransport->close(true);
|
||||
_broadcastTransport.reset();
|
||||
}
|
||||
|
||||
// stop accepting connections
|
||||
if (_acceptor != NULL)
|
||||
{
|
||||
_acceptor->destroy();
|
||||
_acceptor.reset();
|
||||
}
|
||||
|
||||
// stop emitting beacons
|
||||
if (_beaconEmitter != NULL)
|
||||
{
|
||||
_beaconEmitter->destroy();
|
||||
_beaconEmitter.reset();
|
||||
}
|
||||
|
||||
// this will also destroy all channels
|
||||
@@ -326,20 +353,19 @@ void ServerContextImpl::destroyAllTransports()
|
||||
return;
|
||||
}
|
||||
|
||||
int32 size;
|
||||
Transport** transports = _transportRegistry->toArray(size);
|
||||
|
||||
std::auto_ptr<TransportRegistry::transportVector_t> transports = _transportRegistry->toArray();
|
||||
if (transports.get() == 0)
|
||||
return;
|
||||
|
||||
int size = (int)transports->size();
|
||||
if (size == 0)
|
||||
{
|
||||
delete[] transports;
|
||||
return;
|
||||
}
|
||||
|
||||
errlogSevPrintf(errlogInfo, "Server context still has %d transport(s) active and closing...", size);
|
||||
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
Transport* transport = transports[i];
|
||||
Transport::shared_pointer transport = (*transports)[i];
|
||||
try
|
||||
{
|
||||
transport->close(true);
|
||||
@@ -356,7 +382,9 @@ void ServerContextImpl::destroyAllTransports()
|
||||
}
|
||||
}
|
||||
|
||||
delete[] transports;
|
||||
// now clear all (release)
|
||||
_transportRegistry->clear();
|
||||
|
||||
}
|
||||
|
||||
void ServerContextImpl::printInfo()
|
||||
@@ -391,7 +419,7 @@ void ServerContextImpl::dispose()
|
||||
}
|
||||
}
|
||||
|
||||
void ServerContextImpl::setBeaconServerStatusProvider(BeaconServerStatusProvider* beaconServerStatusProvider)
|
||||
void ServerContextImpl::setBeaconServerStatusProvider(BeaconServerStatusProvider::shared_pointer& beaconServerStatusProvider)
|
||||
{
|
||||
_beaconServerStatusProvider = beaconServerStatusProvider;
|
||||
}
|
||||
@@ -448,7 +476,7 @@ std::string ServerContextImpl::getIgnoreAddressList()
|
||||
return _ignoreAddressList;
|
||||
}
|
||||
|
||||
BeaconServerStatusProvider* ServerContextImpl::getBeaconServerStatusProvider()
|
||||
BeaconServerStatusProvider::shared_pointer ServerContextImpl::getBeaconServerStatusProvider()
|
||||
{
|
||||
return _beaconServerStatusProvider;
|
||||
}
|
||||
@@ -457,17 +485,17 @@ osiSockAddr* ServerContextImpl::getServerInetAddress()
|
||||
{
|
||||
if(_acceptor != NULL)
|
||||
{
|
||||
return _acceptor->getBindAddress();
|
||||
return const_cast<osiSockAddr*>(_acceptor->getBindAddress());
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BlockingUDPTransport* ServerContextImpl::getBroadcastTransport()
|
||||
BlockingUDPTransport::shared_pointer ServerContextImpl::getBroadcastTransport()
|
||||
{
|
||||
return _broadcastTransport;
|
||||
}
|
||||
|
||||
ChannelAccess* ServerContextImpl::getChannelAccess()
|
||||
ChannelAccess::shared_pointer ServerContextImpl::getChannelAccess()
|
||||
{
|
||||
return _channelAccess;
|
||||
}
|
||||
@@ -484,41 +512,38 @@ void ServerContextImpl::setChannelProviderName(std::string channelProviderName)
|
||||
_channelProviderName = channelProviderName;
|
||||
}
|
||||
|
||||
ChannelProvider* ServerContextImpl::getChannelProvider()
|
||||
ChannelProvider::shared_pointer ServerContextImpl::getChannelProvider()
|
||||
{
|
||||
return _channelProvider;
|
||||
}
|
||||
|
||||
Timer* ServerContextImpl::getTimer()
|
||||
Timer::shared_pointer ServerContextImpl::getTimer()
|
||||
{
|
||||
return _timer;
|
||||
}
|
||||
|
||||
TransportRegistry* ServerContextImpl::getTransportRegistry()
|
||||
TransportRegistry::shared_pointer ServerContextImpl::getTransportRegistry()
|
||||
{
|
||||
return _transportRegistry;
|
||||
}
|
||||
|
||||
Channel* ServerContextImpl::getChannel(pvAccessID id)
|
||||
Channel::shared_pointer ServerContextImpl::getChannel(pvAccessID id)
|
||||
{
|
||||
//TODO
|
||||
return NULL;
|
||||
//TODO, not used
|
||||
return Channel::shared_pointer();
|
||||
}
|
||||
|
||||
Transport* ServerContextImpl::getSearchTransport()
|
||||
Transport::shared_pointer ServerContextImpl::getSearchTransport()
|
||||
{
|
||||
//TODO
|
||||
return NULL;
|
||||
//TODO, not used
|
||||
return Transport::shared_pointer();
|
||||
}
|
||||
|
||||
void ServerContextImpl::acquire()
|
||||
void ServerContextImpl::beaconAnomalyNotify()
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
void ServerContextImpl::release()
|
||||
{
|
||||
// TODO
|
||||
// noop
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,16 +5,15 @@
|
||||
#ifndef SERVERCONTEXT_H_
|
||||
#define SERVERCONTEXT_H_
|
||||
|
||||
#include "remote.h"
|
||||
#include "beaconServerStatusProvider.h"
|
||||
#include "caConstants.h"
|
||||
#include "version.h"
|
||||
#include "pvAccess.h"
|
||||
#include "logger.h"
|
||||
#include "blockingUDP.h"
|
||||
#include "blockingTCP.h"
|
||||
#include <remote.h>
|
||||
#include <beaconServerStatusProvider.h>
|
||||
#include <caConstants.h>
|
||||
#include <version.h>
|
||||
#include <pvAccess.h>
|
||||
#include <blockingUDP.h>
|
||||
#include <blockingTCP.h>
|
||||
#include "beaconEmitter.h"
|
||||
#include "logger.h"
|
||||
#include <logger.h>
|
||||
|
||||
#include <errlog.h>
|
||||
|
||||
@@ -24,10 +23,13 @@ namespace pvAccess {
|
||||
/**
|
||||
* The class representing a CA Server context.
|
||||
*/
|
||||
class ServerContext
|
||||
class ServerContext
|
||||
{
|
||||
public:
|
||||
/**
|
||||
typedef std::tr1::shared_ptr<ServerContext> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ServerContext> const_shared_pointer;
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
virtual ~ServerContext() {};
|
||||
@@ -41,7 +43,7 @@ public:
|
||||
* Set <code>ChannelAccess</code> implementation and initialize server.
|
||||
* @param channelAccess implementation of channel access to be served.
|
||||
*/
|
||||
virtual void initialize(ChannelAccess* channelAccess) = 0;
|
||||
virtual void initialize(ChannelAccess::shared_pointer& channelAccess) = 0;
|
||||
|
||||
/**
|
||||
* Run server (process events).
|
||||
@@ -89,38 +91,46 @@ public:
|
||||
* Set beacon server status provider.
|
||||
* @param beaconServerStatusProvider <code>BeaconServerStatusProvider</code> implementation to set.
|
||||
*/
|
||||
virtual void setBeaconServerStatusProvider(BeaconServerStatusProvider* beaconServerStatusProvider) = 0;
|
||||
virtual void setBeaconServerStatusProvider(BeaconServerStatusProvider::shared_pointer& beaconServerStatusProvider) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
class BeaconEmitter;
|
||||
|
||||
class ServerContextImpl : public ServerContext, public Context
|
||||
class ServerContextImpl :
|
||||
public ServerContext,
|
||||
public Context,
|
||||
public ResponseHandlerFactory,
|
||||
public std::tr1::enable_shared_from_this<ServerContextImpl>
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* Constructor.
|
||||
*/
|
||||
typedef std::tr1::shared_ptr<ServerContextImpl> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const ServerContextImpl> const_shared_pointer;
|
||||
protected:
|
||||
ServerContextImpl();
|
||||
public:
|
||||
static ServerContextImpl::shared_pointer create();
|
||||
|
||||
virtual ~ServerContextImpl();
|
||||
|
||||
//**************** derived from ServerContext ****************//
|
||||
const Version& getVersion();
|
||||
void initialize(ChannelAccess* channelAccess);
|
||||
void initialize(ChannelAccess::shared_pointer& channelAccess);
|
||||
void run(int32 seconds);
|
||||
void shutdown();
|
||||
void destroy();
|
||||
void printInfo();
|
||||
void printInfo(ostream& str);
|
||||
void dispose();
|
||||
void setBeaconServerStatusProvider(BeaconServerStatusProvider* beaconServerStatusProvider);
|
||||
void setBeaconServerStatusProvider(BeaconServerStatusProvider::shared_pointer& beaconServerStatusProvider);
|
||||
//**************** derived from Context ****************//
|
||||
Timer* getTimer();
|
||||
Channel* getChannel(pvAccessID id);
|
||||
Transport* getSearchTransport();
|
||||
Configuration* getConfiguration();
|
||||
TransportRegistry* getTransportRegistry();
|
||||
Timer::shared_pointer getTimer();
|
||||
Channel::shared_pointer getChannel(pvAccessID id);
|
||||
Transport::shared_pointer getSearchTransport();
|
||||
Configuration::shared_pointer getConfiguration();
|
||||
TransportRegistry::shared_pointer getTransportRegistry();
|
||||
|
||||
std::auto_ptr<ResponseHandler> createResponseHandler();
|
||||
void beaconAnomalyNotify();
|
||||
|
||||
/**
|
||||
* Version.
|
||||
@@ -226,7 +236,7 @@ public:
|
||||
* Get registered beacon server status provider.
|
||||
* @return registered beacon server status provider.
|
||||
*/
|
||||
BeaconServerStatusProvider* getBeaconServerStatusProvider();
|
||||
BeaconServerStatusProvider::shared_pointer getBeaconServerStatusProvider();
|
||||
|
||||
/**
|
||||
* Get server newtwork (IP) address.
|
||||
@@ -238,13 +248,13 @@ public:
|
||||
* Broadcast transport.
|
||||
* @return broadcast transport.
|
||||
*/
|
||||
BlockingUDPTransport* getBroadcastTransport();
|
||||
BlockingUDPTransport::shared_pointer getBroadcastTransport();
|
||||
|
||||
/**
|
||||
* Get channel access implementation.
|
||||
* @return channel access implementation.
|
||||
*/
|
||||
ChannelAccess* getChannelAccess();
|
||||
ChannelAccess::shared_pointer getChannelAccess();
|
||||
|
||||
/**
|
||||
* Get channel provider name.
|
||||
@@ -262,10 +272,7 @@ public:
|
||||
* Get channel provider.
|
||||
* @return channel provider.
|
||||
*/
|
||||
ChannelProvider* getChannelProvider();
|
||||
|
||||
void release();
|
||||
void acquire();
|
||||
ChannelProvider::shared_pointer getChannelProvider();
|
||||
|
||||
private:
|
||||
/**
|
||||
@@ -333,33 +340,33 @@ private:
|
||||
/**
|
||||
* Timer.
|
||||
*/
|
||||
epics::pvData::Timer* _timer;
|
||||
epics::pvData::Timer::shared_pointer _timer;
|
||||
|
||||
/**
|
||||
* Broadcast transport needed for channel searches.
|
||||
*/
|
||||
BlockingUDPTransport* _broadcastTransport;
|
||||
BlockingUDPTransport::shared_pointer _broadcastTransport;
|
||||
|
||||
/**
|
||||
* Beacon emitter.
|
||||
*/
|
||||
BeaconEmitter* _beaconEmitter;
|
||||
BeaconEmitter::shared_pointer _beaconEmitter;
|
||||
|
||||
/**
|
||||
* CAS acceptor (accepts CA virtual circuit).
|
||||
*/
|
||||
BlockingTCPAcceptor* _acceptor;
|
||||
BlockingTCPAcceptor::shared_pointer _acceptor;
|
||||
|
||||
/**
|
||||
* CA transport (virtual circuit) registry.
|
||||
* This registry contains all active transports - connections to CA servers.
|
||||
*/
|
||||
TransportRegistry* _transportRegistry;
|
||||
TransportRegistry::shared_pointer _transportRegistry;
|
||||
|
||||
/**
|
||||
* Channel access.
|
||||
*/
|
||||
ChannelAccess* _channelAccess;
|
||||
ChannelAccess::shared_pointer _channelAccess;
|
||||
|
||||
/**
|
||||
* Channel provider name.
|
||||
@@ -369,7 +376,7 @@ private:
|
||||
/**
|
||||
* Channel provider.
|
||||
*/
|
||||
ChannelProvider* _channelProvider;
|
||||
ChannelProvider::shared_pointer _channelProvider;
|
||||
|
||||
/**
|
||||
* Run mutex.
|
||||
@@ -384,7 +391,7 @@ private:
|
||||
/**
|
||||
* Beacon server status provider interface (optional).
|
||||
*/
|
||||
BeaconServerStatusProvider* _beaconServerStatusProvider;
|
||||
BeaconServerStatusProvider::shared_pointer _beaconServerStatusProvider;
|
||||
|
||||
/**
|
||||
* Initialize logger.
|
||||
|
||||
@@ -1,376 +0,0 @@
|
||||
/*
|
||||
* arrayFIFO.h
|
||||
*
|
||||
* Created on: Nov 8, 2010
|
||||
* Author: Miha Vitorovic
|
||||
*/
|
||||
|
||||
#ifndef ARRAYFIFO_H_
|
||||
#define ARRAYFIFO_H_
|
||||
|
||||
#ifdef ARRAY_FIFO_DEBUG
|
||||
#include <iostream>
|
||||
#endif
|
||||
|
||||
#include <cstring>
|
||||
#include <lock.h>
|
||||
#include <epicsAssert.h>
|
||||
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
template<class T>
|
||||
class ArrayFIFO {
|
||||
public:
|
||||
/**
|
||||
* Constructs an empty array deque with an initial capacity
|
||||
* sufficient to hold the specified number of elements. Array FIFO
|
||||
* is designed to hold objects allocated on the heap.
|
||||
*
|
||||
* @param[in] numElements lower bound on initial capacity of the
|
||||
* deque. Default value is 16 elements.
|
||||
*/
|
||||
ArrayFIFO(size_t numElements = 16);
|
||||
~ArrayFIFO();
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the front of this deque.
|
||||
*
|
||||
* @param[in] e the element to add.
|
||||
*/
|
||||
void addFirst(const T e);
|
||||
|
||||
/**
|
||||
* Inserts the specified element at the end of this deque.
|
||||
* @param[in] e the element to add
|
||||
*/
|
||||
void addLast(const T e);
|
||||
|
||||
T pollFirst();
|
||||
T pollLast();
|
||||
T peekFirst();
|
||||
T peekLast();
|
||||
|
||||
/**
|
||||
* Pushes an element onto the stack represented by this deque. In other
|
||||
* words, inserts the element at the front of this deque.
|
||||
*
|
||||
* @param[in] e the element to push
|
||||
*/
|
||||
void push(const T e);
|
||||
|
||||
/**
|
||||
* Pops an element from the stack represented by this deque. In other
|
||||
* words, removes and returns the first element of this deque.
|
||||
*
|
||||
* @return the element at the front of this deque (which is the top
|
||||
* of the stack represented by this deque), <code>null</code> if no element available.
|
||||
*/
|
||||
T pop();
|
||||
|
||||
/**
|
||||
* Looks at the object at the top of this stack without removing it
|
||||
* from the stack.
|
||||
* @return the object at the top of this stack (the last item
|
||||
* of the <tt>Vector</tt> object).
|
||||
*/
|
||||
T peek();
|
||||
|
||||
/**
|
||||
* Returns the number of elements in this deque.
|
||||
* @return the number of elements in this deque
|
||||
*/
|
||||
size_t size();
|
||||
|
||||
/**
|
||||
* Returns <tt>true</tt> if this deque contains no elements.
|
||||
*
|
||||
* @return <tt>true</tt> if this deque contains no elements
|
||||
*/
|
||||
bool isEmpty();
|
||||
|
||||
/**
|
||||
* Removes all of the elements from this deque.
|
||||
* The deque will be empty after this call returns.
|
||||
*
|
||||
* @param freeElements tells the methods to automatically free
|
||||
* the memory of all the elments in the FIFO. Default is {@code true}
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
* Removes the first occurrence of the specified element in this
|
||||
* deque (when traversing the deque from head to tail).
|
||||
* If the deque does not contain the element, it is unchanged.
|
||||
* More formally, removes the first element <tt>e</tt> such that
|
||||
* <tt>o.equals(e)</tt> (if such an element exists).
|
||||
* Returns <tt>true</tt> if this deque contained the specified element
|
||||
* (or equivalently, if this deque changed as a result of the call).
|
||||
*
|
||||
* @param o element to be removed from this deque, if present
|
||||
* @return <tt>true</tt> if the deque contained the specified element
|
||||
*/
|
||||
bool remove(const T e);
|
||||
|
||||
#ifdef ARRAY_FIFO_DEBUG
|
||||
void debugState() {
|
||||
//size_t mask = _size-1;
|
||||
std::cout<<"h:"<<_head<<",t:"<<_tail<<",c:"<<_size;
|
||||
std::cout<<",s:"<<size()<<std::endl;
|
||||
std::cout<<"Content:"<<std::endl;
|
||||
for (size_t i = 0; i < _size; i++)
|
||||
std::cout<<"["<<i<<"]: "<<_elements[i]<<std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
private:
|
||||
T* _elements; // array of pointers
|
||||
size_t _head, _tail, _size;
|
||||
epics::pvData::Mutex _mutex;
|
||||
static int MIN_INITIAL_CAPACITY;
|
||||
|
||||
/**
|
||||
* Allocate empty array to hold the given number of elements.
|
||||
* @param[in] numElements the number of elements to hold
|
||||
*/
|
||||
void allocateElements(const size_t numElements);
|
||||
|
||||
/**
|
||||
* Double the capacity of this deque. Call only when full, i.e.,
|
||||
* when head and tail have wrapped around to become equal.
|
||||
*/
|
||||
void doubleCapacity();
|
||||
|
||||
void arraycopy(T* src, size_t srcPos, T* dest, size_t destPos,
|
||||
size_t length);
|
||||
|
||||
/**
|
||||
* Removes the element at the specified position in the elements array,
|
||||
* adjusting head and tail as necessary. This can result in motion of
|
||||
* elements backwards or forwards in the array.
|
||||
*
|
||||
* <p>This method is called delete rather than remove to emphasize
|
||||
* that its semantics differ from those of {@link List#remove(int)}.
|
||||
*
|
||||
* @return true if elements moved backwards
|
||||
*/
|
||||
bool del(const size_t i);
|
||||
|
||||
};
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* g++ requires template definition inside a header file.
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
template<class T>
|
||||
int ArrayFIFO<T>::MIN_INITIAL_CAPACITY = 8;
|
||||
|
||||
template<class T>
|
||||
void ArrayFIFO<T>::arraycopy(T* src, size_t srcPos, T* dest,
|
||||
size_t destPos, size_t length) {
|
||||
if(srcPos<destPos) // this takes care of same-buffer copy
|
||||
for(int i = length-1; i>=0; i--)
|
||||
dest[destPos+i] = src[srcPos+i];
|
||||
else
|
||||
for(size_t i = 0; i<length; i++)
|
||||
dest[destPos++] = src[srcPos++];
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void ArrayFIFO<T>::allocateElements(size_t numElements) {
|
||||
_size = MIN_INITIAL_CAPACITY;
|
||||
// Find the best power of two to hold elements.
|
||||
// Tests "<=" because arrays aren't kept full.
|
||||
if(numElements>=_size) {
|
||||
_size = numElements;
|
||||
_size |= (_size>>1);
|
||||
_size |= (_size>>2);
|
||||
_size |= (_size>>4);
|
||||
_size |= (_size>>8);
|
||||
_size |= (_size>>16);
|
||||
_size++;
|
||||
}
|
||||
_elements = new T[_size];
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void ArrayFIFO<T>::doubleCapacity() {
|
||||
size_t p = _head;
|
||||
size_t n = _size;
|
||||
size_t r = n-p; // number of elements to the right of p
|
||||
size_t newCapacity = n<<1;
|
||||
T* a = new T[newCapacity];
|
||||
arraycopy(_elements, p, a, 0, r);
|
||||
arraycopy(_elements, 0, a, r, p);
|
||||
delete[] _elements;
|
||||
_elements = a;
|
||||
_size = newCapacity;
|
||||
_head = 0;
|
||||
_tail = n;
|
||||
|
||||
}
|
||||
|
||||
template<class T>
|
||||
ArrayFIFO<T>::ArrayFIFO(size_t numElements) :
|
||||
_head(0), _tail(0), _mutex() {
|
||||
allocateElements(numElements);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
ArrayFIFO<T>::~ArrayFIFO() {
|
||||
delete[] _elements;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void ArrayFIFO<T>::addFirst(const T e) {
|
||||
epics::pvData::Lock lock(_mutex);
|
||||
|
||||
_elements[_head = (_head-1)&(_size-1)] = e;
|
||||
if(_head==_tail) doubleCapacity();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void ArrayFIFO<T>::addLast(const T e) {
|
||||
epics::pvData::Lock lock(_mutex);
|
||||
|
||||
_elements[_tail] = e;
|
||||
if((_tail = (_tail+1)&(_size-1))==_head) doubleCapacity();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T ArrayFIFO<T>::pollFirst() {
|
||||
epics::pvData::Lock lock(_mutex);
|
||||
|
||||
if(isEmpty()) return 0;
|
||||
|
||||
T result = _elements[_head]; // Element is null if deque empty
|
||||
_head = (_head+1)&(_size-1);
|
||||
return result;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T ArrayFIFO<T>::pollLast() {
|
||||
epics::pvData::Lock lock(_mutex);
|
||||
|
||||
if(isEmpty()) return 0;
|
||||
|
||||
_tail = (_tail-1)&(_size-1);
|
||||
return _elements[_tail];
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T ArrayFIFO<T>::peekFirst() {
|
||||
epics::pvData::Lock lock(_mutex);
|
||||
|
||||
if(isEmpty()) return 0;
|
||||
|
||||
return _elements[_head];
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T ArrayFIFO<T>::peekLast() {
|
||||
epics::pvData::Lock lock(_mutex);
|
||||
|
||||
if(isEmpty()) return 0;
|
||||
|
||||
return _elements[(_tail-1)&(_size-1)];
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void ArrayFIFO<T>::push(const T e) {
|
||||
addLast(e);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T ArrayFIFO<T>::pop() {
|
||||
return pollLast();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T ArrayFIFO<T>::peek() {
|
||||
return peekFirst();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
size_t ArrayFIFO<T>::size() {
|
||||
epics::pvData::Lock lock(_mutex);
|
||||
|
||||
return (_tail-_head)&(_size-1);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool ArrayFIFO<T>::isEmpty() {
|
||||
epics::pvData::Lock lock(_mutex);
|
||||
|
||||
return _head==_tail;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
void ArrayFIFO<T>::clear() {
|
||||
epics::pvData::Lock lock(_mutex);
|
||||
|
||||
_head = _tail = 0;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool ArrayFIFO<T>::del(const size_t i) {
|
||||
// i is absolute index in the array
|
||||
size_t mask = _size-1;
|
||||
size_t h = _head;
|
||||
size_t t = _tail;
|
||||
size_t front = (i-h)&mask;
|
||||
size_t back = (t-i)&mask;
|
||||
|
||||
// Invariant: head <= i < tail mod circularity
|
||||
assert(front<((t-h)&mask)); // concurrency problem detected
|
||||
|
||||
// Optimize for least element motion
|
||||
if(front<back) {
|
||||
if(h<=i) {
|
||||
arraycopy(_elements, h, _elements, h+1, front);
|
||||
}
|
||||
else { // Wrap around
|
||||
arraycopy(_elements, 0, _elements, 1, i);
|
||||
if(t>0) _elements[0] = _elements[mask];
|
||||
arraycopy(_elements, h, _elements, h+1, mask-h);
|
||||
}
|
||||
_head = (h+1)&mask;
|
||||
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if(i<t) { // Copy the null tail as well
|
||||
arraycopy(_elements, i+1, _elements, i, back);
|
||||
_tail = t-1;
|
||||
}
|
||||
else { // Wrap around
|
||||
arraycopy(_elements, i+1, _elements, i, mask-i);
|
||||
_elements[mask] = _elements[0];
|
||||
arraycopy(_elements, 1, _elements, 0, t);
|
||||
_tail = (t-1)&mask;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool ArrayFIFO<T>::remove(const T e) {
|
||||
epics::pvData::Lock lock(_mutex);
|
||||
|
||||
if(isEmpty()) return false; // nothing to do
|
||||
|
||||
size_t mask = _size-1;
|
||||
size_t i = _head;
|
||||
while(i!=_tail) {
|
||||
if(e==_elements[i]) {
|
||||
del(i);
|
||||
return true;
|
||||
}
|
||||
i = (i+1)&mask;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* ARRAYFIFO_H_ */
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <pvType.h>
|
||||
#include <noDefaultMethods.h>
|
||||
#include <lock.h>
|
||||
#include <sharedPtr.h>
|
||||
|
||||
#include <envDefs.h>
|
||||
|
||||
@@ -72,6 +73,9 @@ private:
|
||||
class Configuration : private epics::pvData::NoDefaultMethods
|
||||
{
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<Configuration> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const Configuration> const_shared_pointer;
|
||||
|
||||
/*
|
||||
* Destructor.
|
||||
*/
|
||||
|
||||
@@ -1,281 +0,0 @@
|
||||
/*
|
||||
* growingCircularBuffer.h
|
||||
*
|
||||
* Created on: Nov 11, 2010
|
||||
* Author: Miha Vitorovic
|
||||
*/
|
||||
|
||||
#ifndef GROWINGCIRCULARBUFFER_H_
|
||||
#define GROWINGCIRCULARBUFFER_H_
|
||||
|
||||
// TODO remove exception throwing !!!
|
||||
|
||||
#include <epicsException.h>
|
||||
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
/**
|
||||
* Implementation of circular FIFO unbouded buffer.
|
||||
* Instance is not thread safe.
|
||||
* @author Miha Vitorovic
|
||||
*/
|
||||
template<class T>
|
||||
class GrowingCircularBuffer {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Create a GrowingCircularBuffer with the given capacity.
|
||||
**/
|
||||
GrowingCircularBuffer(size_t capacity = 16) :
|
||||
_elements(new T[capacity]), _takePointer(0), _putPointer(0),
|
||||
_count(0), _size(capacity) {
|
||||
}
|
||||
|
||||
~GrowingCircularBuffer() {
|
||||
delete[] _elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of elements in the buffer.
|
||||
* @return number of elements in the buffer.
|
||||
*/
|
||||
inline size_t size() {
|
||||
return _count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current buffer capacity.
|
||||
* @return buffer current capacity.
|
||||
*/
|
||||
inline size_t capacity() {
|
||||
return _size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a new element in to the buffer.
|
||||
* If buffer full the buffer is doubled.
|
||||
*
|
||||
* @param x element to insert.
|
||||
* @return <code>true</code> if first element.
|
||||
*/
|
||||
bool insert(const T x);
|
||||
|
||||
/**
|
||||
* Extract the oldest element from the buffer.
|
||||
* @return the oldest element from the buffer.
|
||||
*/
|
||||
T extract();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Array (circular buffer) of elements.
|
||||
*/
|
||||
T* _elements;
|
||||
|
||||
/**
|
||||
* Take (read) pointer.
|
||||
*/
|
||||
size_t _takePointer;
|
||||
|
||||
/**
|
||||
* Put (write) pointer.
|
||||
*/
|
||||
size_t _putPointer;
|
||||
|
||||
/**
|
||||
* Number of elements in the buffer.
|
||||
*/
|
||||
size_t _count;
|
||||
|
||||
size_t _size;
|
||||
|
||||
void arraycopy(T* src, size_t srcPos, T* dest, size_t destPos,
|
||||
size_t length);
|
||||
};
|
||||
|
||||
template<class T>
|
||||
void GrowingCircularBuffer<T>::arraycopy(T* src, size_t srcPos,
|
||||
T* dest, size_t destPos, size_t length) {
|
||||
if(srcPos<destPos) // this takes care of same-buffer copy
|
||||
for(int i = length-1; i>=0; i--)
|
||||
dest[destPos+i] = src[srcPos+i];
|
||||
else
|
||||
for(size_t i = 0; i<length; i++)
|
||||
dest[destPos++] = src[srcPos++];
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool GrowingCircularBuffer<T>::insert(const T x) {
|
||||
if(_count==_size) {
|
||||
// we are full, grow by factor 2
|
||||
T* newElements = new T[_size*2];
|
||||
|
||||
// invariant: _takePointer < _size
|
||||
size_t split = _size-_takePointer;
|
||||
if(split>0) arraycopy(_elements, _takePointer, newElements, 0,
|
||||
split);
|
||||
if(_takePointer!=0) arraycopy(_elements, 0, newElements, split,
|
||||
_putPointer);
|
||||
|
||||
_takePointer = 0;
|
||||
_putPointer = _size;
|
||||
_size *= 2;
|
||||
delete[] _elements;
|
||||
_elements = newElements;
|
||||
}
|
||||
_count++;
|
||||
|
||||
_elements[_putPointer] = x;
|
||||
if(++_putPointer>=_size) _putPointer = 0;
|
||||
return _count==1;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T GrowingCircularBuffer<T>::extract() {
|
||||
if(_count==0) THROW_BASE_EXCEPTION("Buffer empty.");
|
||||
|
||||
_count--;
|
||||
T old = _elements[_takePointer];
|
||||
if(++_takePointer>=_size) _takePointer = 0;
|
||||
return old;
|
||||
}
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
/**
|
||||
* Template specialization for pointers.
|
||||
* Implementation of circular FIFO unbouded buffer.
|
||||
* Instance is not thread safe.
|
||||
* @author Miha Vitorovic
|
||||
*/
|
||||
template<class T>
|
||||
class GrowingCircularBuffer<T*> {
|
||||
public:
|
||||
|
||||
/**
|
||||
* Create a GrowingCircularBuffer with the given capacity.
|
||||
**/
|
||||
GrowingCircularBuffer(size_t capacity = 16) :
|
||||
_elements(new T*[capacity]), _takePointer(0), _putPointer(0),
|
||||
_count(0), _size(capacity) {
|
||||
}
|
||||
|
||||
~GrowingCircularBuffer() {
|
||||
delete[] _elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get number of elements in the buffer.
|
||||
* @return number of elements in the buffer.
|
||||
*/
|
||||
inline size_t size() {
|
||||
return _count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get current buffer capacity.
|
||||
* @return buffer current capacity.
|
||||
*/
|
||||
inline size_t capacity() {
|
||||
return _size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a new element in to the buffer.
|
||||
* If buffer full the buffer is doubled.
|
||||
*
|
||||
* @param x element to insert.
|
||||
* @return <code>true</code> if first element.
|
||||
*/
|
||||
bool insert(const T* x);
|
||||
|
||||
/**
|
||||
* Extract the oldest element from the buffer.
|
||||
* @return the oldest element from the buffer.
|
||||
*/
|
||||
T* extract();
|
||||
|
||||
private:
|
||||
/**
|
||||
* Array (circular buffer) of elements.
|
||||
*/
|
||||
T** _elements;
|
||||
|
||||
/**
|
||||
* Take (read) pointer.
|
||||
*/
|
||||
size_t _takePointer;
|
||||
|
||||
/**
|
||||
* Put (write) pointer.
|
||||
*/
|
||||
size_t _putPointer;
|
||||
|
||||
/**
|
||||
* Number of elements in the buffer.
|
||||
*/
|
||||
size_t _count;
|
||||
|
||||
size_t _size;
|
||||
|
||||
void arraycopy(T** src, size_t srcPos, T** dest, size_t destPos,
|
||||
size_t length);
|
||||
};
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
||||
* g++ requires template definition inside a header file.
|
||||
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
|
||||
template<class T>
|
||||
void GrowingCircularBuffer<T*>::arraycopy(T** src, size_t srcPos,
|
||||
T** dest, size_t destPos, size_t length) {
|
||||
if(srcPos<destPos) // this takes care of same-buffer copy
|
||||
for(int i = length-1; i>=0; i--)
|
||||
dest[destPos+i] = src[srcPos+i];
|
||||
else
|
||||
for(size_t i = 0; i<length; i++)
|
||||
dest[destPos++] = src[srcPos++];
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool GrowingCircularBuffer<T*>::insert(const T* x) {
|
||||
if(_count==_size) {
|
||||
// we are full, grow by factor 2
|
||||
T** newElements = new T*[_size*2];
|
||||
|
||||
// invariant: _takePointer < _size
|
||||
size_t split = _size-_takePointer;
|
||||
if(split>0) arraycopy(_elements, _takePointer, newElements, 0,
|
||||
split);
|
||||
if(_takePointer!=0) arraycopy(_elements, 0, newElements, split,
|
||||
_putPointer);
|
||||
|
||||
_takePointer = 0;
|
||||
_putPointer = _size;
|
||||
_size *= 2;
|
||||
delete[] _elements;
|
||||
_elements = newElements;
|
||||
}
|
||||
_count++;
|
||||
|
||||
_elements[_putPointer] = const_cast<T*>(x);
|
||||
if(++_putPointer>=_size) _putPointer = 0;
|
||||
return _count==1;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
T* GrowingCircularBuffer<T*>::extract() {
|
||||
if(_count==0) return NULL;
|
||||
|
||||
_count--;
|
||||
T* old = _elements[_takePointer];
|
||||
if(++_takePointer>=_size) _takePointer = 0;
|
||||
return old;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif /* GROWINGCIRCULARBUFFER_H_ */
|
||||
@@ -3,6 +3,9 @@
|
||||
*/
|
||||
|
||||
#include "introspectionRegistry.h"
|
||||
#include <convert.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
|
||||
namespace epics { namespace pvAccess {
|
||||
|
||||
@@ -12,7 +15,7 @@ const int8 IntrospectionRegistry::FULL_WITH_ID_TYPE_CODE = (int8)-3;
|
||||
PVDataCreate* IntrospectionRegistry::_pvDataCreate = 0;
|
||||
FieldCreate* IntrospectionRegistry::_fieldCreate = 0;
|
||||
|
||||
IntrospectionRegistry::IntrospectionRegistry(bool serverSide) : _mutex()
|
||||
IntrospectionRegistry::IntrospectionRegistry(bool serverSide)
|
||||
{
|
||||
// TODO not optimal
|
||||
_pvDataCreate = getPVDataCreate();
|
||||
@@ -31,11 +34,7 @@ void IntrospectionRegistry::reset()
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
_outgoingIdPointer = _direction;
|
||||
//decrement references
|
||||
for(_registryRIter = _registry.rbegin(); _registryRIter != _registry.rend(); _registryRIter++)
|
||||
{
|
||||
_registryRIter->second->decReferenceCount();
|
||||
}
|
||||
|
||||
_registry.clear();
|
||||
}
|
||||
|
||||
@@ -45,7 +44,7 @@ FieldConstPtr IntrospectionRegistry::getIntrospectionInterface(const short id)
|
||||
_registryIter = _registry.find(id);
|
||||
if(_registryIter == _registry.end())
|
||||
{
|
||||
return NULL;
|
||||
return FieldConstPtr();
|
||||
}
|
||||
return _registryIter->second;
|
||||
}
|
||||
@@ -53,14 +52,11 @@ FieldConstPtr IntrospectionRegistry::getIntrospectionInterface(const short id)
|
||||
void IntrospectionRegistry::registerIntrospectionInterface(const short id,FieldConstPtr field)
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
//first decrement reference on old value
|
||||
|
||||
_registryIter = _registry.find(id);
|
||||
if(_registryIter != _registry.end())
|
||||
{
|
||||
_registryIter->second->decReferenceCount();
|
||||
}
|
||||
|
||||
_registry[id] = field;
|
||||
field->incReferenceCount();
|
||||
|
||||
}
|
||||
|
||||
short IntrospectionRegistry::registerIntrospectionInterface(FieldConstPtr field, bool& existing)
|
||||
@@ -84,13 +80,9 @@ short IntrospectionRegistry::registerIntrospectionInterface(FieldConstPtr field,
|
||||
|
||||
//first decrement reference on old value
|
||||
_registryIter = _registry.find(key);
|
||||
if(_registryIter != _registry.end())
|
||||
{
|
||||
_registryIter->second->decReferenceCount();
|
||||
}
|
||||
|
||||
_registry[key] = field;
|
||||
field->incReferenceCount();
|
||||
|
||||
}
|
||||
return key;
|
||||
}
|
||||
@@ -104,7 +96,7 @@ void IntrospectionRegistry::printKeysAndValues(string name)
|
||||
buffer.clear();
|
||||
cout << "\t" << "Key: "<< _registryIter->first << endl;
|
||||
cout << "\t" << "Value: " << _registryIter->second << endl;
|
||||
_registryIter->second->dumpReferenceCount(&buffer,0);
|
||||
|
||||
cout << "\t" << "References: " << buffer.c_str() << endl;
|
||||
buffer.clear();
|
||||
_registryIter->second->toString(&buffer);
|
||||
@@ -127,7 +119,7 @@ bool IntrospectionRegistry::registryContainsValue(FieldConstPtr field, short& ke
|
||||
|
||||
void IntrospectionRegistry::serialize(FieldConstPtr field, ByteBuffer* buffer, SerializableControl* control)
|
||||
{
|
||||
serialize(field, NULL, buffer, control, this);
|
||||
serialize(field, StructureConstPtr(), buffer, control, this);
|
||||
}
|
||||
|
||||
FieldConstPtr IntrospectionRegistry::deserialize(ByteBuffer* buffer, DeserializableControl* control)
|
||||
@@ -137,7 +129,7 @@ FieldConstPtr IntrospectionRegistry::deserialize(ByteBuffer* buffer, Deserializa
|
||||
|
||||
void IntrospectionRegistry::serializeFull(FieldConstPtr field, ByteBuffer* buffer, SerializableControl* control)
|
||||
{
|
||||
serialize(field, NULL, buffer, control, NULL);
|
||||
serialize(field, StructureConstPtr(), buffer, control, NULL);
|
||||
}
|
||||
|
||||
FieldConstPtr IntrospectionRegistry::deserializeFull(ByteBuffer* buffer, DeserializableControl* control)
|
||||
@@ -181,7 +173,7 @@ void IntrospectionRegistry::serialize(FieldConstPtr field, StructureConstPtr par
|
||||
{
|
||||
case epics::pvData::scalar:
|
||||
{
|
||||
ScalarConstPtr scalar = static_cast<ScalarConstPtr>(field);
|
||||
ScalarConstPtr scalar = static_pointer_cast<const Scalar>(field);
|
||||
control->ensureBuffer(1);
|
||||
buffer->putByte((int8)(epics::pvData::scalar << 4 | scalar->getScalarType()));
|
||||
SerializeHelper::serializeString(field->getFieldName(), buffer, control);
|
||||
@@ -189,7 +181,7 @@ void IntrospectionRegistry::serialize(FieldConstPtr field, StructureConstPtr par
|
||||
}
|
||||
case epics::pvData::scalarArray:
|
||||
{
|
||||
ScalarArrayConstPtr array = static_cast<ScalarArrayConstPtr>(field);
|
||||
ScalarArrayConstPtr array = static_pointer_cast<const ScalarArray>(field);
|
||||
control->ensureBuffer(1);
|
||||
buffer->putByte((int8)(epics::pvData::scalarArray << 4 | array->getElementType()));
|
||||
SerializeHelper::serializeString(field->getFieldName(), buffer, control);
|
||||
@@ -197,7 +189,7 @@ void IntrospectionRegistry::serialize(FieldConstPtr field, StructureConstPtr par
|
||||
}
|
||||
case epics::pvData::structure:
|
||||
{
|
||||
StructureConstPtr structure = static_cast<StructureConstPtr>(field);
|
||||
StructureConstPtr structure = static_pointer_cast<const Structure>(field);
|
||||
control->ensureBuffer(1);
|
||||
buffer->putByte((int8)(epics::pvData::structure << 4));
|
||||
serializeStructureField(buffer, control, registry, structure);
|
||||
@@ -205,12 +197,12 @@ void IntrospectionRegistry::serialize(FieldConstPtr field, StructureConstPtr par
|
||||
}
|
||||
case epics::pvData::structureArray:
|
||||
{
|
||||
StructureArrayConstPtr structureArray = static_cast<StructureArrayConstPtr>(field);
|
||||
StructureArrayConstPtr structureArray = static_pointer_cast<const StructureArray>(field);
|
||||
control->ensureBuffer(1);
|
||||
buffer->putByte((int8)(epics::pvData::structureArray << 4));
|
||||
SerializeHelper::serializeString(field->getFieldName(), buffer, control);
|
||||
// we also need to serialize structure field...
|
||||
const Structure* structureElement = structureArray->getStructure();
|
||||
StructureConstPtr structureElement = structureArray->getStructure();
|
||||
serializeStructureField(buffer, control, registry, structureElement);
|
||||
break;
|
||||
}
|
||||
@@ -236,13 +228,13 @@ FieldConstPtr IntrospectionRegistry::deserialize(ByteBuffer* buffer, Deserializa
|
||||
const int8 typeCode = buffer->getByte();
|
||||
if(typeCode == IntrospectionRegistry::NULL_TYPE_CODE)
|
||||
{
|
||||
return NULL;
|
||||
return FieldConstPtr();
|
||||
}
|
||||
else if(typeCode == IntrospectionRegistry::ONLY_ID_TYPE_CODE)
|
||||
{
|
||||
control->ensureData(sizeof(int16)/sizeof(int8));
|
||||
FieldConstPtr field = registry->getIntrospectionInterface(buffer->getShort());
|
||||
field->incReferenceCount(); // we inc, so that deserialize always returns a field with +1 ref. count (as when created)
|
||||
|
||||
return field;
|
||||
}
|
||||
|
||||
@@ -286,7 +278,7 @@ FieldConstPtr IntrospectionRegistry::deserialize(ByteBuffer* buffer, Deserializa
|
||||
default:
|
||||
{
|
||||
// TODO log
|
||||
return NULL;
|
||||
return FieldConstPtr();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -313,7 +305,7 @@ void IntrospectionRegistry::serializeStructure(ByteBuffer* buffer, SerializableC
|
||||
{
|
||||
if (pvStructure == NULL)
|
||||
{
|
||||
serialize(NULL, buffer, control);
|
||||
serialize(StructureConstPtr(), buffer, control);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -328,7 +320,8 @@ PVStructurePtr IntrospectionRegistry::deserializeStructure(ByteBuffer* buffer, D
|
||||
FieldConstPtr structureField = deserialize(buffer, control);
|
||||
if (structureField != NULL)
|
||||
{
|
||||
pvStructure = _pvDataCreate->createPVStructure(NULL, static_cast<StructureConstPtr>(structureField));
|
||||
pvStructure = _pvDataCreate->createPVStructure(NULL,
|
||||
static_pointer_cast<const Structure>(structureField));
|
||||
pvStructure->deserialize(buffer, control);
|
||||
}
|
||||
return pvStructure;
|
||||
@@ -353,7 +346,8 @@ PVStructurePtr IntrospectionRegistry::deserializeStructureAndCreatePVStructure(B
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
PVStructurePtr retVal = _pvDataCreate->createPVStructure(NULL,static_cast<StructureConstPtr>(field));
|
||||
PVStructurePtr retVal = _pvDataCreate->createPVStructure(NULL,
|
||||
static_pointer_cast<const Structure>(field));
|
||||
return retVal;
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ using namespace std;
|
||||
|
||||
namespace epics { namespace pvAccess {
|
||||
|
||||
typedef std::map<const short,const Field*> registryMap_t;
|
||||
typedef std::map<const short,FieldConstPtr> registryMap_t;
|
||||
|
||||
|
||||
/**
|
||||
@@ -34,10 +34,11 @@ typedef std::map<const short,const Field*> registryMap_t;
|
||||
* Registry is used to cache introspection interfaces to minimize network traffic.
|
||||
* @author gjansa
|
||||
*/
|
||||
class IntrospectionRegistry {
|
||||
class IntrospectionRegistry : public NoDefaultMethods {
|
||||
public:
|
||||
IntrospectionRegistry(bool serverSide);
|
||||
virtual ~IntrospectionRegistry();
|
||||
|
||||
void printKeysAndValues(string name);
|
||||
/**
|
||||
* Resets registry, i.e. must be done when transport is changed (server restarted).
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
/*
|
||||
* namedLockPattern.cpp
|
||||
*/
|
||||
|
||||
#include "namedLockPattern.h"
|
||||
|
||||
//NOTE NamedLockPattern is template so implementation is in header file
|
||||
@@ -13,7 +13,10 @@
|
||||
|
||||
#include "referenceCountingLock.h"
|
||||
|
||||
// TODO implement using smart pointers
|
||||
|
||||
namespace epics { namespace pvAccess {
|
||||
|
||||
/**
|
||||
* NamedLockPattern
|
||||
*/
|
||||
@@ -41,12 +44,12 @@ public:
|
||||
* @return <code>true</code> if acquired, <code>false</code> othwerwise.
|
||||
* NOTE: currently this routine always returns true. Look above for explanation.
|
||||
*/
|
||||
bool acquireSynchronizationObject(const Key name, const epics::pvData::int64 msec);
|
||||
bool acquireSynchronizationObject(const Key& name, const epics::pvData::int64 msec);
|
||||
/**
|
||||
* Release synchronization lock for named object.
|
||||
* @param name name of the object whose lock to release.
|
||||
*/
|
||||
void releaseSynchronizationObject(const Key name);
|
||||
void releaseSynchronizationObject(const Key& name);
|
||||
private:
|
||||
epics::pvData::Mutex _mutex;
|
||||
std::map<const Key,ReferenceCountingLock*,Compare> _namedLocks;
|
||||
@@ -58,11 +61,11 @@ private:
|
||||
* @param release set to <code>false</code> if there is no need to call release
|
||||
* on synchronization lock.
|
||||
*/
|
||||
void releaseSynchronizationObject(const Key name,const bool release);
|
||||
void releaseSynchronizationObject(const Key& name,const bool release);
|
||||
};
|
||||
|
||||
template <class Key, class Compare>
|
||||
bool NamedLockPattern<Key,Compare>::acquireSynchronizationObject(const Key name, const epics::pvData::int64 msec)
|
||||
bool NamedLockPattern<Key,Compare>::acquireSynchronizationObject(const Key& name, const epics::pvData::int64 msec)
|
||||
{
|
||||
ReferenceCountingLock* lock;
|
||||
{ //due to guard
|
||||
@@ -96,13 +99,13 @@ bool NamedLockPattern<Key,Compare>::acquireSynchronizationObject(const Key name,
|
||||
}
|
||||
|
||||
template <class Key, class Compare>
|
||||
void NamedLockPattern<Key,Compare>::releaseSynchronizationObject(const Key name)
|
||||
void NamedLockPattern<Key,Compare>::releaseSynchronizationObject(const Key& name)
|
||||
{
|
||||
releaseSynchronizationObject(name, true);
|
||||
}
|
||||
|
||||
template <class Key, class Compare>
|
||||
void NamedLockPattern<Key,Compare>::releaseSynchronizationObject(const Key name,const bool release)
|
||||
void NamedLockPattern<Key,Compare>::releaseSynchronizationObject(const Key& name,const bool release)
|
||||
{
|
||||
epics::pvData::Lock guard(_mutex);
|
||||
ReferenceCountingLock* lock;
|
||||
@@ -134,7 +137,7 @@ class NamedLock : private epics::pvData::NoDefaultMethods
|
||||
{
|
||||
public:
|
||||
NamedLock(NamedLockPattern<Key,Compare>* namedLockPattern): _namedLockPattern(namedLockPattern) {}
|
||||
bool acquireSynchronizationObject(const Key name, const epics::pvData::int64 msec) {_name = name; return _namedLockPattern->acquireSynchronizationObject(name,msec);}
|
||||
bool acquireSynchronizationObject(const Key& name, const epics::pvData::int64 msec) {_name = name; return _namedLockPattern->acquireSynchronizationObject(name,msec);}
|
||||
~NamedLock(){_namedLockPattern->releaseSynchronizationObject(_name);}
|
||||
private:
|
||||
Key _name;
|
||||
|
||||
@@ -9,100 +9,97 @@ using namespace std;
|
||||
|
||||
namespace epics { namespace pvAccess {
|
||||
|
||||
TransportRegistry::TransportRegistry(): _mutex()
|
||||
TransportRegistry::TransportRegistry(): _transports(), _transportCount(0), _mutex()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
TransportRegistry::~TransportRegistry()
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
void TransportRegistry::put(Transport* transport)
|
||||
void TransportRegistry::put(Transport::shared_pointer& transport)
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
//const String type = transport.getType();
|
||||
const int16 priority = transport->getPriority();
|
||||
const osiSockAddr* address = transport->getRemoteAddress();
|
||||
|
||||
_transportsIter = _transports.find(address);
|
||||
prioritiesMap_t* priorities;
|
||||
if(_transportsIter == _transports.end())
|
||||
transportsMap_t::iterator transportsIter = _transports.find(address);
|
||||
prioritiesMapSharedPtr_t priorities;
|
||||
if(transportsIter == _transports.end())
|
||||
{
|
||||
priorities = new prioritiesMap_t();
|
||||
priorities.reset(new prioritiesMap_t());
|
||||
_transports[address] = priorities;
|
||||
_transportCount++;
|
||||
}
|
||||
else
|
||||
{
|
||||
priorities = _transportsIter->second;
|
||||
}
|
||||
(*priorities)[priority] = transport;
|
||||
_allTransports.push_back(transport);
|
||||
}
|
||||
|
||||
Transport* TransportRegistry::get(const String type, const osiSockAddr* address, const int16 priority)
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
_transportsIter = _transports.find(address);
|
||||
if(_transportsIter != _transports.end())
|
||||
{
|
||||
prioritiesMap_t* priorities = _transportsIter->second;
|
||||
_prioritiesIter = priorities->find(priority);
|
||||
if(_prioritiesIter != priorities->end())
|
||||
priorities = transportsIter->second;
|
||||
prioritiesMap_t::iterator prioritiesIter = priorities->find(priority);
|
||||
if(prioritiesIter == priorities->end()) //only increase transportCount if not replacing
|
||||
{
|
||||
return _prioritiesIter->second;
|
||||
_transportCount++;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
(*priorities)[priority] = transport;
|
||||
}
|
||||
|
||||
Transport** TransportRegistry::get(const String type, const osiSockAddr* address, int32& size)
|
||||
Transport::shared_pointer TransportRegistry::get(String type, const osiSockAddr* address, const int16 priority)
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
_transportsIter = _transports.find(address);
|
||||
if(_transportsIter != _transports.end())
|
||||
transportsMap_t::iterator transportsIter = _transports.find(address);
|
||||
if(transportsIter != _transports.end())
|
||||
{
|
||||
prioritiesMap_t* priorities = _transportsIter->second;
|
||||
size = priorities->size();
|
||||
Transport** transportArray = new Transport*[size];
|
||||
int i = 0;
|
||||
for(_prioritiesIter = priorities->begin(); _prioritiesIter != priorities->end(); _prioritiesIter++, i++)
|
||||
prioritiesMapSharedPtr_t priorities = transportsIter->second;
|
||||
prioritiesMap_t::iterator prioritiesIter = priorities->find(priority);
|
||||
if(prioritiesIter != priorities->end())
|
||||
{
|
||||
transportArray[i] = _prioritiesIter->second;
|
||||
return prioritiesIter->second;
|
||||
}
|
||||
}
|
||||
return Transport::shared_pointer();
|
||||
}
|
||||
|
||||
auto_ptr<TransportRegistry::transportVector_t> TransportRegistry::get(String type, const osiSockAddr* address)
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
transportsMap_t::iterator transportsIter = _transports.find(address);
|
||||
if(transportsIter != _transports.end())
|
||||
{
|
||||
prioritiesMapSharedPtr_t priorities = transportsIter->second;
|
||||
auto_ptr<transportVector_t> transportArray(new transportVector_t(priorities->size()));
|
||||
int32 i = 0;
|
||||
for(prioritiesMap_t::iterator prioritiesIter = priorities->begin();
|
||||
prioritiesIter != priorities->end();
|
||||
prioritiesIter++, i++)
|
||||
{
|
||||
transportArray->at(i) = prioritiesIter->second;
|
||||
}
|
||||
return transportArray;
|
||||
}
|
||||
return NULL;
|
||||
return auto_ptr<transportVector_t>();
|
||||
}
|
||||
|
||||
Transport* TransportRegistry::remove(Transport* transport)
|
||||
Transport::shared_pointer TransportRegistry::remove(Transport::shared_pointer& transport)
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
const int16 priority = transport->getPriority();
|
||||
const osiSockAddr* address = transport->getRemoteAddress();
|
||||
Transport* retTransport = NULL;
|
||||
_transportsIter = _transports.find(address);
|
||||
if(_transportsIter != _transports.end())
|
||||
Transport::shared_pointer retTransport;
|
||||
transportsMap_t::iterator transportsIter = _transports.find(address);
|
||||
if(transportsIter != _transports.end())
|
||||
{
|
||||
prioritiesMap_t* priorities = _transportsIter->second;
|
||||
_prioritiesIter = priorities->find(priority);
|
||||
if(_prioritiesIter != priorities->end())
|
||||
prioritiesMapSharedPtr_t priorities = transportsIter->second;
|
||||
prioritiesMap_t::iterator prioritiesIter = priorities->find(priority);
|
||||
if(prioritiesIter != priorities->end())
|
||||
{
|
||||
for(_allTransportsIter = _allTransports.begin(); _allTransportsIter != _allTransports.end(); _allTransportsIter++)
|
||||
{
|
||||
if(_prioritiesIter->second == *_allTransportsIter)
|
||||
{
|
||||
retTransport = _prioritiesIter->second;
|
||||
_allTransports.erase(_allTransportsIter);
|
||||
break;
|
||||
}
|
||||
}
|
||||
priorities->erase(_prioritiesIter);
|
||||
retTransport = prioritiesIter->second;
|
||||
priorities->erase(prioritiesIter);
|
||||
_transportCount--;
|
||||
if(priorities->size() == 0)
|
||||
{
|
||||
_transports.erase(_transportsIter);
|
||||
delete priorities;
|
||||
_transports.erase(transportsIter);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -112,51 +109,44 @@ Transport* TransportRegistry::remove(Transport* transport)
|
||||
void TransportRegistry::clear()
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
for(_transportsIter = _transports.begin(); _transportsIter != _transports.end(); _transportsIter++)
|
||||
{
|
||||
delete _transportsIter->second;
|
||||
}
|
||||
|
||||
_transports.clear();
|
||||
_allTransports.clear();
|
||||
_transportCount = 0;
|
||||
}
|
||||
|
||||
int TransportRegistry::numberOfActiveTransports()
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
return (int32)_allTransports.size();
|
||||
return _transportCount;
|
||||
}
|
||||
|
||||
Transport** TransportRegistry::toArray(const String type, int32& size)
|
||||
auto_ptr<TransportRegistry::transportVector_t> TransportRegistry::toArray(String type)
|
||||
{
|
||||
// TODO support type
|
||||
Lock guard(_mutex);
|
||||
size = _allTransports.size();
|
||||
Transport** transportArray = new Transport*[size];
|
||||
int i = 0;
|
||||
for(_allTransportsIter = _allTransports.begin(); _allTransportsIter != _allTransports.end(); _allTransportsIter++, i++)
|
||||
{
|
||||
transportArray[i] = *_allTransportsIter;
|
||||
}
|
||||
return transportArray;
|
||||
return toArray();
|
||||
}
|
||||
|
||||
Transport** TransportRegistry::toArray(int32& size)
|
||||
auto_ptr<TransportRegistry::transportVector_t> TransportRegistry::toArray()
|
||||
{
|
||||
Lock guard(_mutex);
|
||||
size = _allTransports.size();
|
||||
if (_transportCount == 0)
|
||||
return auto_ptr<transportVector_t>(0);
|
||||
|
||||
auto_ptr<transportVector_t> transportArray(new transportVector_t(_transportCount));
|
||||
|
||||
if(size == 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Transport** transportArray = new Transport*[size];
|
||||
int i = 0;
|
||||
for(_allTransportsIter = _allTransports.begin(); _allTransportsIter != _allTransports.end(); _allTransportsIter++, i++)
|
||||
{
|
||||
transportArray[i] = *_allTransportsIter;
|
||||
}
|
||||
int32 i = 0;
|
||||
for (transportsMap_t::iterator transportsIter = _transports.begin();
|
||||
transportsIter != _transports.end();
|
||||
transportsIter++)
|
||||
{
|
||||
prioritiesMapSharedPtr_t priorities = transportsIter->second;
|
||||
for (prioritiesMap_t::iterator prioritiesIter = priorities->begin();
|
||||
prioritiesIter != priorities->end();
|
||||
prioritiesIter++, i++)
|
||||
{
|
||||
transportArray->at(i) = prioritiesIter->second;
|
||||
}
|
||||
}
|
||||
|
||||
return transportArray;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,38 +16,40 @@
|
||||
#include <epicsException.h>
|
||||
#include <remote.h>
|
||||
#include "inetAddressUtil.h"
|
||||
#include <sharedPtr.h>
|
||||
|
||||
namespace epics { namespace pvAccess {
|
||||
|
||||
class Transport;
|
||||
//TODO if unordered map is used instead of map we can use sockAddrAreIdentical routine from osiSock.h
|
||||
class TransportRegistry {
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<TransportRegistry> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const TransportRegistry> const_shared_pointer;
|
||||
|
||||
typedef std::map<const epics::pvData::int16,Transport*> prioritiesMap_t;
|
||||
typedef std::map<const osiSockAddr*,prioritiesMap_t*,comp_osiSockAddrPtr> transportsMap_t;
|
||||
typedef std::vector<Transport*> allTransports_t;
|
||||
typedef std::vector<Transport::shared_pointer> transportVector_t;
|
||||
|
||||
class TransportRegistry {
|
||||
public:
|
||||
TransportRegistry();
|
||||
virtual ~TransportRegistry();
|
||||
TransportRegistry();
|
||||
virtual ~TransportRegistry();
|
||||
|
||||
void put(Transport* transport);
|
||||
Transport* get(const epics::pvData::String type, const osiSockAddr* address, const epics::pvData::int16 priority);
|
||||
Transport** get(const epics::pvData::String type, const osiSockAddr* address, epics::pvData::int32& size);
|
||||
Transport* remove(Transport* transport);
|
||||
void clear();
|
||||
epics::pvData::int32 numberOfActiveTransports();
|
||||
Transport** toArray(const epics::pvData::String type, epics::pvData::int32& size);
|
||||
Transport** toArray(epics::pvData::int32& size);
|
||||
void put(Transport::shared_pointer& transport);
|
||||
Transport::shared_pointer get(epics::pvData::String type, const osiSockAddr* address, const epics::pvData::int16 priority);
|
||||
std::auto_ptr<transportVector_t> get(epics::pvData::String type, const osiSockAddr* address);
|
||||
Transport::shared_pointer remove(Transport::shared_pointer& transport);
|
||||
void clear();
|
||||
epics::pvData::int32 numberOfActiveTransports();
|
||||
std::auto_ptr<transportVector_t> toArray(epics::pvData::String type);
|
||||
std::auto_ptr<transportVector_t> toArray();
|
||||
|
||||
private:
|
||||
transportsMap_t _transports;
|
||||
transportsMap_t::iterator _transportsIter;
|
||||
prioritiesMap_t::iterator _prioritiesIter;
|
||||
allTransports_t _allTransports;
|
||||
allTransports_t::iterator _allTransportsIter;
|
||||
epics::pvData::Mutex _mutex;
|
||||
};
|
||||
private:
|
||||
//TODO if unordered map is used instead of map we can use sockAddrAreIdentical routine from osiSock.h
|
||||
// NOTE: pointers are used to osiSockAddr (to save memory), since it guaranteed that their reference is valid as long as Transport
|
||||
typedef std::map<const epics::pvData::int16,Transport::shared_pointer> prioritiesMap_t;
|
||||
typedef std::tr1::shared_ptr<prioritiesMap_t> prioritiesMapSharedPtr_t;
|
||||
typedef std::map<const osiSockAddr*,prioritiesMapSharedPtr_t,comp_osiSockAddrPtr> transportsMap_t;
|
||||
|
||||
transportsMap_t _transports;
|
||||
int32 _transportCount;
|
||||
epics::pvData::Mutex _mutex;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
TOP = ..
|
||||
include $(TOP)/configure/CONFIG
|
||||
DIRS += utils
|
||||
DIRS += client
|
||||
#DIRS += client
|
||||
DIRS += remote
|
||||
include $(TOP)/configure/RULES_DIRS
|
||||
|
||||
@@ -294,7 +294,7 @@ class MockMonitor : public Monitor, public MonitorElement
|
||||
m_changedBitSet->set(0);
|
||||
|
||||
// TODO pvRequest
|
||||
m_monitorRequester->monitorConnect(Status::OK, this, const_cast<Structure*>(m_pvStructure->getStructure()));
|
||||
m_monitorRequester->monitorConnect(Status::OK, this, m_pvStructure->getStructure());
|
||||
}
|
||||
|
||||
virtual Status start()
|
||||
|
||||
@@ -16,145 +16,174 @@
|
||||
using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
|
||||
|
||||
class RequesterImpl : public Requester {
|
||||
public:
|
||||
|
||||
virtual String getRequesterName()
|
||||
{
|
||||
return "RequesterImpl";
|
||||
};
|
||||
|
||||
virtual void message(String message,MessageType messageType)
|
||||
{
|
||||
std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void testCreateRequest() {
|
||||
printf("testCreateRequest... ");
|
||||
printf("testCreateRequest... ");
|
||||
|
||||
RequesterImpl requester;
|
||||
String out;
|
||||
String out;
|
||||
String request = "";
|
||||
PVStructure* pvRequest = getCreateRequest()->createRequest(request,&requester);
|
||||
assert(pvRequest);
|
||||
out.clear(); pvRequest->toString(&out); std::cout << out << std::endl;
|
||||
delete pvRequest;
|
||||
std::tr1::shared_ptr<PVStructure> pvRequest(getCreateRequest()->createRequest(request));
|
||||
assert(pvRequest);
|
||||
out.clear(); pvRequest->toString(&out); std::cout << out << std::endl;
|
||||
|
||||
request = "alarm,timeStamp,power.value";
|
||||
pvRequest = getCreateRequest()->createRequest(request,&requester);
|
||||
assert(pvRequest);
|
||||
out.clear(); pvRequest->toString(&out); std::cout << out << std::endl;
|
||||
delete pvRequest;
|
||||
request = "alarm,timeStamp,power.value";
|
||||
pvRequest = getCreateRequest()->createRequest(request);
|
||||
assert(pvRequest);
|
||||
out.clear(); pvRequest->toString(&out); std::cout << out << std::endl;
|
||||
|
||||
request = "record[process=true]field(alarm,timeStamp,power.value)";
|
||||
pvRequest = getCreateRequest()->createRequest(request,&requester);
|
||||
assert(pvRequest);
|
||||
out.clear(); pvRequest->toString(&out); std::cout << out << std::endl;
|
||||
delete pvRequest;
|
||||
|
||||
request = "record[process=true]field(alarm,timeStamp[algorithm=onChange,causeMonitor=false],power{power.value,power.alarm})";
|
||||
pvRequest = getCreateRequest()->createRequest(request,&requester);
|
||||
assert(pvRequest);
|
||||
out.clear(); pvRequest->toString(&out); std::cout << out << std::endl;
|
||||
delete pvRequest;
|
||||
request = "record[process=true]field(alarm,timeStamp,power.value)";
|
||||
pvRequest = getCreateRequest()->createRequest(request);
|
||||
assert(pvRequest);
|
||||
out.clear(); pvRequest->toString(&out); std::cout << out << std::endl;
|
||||
|
||||
request = "record[process=true,xxx=yyy]field(alarm,timeStamp[shareData=true],power.value)";
|
||||
pvRequest = getCreateRequest()->createRequest(request,&requester);
|
||||
assert(pvRequest);
|
||||
out.clear(); pvRequest->toString(&out); std::cout << out << std::endl;
|
||||
delete pvRequest;
|
||||
request = "record[process=true]field(alarm,timeStamp[algorithm=onChange,causeMonitor=false],power{power.value,power.alarm})";
|
||||
pvRequest = getCreateRequest()->createRequest(request);
|
||||
assert(pvRequest);
|
||||
out.clear(); pvRequest->toString(&out); std::cout << out << std::endl;
|
||||
|
||||
request = String("record[process=true,xxx=yyy]")
|
||||
+ "putField(power.value)"
|
||||
+ "getField(alarm,timeStamp,power{power.value,power.alarm},"
|
||||
+ "current{current.value,current.alarm},voltage{voltage.value,voltage.alarm})";
|
||||
pvRequest = getCreateRequest()->createRequest(request,&requester);
|
||||
assert(pvRequest);
|
||||
out.clear(); pvRequest->toString(&out); std::cout << out << std::endl;
|
||||
delete pvRequest;
|
||||
request = "record[process=true,xxx=yyy]field(alarm,timeStamp[shareData=true],power.value)";
|
||||
pvRequest = getCreateRequest()->createRequest(request);
|
||||
assert(pvRequest);
|
||||
out.clear(); pvRequest->toString(&out); std::cout << out << std::endl;
|
||||
|
||||
request = String("record[process=true,xxx=yyy]")
|
||||
+ "putField(power.value)"
|
||||
+ "getField(alarm,timeStamp,power{power.value,power.alarm},"
|
||||
+ "current{current.value,current.alarm},voltage{voltage.value,voltage.alarm},"
|
||||
+ "ps0{"
|
||||
+ "ps0.alarm,ps0.timeStamp,power{ps0.power.value,ps0.power.alarm},"
|
||||
+ "current{ps0.current.value,ps0.current.alarm},voltage{ps0.voltage.value,ps0.voltage.alarm}},"
|
||||
+ "ps1{"
|
||||
+ "ps1.alarm,ps1.timeStamp,power{ps1.power.value,ps1.power.alarm},"
|
||||
+ "current{ps1.current.value,ps1.current.alarm},voltage{ps1.voltage.value,ps1.voltage.alarm}"
|
||||
+ "})";
|
||||
pvRequest = getCreateRequest()->createRequest(request,&requester);
|
||||
assert(pvRequest);
|
||||
out.clear(); pvRequest->toString(&out); std::cout << out << std::endl;
|
||||
delete pvRequest;
|
||||
request = String("record[process=true,xxx=yyy]")
|
||||
+ "putField(power.value)"
|
||||
+ "getField(alarm,timeStamp,power{power.value,power.alarm},"
|
||||
+ "current{current.value,current.alarm},voltage{voltage.value,voltage.alarm})";
|
||||
pvRequest = getCreateRequest()->createRequest(request);
|
||||
assert(pvRequest);
|
||||
out.clear(); pvRequest->toString(&out); std::cout << out << std::endl;
|
||||
|
||||
request = "a{b{c{d}}}";
|
||||
pvRequest = getCreateRequest()->createRequest(request,&requester);
|
||||
assert(pvRequest);
|
||||
out.clear(); pvRequest->toString(&out); std::cout << out << std::endl;
|
||||
delete pvRequest;
|
||||
request = String("record[process=true,xxx=yyy]")
|
||||
+ "putField(power.value)"
|
||||
+ "getField(alarm,timeStamp,power{power.value,power.alarm},"
|
||||
+ "current{current.value,current.alarm},voltage{voltage.value,voltage.alarm},"
|
||||
+ "ps0{"
|
||||
+ "ps0.alarm,ps0.timeStamp,power{ps0.power.value,ps0.power.alarm},"
|
||||
+ "current{ps0.current.value,ps0.current.alarm},voltage{ps0.voltage.value,ps0.voltage.alarm}},"
|
||||
+ "ps1{"
|
||||
+ "ps1.alarm,ps1.timeStamp,power{ps1.power.value,ps1.power.alarm},"
|
||||
+ "current{ps1.current.value,ps1.current.alarm},voltage{ps1.voltage.value,ps1.voltage.alarm}"
|
||||
+ "})";
|
||||
pvRequest = getCreateRequest()->createRequest(request);
|
||||
assert(pvRequest);
|
||||
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 << std::endl << "Error Expected for next call!!" << std::endl;
|
||||
pvRequest = getCreateRequest()->createRequest(request,&requester);
|
||||
assert(pvRequest==0);
|
||||
|
||||
request = String("record[process=true,xxx=yyy]")
|
||||
+ "putField(power.value)"
|
||||
+ "getField(alarm,timeStamp,power{power.value,power.alarm},"
|
||||
+ "current{current.value,current.alarm},voltage{voltage.value,voltage.alarm},"
|
||||
+ "ps0{"
|
||||
+ "ps0.alarm,ps0.timeStamp,power{ps0.power.value,ps0.power.alarm},"
|
||||
+ "current{ps0.current.value,ps0.current.alarm},voltage{ps0.voltage.value,ps0.voltage.alarm}},"
|
||||
+ "ps1{"
|
||||
+ "ps1.alarm,ps1.timeStamp,power{ps1.power.value,ps1.power.alarm},"
|
||||
+ "current{ps1.current.value,ps1.current.alarm},voltage{ps1.voltage.value,ps1.voltage.alarm}"
|
||||
+ ")";
|
||||
std::cout << std::endl << "Error Expected for next call!!" << std::endl;
|
||||
pvRequest = getCreateRequest()->createRequest(request,&requester);
|
||||
assert(pvRequest==0);
|
||||
request = "a{b{c{d}}}";
|
||||
pvRequest = getCreateRequest()->createRequest(request);
|
||||
assert(pvRequest);
|
||||
out.clear(); pvRequest->toString(&out); std::cout << out << std::endl;
|
||||
|
||||
request = "record[process=true,power.value";
|
||||
std::cout << std::endl << "Error Expected for next call!!" << std::endl;
|
||||
pvRequest = getCreateRequest()->createRequest(request,&requester);
|
||||
assert(pvRequest==0);
|
||||
|
||||
request = "field(power.value";
|
||||
std::cout << std::endl << "Error Expected for next call!!" << std::endl;
|
||||
pvRequest = getCreateRequest()->createRequest(request,&requester);
|
||||
assert(pvRequest==0);
|
||||
|
||||
request = "putField(power.value";
|
||||
std::cout << std::endl << "Error Expected for next call!!" << std::endl;
|
||||
pvRequest = getCreateRequest()->createRequest(request,&requester);
|
||||
assert(pvRequest==0);
|
||||
request = "record[process=true,xxx=yyy]field(alarm,timeStamp[shareData=true],power.value";
|
||||
std::cout << std::endl << "Error Expected for next call!!" << std::endl;
|
||||
try
|
||||
{
|
||||
pvRequest = getCreateRequest()->createRequest(request);
|
||||
assert(false);
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
|
||||
request = "getField(power.value";
|
||||
std::cout << std::endl << "Error Expected for next call!!" << std::endl;
|
||||
pvRequest = getCreateRequest()->createRequest(request,&requester);
|
||||
assert(pvRequest==0);
|
||||
request = String("record[process=true,xxx=yyy]")
|
||||
+ "putField(power.value)"
|
||||
+ "getField(alarm,timeStamp,power{power.value,power.alarm},"
|
||||
+ "current{current.value,current.alarm},voltage{voltage.value,voltage.alarm},"
|
||||
+ "ps0{"
|
||||
+ "ps0.alarm,ps0.timeStamp,power{ps0.power.value,ps0.power.alarm},"
|
||||
+ "current{ps0.current.value,ps0.current.alarm},voltage{ps0.voltage.value,ps0.voltage.alarm}},"
|
||||
+ "ps1{"
|
||||
+ "ps1.alarm,ps1.timeStamp,power{ps1.power.value,ps1.power.alarm},"
|
||||
+ "current{ps1.current.value,ps1.current.alarm},voltage{ps1.voltage.value,ps1.voltage.alarm}"
|
||||
+ ")";
|
||||
std::cout << std::endl << "Error Expected for next call!!" << std::endl;
|
||||
try
|
||||
{
|
||||
pvRequest = getCreateRequest()->createRequest(request);
|
||||
assert(false);
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
|
||||
request = "record[process=true=power.value]";
|
||||
std::cout << std::endl << "Error Expected for next call!!" << std::endl;
|
||||
pvRequest = getCreateRequest()->createRequest(request,&requester);
|
||||
assert(pvRequest==0);
|
||||
|
||||
printf("PASSED\n");
|
||||
request = "record[process=true,power.value";
|
||||
std::cout << std::endl << "Error Expected for next call!!" << std::endl;
|
||||
try
|
||||
{
|
||||
pvRequest = getCreateRequest()->createRequest(request);
|
||||
assert(false);
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
|
||||
|
||||
request = "field(power.value";
|
||||
std::cout << std::endl << "Error Expected for next call!!" << std::endl;
|
||||
try
|
||||
{
|
||||
pvRequest = getCreateRequest()->createRequest(request);
|
||||
assert(false);
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
|
||||
|
||||
request = "putField(power.value";
|
||||
std::cout << std::endl << "Error Expected for next call!!" << std::endl;
|
||||
try
|
||||
{
|
||||
pvRequest = getCreateRequest()->createRequest(request);
|
||||
assert(false);
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
|
||||
|
||||
request = "getField(power.value";
|
||||
std::cout << std::endl << "Error Expected for next call!!" << std::endl;\
|
||||
try
|
||||
{
|
||||
pvRequest = getCreateRequest()->createRequest(request);
|
||||
assert(false);
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
|
||||
|
||||
request = "record[process=true=power.value]";
|
||||
std::cout << std::endl << "Error Expected for next call!!" << std::endl;
|
||||
try
|
||||
{
|
||||
pvRequest = getCreateRequest()->createRequest(request);
|
||||
assert(false);
|
||||
}
|
||||
catch(std::exception& e)
|
||||
{
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
|
||||
printf("PASSED\n");
|
||||
|
||||
}
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
testCreateRequest();
|
||||
testCreateRequest();
|
||||
|
||||
std::cout << "-----------------------------------------------------------------------" << std::endl;
|
||||
epicsExitCallAtExits();
|
||||
CDRMonitor::get().show(stdout);
|
||||
return 0;
|
||||
std::cout << "-----------------------------------------------------------------------" << std::endl;
|
||||
epicsExitCallAtExits();
|
||||
CDRMonitor::get().show(stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -14,11 +14,11 @@ PROD_HOST += testRemoteClientImpl
|
||||
testRemoteClientImpl_SRCS += testRemoteClientImpl.cpp
|
||||
testRemoteClientImpl_LIBS += pvData pvAccess Com
|
||||
|
||||
PROD_HOST += testBeaconEmitter
|
||||
#PROD_HOST += testBeaconEmitter
|
||||
testBeaconEmitter_SRCS += testBeaconEmitter.cpp
|
||||
testBeaconEmitter_LIBS += pvData pvAccess Com
|
||||
|
||||
PROD_HOST += testBeaconHandler
|
||||
#PROD_HOST += testBeaconHandler
|
||||
testBeaconHandler_SRCS += testBeaconHandler.cpp
|
||||
testBeaconHandler_LIBS += pvData pvAccess Com
|
||||
|
||||
|
||||
@@ -21,6 +21,8 @@
|
||||
#include <iostream>
|
||||
#include <cstdio>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::pvData;
|
||||
|
||||
@@ -28,48 +30,49 @@ using std::cout;
|
||||
using std::endl;
|
||||
using std::sscanf;
|
||||
|
||||
|
||||
class ContextImpl : public Context {
|
||||
public:
|
||||
ContextImpl() :
|
||||
_tr(new TransportRegistry()), _timer(new Timer("server thread",
|
||||
lowPriority)), _conf(new SystemConfigurationImpl()) {
|
||||
}
|
||||
_tr(new TransportRegistry()), _timer(new Timer("server thread",
|
||||
lowPriority)), _conf(new SystemConfigurationImpl())
|
||||
{}
|
||||
|
||||
virtual ~ContextImpl() {
|
||||
delete _tr;
|
||||
delete _timer;
|
||||
}
|
||||
virtual Timer* getTimer() {
|
||||
virtual Timer::shared_pointer getTimer() {
|
||||
return _timer;
|
||||
}
|
||||
virtual TransportRegistry* getTransportRegistry() {
|
||||
virtual std::tr1::shared_ptr<TransportRegistry> getTransportRegistry() {
|
||||
return _tr;
|
||||
}
|
||||
virtual Channel* getChannel(epics::pvAccess::pvAccessID) {
|
||||
return 0;
|
||||
virtual std::tr1::shared_ptr<Channel> getChannel(epics::pvAccess::pvAccessID) {
|
||||
return std::tr1::shared_ptr<Channel>();
|
||||
}
|
||||
virtual Transport* getSearchTransport() {
|
||||
return 0;
|
||||
virtual Transport::shared_pointer getSearchTransport() {
|
||||
return Transport::shared_pointer();
|
||||
}
|
||||
virtual Configuration* getConfiguration() {
|
||||
virtual Configuration::shared_pointer getConfiguration() {
|
||||
return _conf;
|
||||
}
|
||||
virtual void acquire() {}
|
||||
virtual void release() {}
|
||||
virtual void beaconAnomalyNotify() {}
|
||||
|
||||
private:
|
||||
TransportRegistry* _tr;
|
||||
Timer* _timer;
|
||||
Configuration* _conf;
|
||||
std::tr1::shared_ptr<TransportRegistry> _tr;
|
||||
Timer::shared_pointer _timer;
|
||||
Configuration::shared_pointer _conf;
|
||||
};
|
||||
|
||||
class DummyResponseHandler : public ResponseHandler {
|
||||
public:
|
||||
DummyResponseHandler(Context* ctx) :
|
||||
DummyResponseHandler() :
|
||||
ResponseHandler() {
|
||||
}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport* transport, int8 version, int8 command, int payloadSize,
|
||||
Transport::shared_pointer& transport, int8 version, int8 command, int payloadSize,
|
||||
ByteBuffer* payloadBuffer) {
|
||||
|
||||
if(command==CMD_CONNECTION_VALIDATION) transport->verified();
|
||||
@@ -85,7 +88,7 @@ public:
|
||||
virtual void transportUnresponsive() {
|
||||
errlogSevPrintf(errlogInfo, "unresponsive");
|
||||
}
|
||||
virtual void transportResponsive(Transport* transport) {
|
||||
virtual void transportResponsive(Transport::shared_pointer& transport) {
|
||||
errlogSevPrintf(errlogInfo, "responsive");
|
||||
}
|
||||
virtual void transportChanged() {
|
||||
@@ -96,6 +99,7 @@ public:
|
||||
}
|
||||
virtual void acquire() {};
|
||||
virtual void release() {};
|
||||
virtual pvAccessID getID() {return 0;};
|
||||
};
|
||||
|
||||
class DummyTransportSender : public TransportSender {
|
||||
@@ -129,32 +133,31 @@ private:
|
||||
};
|
||||
|
||||
void testBlockingTCPSender() {
|
||||
ContextImpl ctx;
|
||||
BlockingTCPConnector connector(&ctx, 1024, 1.0);
|
||||
Context::shared_pointer ctx(new ContextImpl());
|
||||
BlockingTCPConnector connector(ctx, 1024, 1.0);
|
||||
|
||||
DummyTransportClient dtc;
|
||||
DummyTransportSender dts;
|
||||
DummyResponseHandler drh(&ctx);
|
||||
TransportClient::shared_pointer dtc(new DummyTransportClient());
|
||||
TransportSender::shared_pointer dts(new DummyTransportSender());
|
||||
std::auto_ptr<ResponseHandler> drh(new DummyResponseHandler());
|
||||
|
||||
osiSockAddr srvAddr;
|
||||
|
||||
//srvAddr.ia.sin_family = AF_INET;
|
||||
if(aToIPAddr("192.168.71.132", CA_SERVER_PORT, &srvAddr.ia)<0) {
|
||||
if(aToIPAddr("localhost", CA_SERVER_PORT, &srvAddr.ia)<0) {
|
||||
cout<<"error in aToIPAddr(...)"<<endl;
|
||||
return;
|
||||
}
|
||||
|
||||
Transport* transport=NULL;
|
||||
try {
|
||||
transport = connector.connect(&dtc, &drh, srvAddr,
|
||||
CA_MAGIC_AND_VERSION, CA_DEFAULT_PRIORITY);
|
||||
Transport::shared_pointer transport(connector.connect(dtc, drh, srvAddr,
|
||||
CA_MAGIC_AND_VERSION, CA_DEFAULT_PRIORITY));
|
||||
|
||||
cout<<"Sending 10 messages..."<<endl;
|
||||
|
||||
for(int i = 0; i<10; i++) {
|
||||
cout<<" Message: "<<i+1<<endl;
|
||||
if(!transport->isClosed())
|
||||
transport->enqueueSendRequest(&dts);
|
||||
transport->enqueueSendRequest(dts);
|
||||
else
|
||||
break;
|
||||
sleep(1);
|
||||
@@ -163,7 +166,7 @@ void testBlockingTCPSender() {
|
||||
cout<<e.what()<<endl;
|
||||
}
|
||||
|
||||
delete transport;
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
@@ -25,29 +25,41 @@ public:
|
||||
_tr(new TransportRegistry()),
|
||||
_timer(new Timer("server thread", lowPriority)),
|
||||
_conf(new SystemConfigurationImpl()) {}
|
||||
virtual ~ContextImpl() {
|
||||
delete _tr;
|
||||
delete _timer;
|
||||
}
|
||||
virtual Timer* getTimer() { return _timer; }
|
||||
virtual TransportRegistry* getTransportRegistry() { return _tr; }
|
||||
virtual Channel* getChannel(epics::pvAccess::pvAccessID) { return 0; }
|
||||
virtual Transport* getSearchTransport() { return 0; }
|
||||
virtual Configuration* getConfiguration() { return _conf; }
|
||||
Timer::shared_pointer getTimer() { return _timer; }
|
||||
std::tr1::shared_ptr<TransportRegistry> getTransportRegistry() { return _tr; }
|
||||
Channel::shared_pointer getChannel(epics::pvAccess::pvAccessID) { return Channel::shared_pointer(); }
|
||||
Transport::shared_pointer getSearchTransport() { return Transport::shared_pointer(); }
|
||||
Configuration::shared_pointer getConfiguration() { return _conf; }
|
||||
virtual void acquire() {}
|
||||
virtual void release() {}
|
||||
|
||||
private:
|
||||
TransportRegistry* _tr;
|
||||
Timer* _timer;
|
||||
Configuration* _conf;
|
||||
std::tr1::shared_ptr<TransportRegistry> _tr;
|
||||
Timer::shared_pointer _timer;
|
||||
Configuration::shared_pointer _conf;
|
||||
};
|
||||
|
||||
void testServerConnections() {
|
||||
ContextImpl ctx;
|
||||
class DummyResponseHandler : public ResponseHandler {
|
||||
public:
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport::shared_pointer& transport, int8 version, int8 command, int payloadSize,
|
||||
ByteBuffer* payloadBuffer) {
|
||||
cout << "DummyResponseHandler::handleResponse" << endl;
|
||||
}
|
||||
};
|
||||
|
||||
BlockingTCPAcceptor* srv = new BlockingTCPAcceptor(&ctx, CA_SERVER_PORT,
|
||||
1024);
|
||||
class DummyResponseHandlerFactory : public ResponseHandlerFactory
|
||||
{
|
||||
public:
|
||||
std::auto_ptr<ResponseHandler> createResponseHandler() {return std::auto_ptr<ResponseHandler>(new DummyResponseHandler());};
|
||||
};
|
||||
|
||||
|
||||
void testServerConnections() {
|
||||
Context::shared_pointer ctx(new ContextImpl());
|
||||
ResponseHandlerFactory::shared_pointer rhf(new DummyResponseHandlerFactory());
|
||||
|
||||
BlockingTCPAcceptor* srv = new BlockingTCPAcceptor(ctx, rhf, CA_SERVER_PORT, 1024);
|
||||
|
||||
cout<<"Press any key to stop the server...";
|
||||
cin.peek();
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::pvData;
|
||||
using std::tr1::static_pointer_cast;
|
||||
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
@@ -30,28 +31,28 @@ static osiSockAddr sendTo;
|
||||
|
||||
class ContextImpl : public Context {
|
||||
public:
|
||||
ContextImpl()
|
||||
{}
|
||||
ContextImpl() {}
|
||||
|
||||
virtual ~ContextImpl() {
|
||||
}
|
||||
virtual Timer* getTimer() {
|
||||
return 0;
|
||||
virtual Timer::shared_pointer getTimer() {
|
||||
return Timer::shared_pointer();
|
||||
}
|
||||
virtual TransportRegistry* getTransportRegistry() {
|
||||
return 0;
|
||||
virtual std::tr1::shared_ptr<TransportRegistry> getTransportRegistry() {
|
||||
return std::tr1::shared_ptr<TransportRegistry>();
|
||||
}
|
||||
virtual Channel* getChannel(epics::pvAccess::pvAccessID) {
|
||||
return 0;
|
||||
virtual std::tr1::shared_ptr<Channel> getChannel(epics::pvAccess::pvAccessID) {
|
||||
return std::tr1::shared_ptr<Channel>();
|
||||
}
|
||||
virtual Transport* getSearchTransport() {
|
||||
return 0;
|
||||
virtual Transport::shared_pointer getSearchTransport() {
|
||||
return Transport::shared_pointer();
|
||||
}
|
||||
virtual Configuration* getConfiguration() {
|
||||
return 0;
|
||||
virtual Configuration::shared_pointer getConfiguration() {
|
||||
return Configuration::shared_pointer();
|
||||
}
|
||||
virtual void acquire() {}
|
||||
virtual void release() {}
|
||||
virtual void beaconAnomalyNotify() {}
|
||||
};
|
||||
|
||||
class DummyResponseHandler : public ResponseHandler {
|
||||
@@ -62,13 +63,16 @@ public:
|
||||
virtual ~DummyResponseHandler() {}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport* transport, int8 version, int8 command, int payloadSize,
|
||||
Transport::shared_pointer&, int8 version, int8 command, int payloadSize,
|
||||
ByteBuffer* payloadBuffer) {
|
||||
}
|
||||
};
|
||||
|
||||
class DummyTransportSender : public TransportSender {
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<DummyTransportSender> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const DummyTransportSender> const_pointer;
|
||||
|
||||
DummyTransportSender() {
|
||||
for(int i = 0; i<20; i++)
|
||||
data[i] = (char)(i+1);
|
||||
@@ -102,8 +106,9 @@ void testBlockingUDPSender() {
|
||||
BlockingUDPConnector connector(false, true);
|
||||
ContextImpl ctx;
|
||||
|
||||
DummyTransportSender dts;
|
||||
DummyResponseHandler drh(&ctx);
|
||||
|
||||
auto_ptr<ResponseHandler> drh(new DummyResponseHandler(&ctx));
|
||||
TransportSender::shared_pointer dts(new DummyTransportSender());
|
||||
|
||||
osiSockAddr bindAddr;
|
||||
|
||||
@@ -111,7 +116,8 @@ void testBlockingUDPSender() {
|
||||
bindAddr.ia.sin_port = htons(65001);
|
||||
bindAddr.ia.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
Transport* transport = connector.connect(NULL, &drh, bindAddr, 1, 50);
|
||||
TransportClient::shared_pointer nullPointer;
|
||||
Transport::shared_pointer transport(connector.connect(nullPointer, drh, bindAddr, 1, 50));
|
||||
|
||||
// SRV_IP defined at the top of the this file
|
||||
if(aToIPAddr(SRV_IP, 65000, &sendTo.ia)<0) {
|
||||
@@ -121,14 +127,12 @@ void testBlockingUDPSender() {
|
||||
|
||||
cout<<"Sending 10 packets..."<<endl;
|
||||
|
||||
|
||||
for(int i = 0; i<10; i++) {
|
||||
cout<<" Packet: "<<i+1<<endl;
|
||||
transport->enqueueSendRequest(&dts);
|
||||
transport->enqueueSendRequest(dts);
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
delete transport;
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
@@ -20,6 +20,7 @@ using std::cout;
|
||||
using std::endl;
|
||||
using std::hex;
|
||||
using std::dec;
|
||||
using std::tr1::static_pointer_cast;
|
||||
|
||||
class ContextImpl : public Context {
|
||||
public:
|
||||
@@ -27,23 +28,24 @@ public:
|
||||
|
||||
virtual ~ContextImpl() {
|
||||
}
|
||||
virtual Timer* getTimer() {
|
||||
return 0;
|
||||
virtual Timer::shared_pointer getTimer() {
|
||||
return Timer::shared_pointer();
|
||||
}
|
||||
virtual TransportRegistry* getTransportRegistry() {
|
||||
return 0;
|
||||
virtual std::tr1::shared_ptr<TransportRegistry> getTransportRegistry() {
|
||||
return std::tr1::shared_ptr<TransportRegistry>();
|
||||
}
|
||||
virtual Channel* getChannel(epics::pvAccess::pvAccessID) {
|
||||
return 0;
|
||||
virtual std::tr1::shared_ptr<Channel> getChannel(epics::pvAccess::pvAccessID) {
|
||||
return std::tr1::shared_ptr<Channel>();
|
||||
}
|
||||
virtual Transport* getSearchTransport() {
|
||||
return 0;
|
||||
virtual Transport::shared_pointer getSearchTransport() {
|
||||
return Transport::shared_pointer();
|
||||
}
|
||||
virtual Configuration* getConfiguration() {
|
||||
return 0;
|
||||
virtual Configuration::shared_pointer getConfiguration() {
|
||||
return Configuration::shared_pointer();
|
||||
}
|
||||
virtual void acquire() {}
|
||||
virtual void release() {}
|
||||
virtual void beaconAnomalyNotify() {}
|
||||
};
|
||||
|
||||
class DummyResponseHandler : public ResponseHandler {
|
||||
@@ -59,14 +61,14 @@ public:
|
||||
}
|
||||
|
||||
virtual void handleResponse(osiSockAddr* responseFrom,
|
||||
Transport* transport, int8 version, int8 command, int payloadSize,
|
||||
Transport::shared_pointer&, int8 version, int8 command, int payloadSize,
|
||||
ByteBuffer* payloadBuffer);
|
||||
private:
|
||||
int packets;
|
||||
};
|
||||
|
||||
void DummyResponseHandler::handleResponse(osiSockAddr* responseFrom,
|
||||
Transport* transport, int8 version, int8 command, int payloadSize,
|
||||
Transport::shared_pointer&, int8 version, int8 command, int payloadSize,
|
||||
ByteBuffer* payloadBuffer) {
|
||||
std::ostringstream os;
|
||||
|
||||
@@ -100,7 +102,8 @@ void testBlockingUDPConnector() {
|
||||
BlockingUDPConnector connector(false, true);
|
||||
ContextImpl ctx;
|
||||
|
||||
DummyResponseHandler drh(&ctx);
|
||||
DummyResponseHandler* drh = new DummyResponseHandler(&ctx);
|
||||
auto_ptr<ResponseHandler> rh(static_cast<ResponseHandler*>(drh));
|
||||
|
||||
osiSockAddr bindAddr;
|
||||
|
||||
@@ -108,17 +111,17 @@ void testBlockingUDPConnector() {
|
||||
bindAddr.ia.sin_port = htons(65000);
|
||||
bindAddr.ia.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
Transport* transport = connector.connect(NULL, &drh, bindAddr, 1, 50);
|
||||
TransportClient::shared_pointer nullPointer;
|
||||
Transport::shared_pointer transport(connector.connect(nullPointer,rh, bindAddr, 1, 50));
|
||||
|
||||
((BlockingUDPTransport*)transport)->start();
|
||||
static_pointer_cast<BlockingUDPTransport>(transport)->start();
|
||||
|
||||
cout<<"Waiting for 10 packets..."<<endl;
|
||||
|
||||
while(drh.getPackets()<10) {
|
||||
//TODO drh can be deleted in connector!
|
||||
while(drh->getPackets()<10) {
|
||||
sleep(1);
|
||||
}
|
||||
|
||||
delete transport;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
@@ -9,346 +9,103 @@ using namespace epics::pvData;
|
||||
using namespace epics::pvAccess;
|
||||
|
||||
//TODO this will be deleted
|
||||
class ChannelImpl;
|
||||
|
||||
class ContextImpl : public Context
|
||||
|
||||
{
|
||||
|
||||
private:
|
||||
|
||||
Timer* _timer;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
|
||||
ContextImpl()
|
||||
|
||||
{
|
||||
|
||||
_timer = new Timer("krneki",lowPriority);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
virtual Version* getVersion() {
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
virtual ChannelProvider* getProvider() {
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
Timer* getTimer()
|
||||
|
||||
{
|
||||
|
||||
return _timer;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
virtual void initialize() {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
virtual void printInfo() {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
virtual void printInfo(epics::pvData::StringBuilder out) {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
virtual void destroy()
|
||||
|
||||
{
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
virtual void dispose()
|
||||
|
||||
{
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
BlockingUDPTransport* getSearchTransport()
|
||||
|
||||
{
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* Searches for a channel with given channel ID.
|
||||
|
||||
* @param channelID CID.
|
||||
|
||||
* @return channel with given CID, <code></code> if non-existent.
|
||||
|
||||
*/
|
||||
|
||||
Channel* getChannel(pvAccessID channelID)
|
||||
|
||||
{
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
Configuration* getConfiguration() {return NULL;}
|
||||
|
||||
TransportRegistry* getTransportRegistry() {return NULL;}
|
||||
|
||||
~ContextImpl() { delete _timer;};
|
||||
|
||||
private:
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void loadConfiguration() {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void internalInitialize() {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void initializeUDPTransport() {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void internalDestroy() {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void destroyAllChannels() {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* Check channel name.
|
||||
|
||||
*/
|
||||
|
||||
void checkChannelName(String& name) {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* Check context state and tries to establish necessary state.
|
||||
|
||||
*/
|
||||
|
||||
void checkState() {
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* Generate Client channel ID (CID).
|
||||
|
||||
* @return Client channel ID (CID).
|
||||
|
||||
*/
|
||||
|
||||
pvAccessID generateCID()
|
||||
|
||||
{
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* Free generated channel ID (CID).
|
||||
|
||||
*/
|
||||
|
||||
void freeCID(int cid)
|
||||
|
||||
{
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* Get, or create if necessary, transport of given server address.
|
||||
|
||||
* @param serverAddress required transport address
|
||||
|
||||
* @param priority process priority.
|
||||
|
||||
* @return transport for given address
|
||||
|
||||
*/
|
||||
|
||||
Transport* getTransport(TransportClient* client, osiSockAddr* serverAddress, int minorRevision, int priority)
|
||||
|
||||
{
|
||||
|
||||
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* Internal create channel.
|
||||
|
||||
*/
|
||||
|
||||
// TODO no minor version with the addresses
|
||||
|
||||
// TODO what if there is an channel with the same name, but on different host!
|
||||
|
||||
Channel* createChannelInternal(String name, ChannelRequester* requester, short priority,
|
||||
|
||||
InetAddrVector* addresses) {
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* Destroy channel.
|
||||
|
||||
* @param channel
|
||||
|
||||
* @param force
|
||||
|
||||
* @throws CAException
|
||||
|
||||
* @throws IllegalStateException
|
||||
|
||||
*/
|
||||
|
||||
void destroyChannel(ChannelImpl* channel, bool force) {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
|
||||
* Get channel search manager.
|
||||
|
||||
* @return channel search manager.
|
||||
|
||||
*/
|
||||
|
||||
ChannelSearchManager* getChannelSearchManager() {
|
||||
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
virtual void acquire() {}
|
||||
virtual void release() {}
|
||||
|
||||
};
|
||||
class ChannelImpl;
|
||||
|
||||
class ContextImpl : public Context
|
||||
{
|
||||
public:
|
||||
ContextImpl(): _timer(new Timer("krneki",lowPriority))
|
||||
{
|
||||
|
||||
}
|
||||
virtual Version* getVersion()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
virtual ChannelProvider* getProvider()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
Timer::shared_pointer getTimer()
|
||||
{
|
||||
return _timer;
|
||||
}
|
||||
virtual void initialize()
|
||||
{
|
||||
}
|
||||
virtual void printInfo()
|
||||
{
|
||||
}
|
||||
virtual void printInfo(epics::pvData::StringBuilder out)
|
||||
{
|
||||
}
|
||||
virtual void destroy()
|
||||
{
|
||||
}
|
||||
virtual void dispose()
|
||||
{
|
||||
}
|
||||
Transport::shared_pointer getSearchTransport()
|
||||
{
|
||||
return Transport::shared_pointer();
|
||||
}
|
||||
std::tr1::shared_ptr<Channel> getChannel(pvAccessID channelID)
|
||||
{
|
||||
return std::tr1::shared_ptr<Channel>();
|
||||
}
|
||||
Configuration::shared_pointer getConfiguration()
|
||||
{
|
||||
return Configuration::shared_pointer();
|
||||
}
|
||||
std::tr1::shared_ptr<TransportRegistry> getTransportRegistry()
|
||||
{
|
||||
return std::tr1::shared_ptr<TransportRegistry>();
|
||||
}
|
||||
void beaconAnomalyNotify() {};
|
||||
private:
|
||||
Timer::shared_pointer _timer;
|
||||
void loadConfiguration() { }
|
||||
void internalInitialize() { }
|
||||
void initializeUDPTransport() { }
|
||||
void internalDestroy() { }
|
||||
void destroyAllChannels() { }
|
||||
void checkChannelName(String& name) {}
|
||||
void checkState() { }
|
||||
pvAccessID generateCID()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
void freeCID(int cid)
|
||||
{
|
||||
}
|
||||
Transport* getTransport(TransportClient* client, osiSockAddr* serverAddress, int minorRevision, int priority)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
Channel* createChannelInternal(String name, ChannelRequester* requester, short priority,
|
||||
InetAddrVector* addresses)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
void destroyChannel(ChannelImpl* channel, bool force) {
|
||||
}
|
||||
ChannelSearchManager* getChannelSearchManager() {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
virtual void acquire() {}
|
||||
virtual void release() {}
|
||||
};
|
||||
|
||||
class TestSearcInstance : public BaseSearchInstance
|
||||
{
|
||||
public:
|
||||
TestSearcInstance(string channelName, pvAccessID channelID): _channelID(channelID), _channelName(channelName) {}
|
||||
pvAccessID getSearchInstanceID() { return _channelID;};
|
||||
string getSearchInstanceName() {return _channelName;};
|
||||
string getSearchInstanceName() {return _channelName;};
|
||||
void searchResponse(int8 minorRevision, osiSockAddr* serverAddress) {};
|
||||
void acquire() {};
|
||||
void release() {};
|
||||
void acquire() {};
|
||||
void release() {};
|
||||
private:
|
||||
pvAccessID _channelID;
|
||||
string _channelName;
|
||||
@@ -360,90 +117,91 @@ ChannelSearchManager* manager = new ChannelSearchManager(static_cast<Context*>(c
|
||||
TestSearcInstance** chanArray = new TestSearcInstance*[max_channels];
|
||||
|
||||
void* testWorker1(void* p)
|
||||
{
|
||||
for(int i = 0; i < 1000; i++)
|
||||
{
|
||||
for(int j = 0; j < max_channels/2; j++)
|
||||
{
|
||||
manager->unregisterChannel(chanArray[j]);
|
||||
usleep(100);
|
||||
manager->registerChannel(chanArray[j]);
|
||||
}
|
||||
}
|
||||
{
|
||||
for(int i = 0; i < 1000; i++)
|
||||
{
|
||||
for(int j = 0; j < max_channels/2; j++)
|
||||
{
|
||||
manager->unregisterChannel(chanArray[j]);
|
||||
usleep(100);
|
||||
manager->registerChannel(chanArray[j]);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void* testWorker2(void* p)
|
||||
{
|
||||
for(int i = 0; i < 1000; i++)
|
||||
{
|
||||
for(int j = max_channels/2; j < max_channels; j++)
|
||||
{
|
||||
manager->unregisterChannel(chanArray[j]);
|
||||
usleep(100);
|
||||
manager->registerChannel(chanArray[j]);
|
||||
manager->beaconAnomalyNotify();
|
||||
}
|
||||
}
|
||||
{
|
||||
for(int i = 0; i < 1000; i++)
|
||||
{
|
||||
for(int j = max_channels/2; j < max_channels; j++)
|
||||
{
|
||||
manager->unregisterChannel(chanArray[j]);
|
||||
usleep(100);
|
||||
manager->registerChannel(chanArray[j]);
|
||||
manager->beaconAnomalyNotify();
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
pthread_t _worker1Id;
|
||||
pthread_t _worker2Id;
|
||||
pthread_t _worker1Id;
|
||||
pthread_t _worker2Id;
|
||||
|
||||
ostringstream obuffer;
|
||||
for(int i = 0; i < max_channels; i++)
|
||||
{
|
||||
obuffer.clear();
|
||||
obuffer.str("");
|
||||
obuffer << i;
|
||||
string name = "chan" + obuffer.str();
|
||||
chanArray[i] = new TestSearcInstance(name.c_str(), i);
|
||||
manager->registerChannel(chanArray[i]);
|
||||
}
|
||||
ostringstream obuffer;
|
||||
for(int i = 0; i < max_channels; i++)
|
||||
{
|
||||
obuffer.clear();
|
||||
obuffer.str("");
|
||||
obuffer << i;
|
||||
string name = "chan" + obuffer.str();
|
||||
chanArray[i] = new TestSearcInstance(name.c_str(), i);
|
||||
manager->registerChannel(chanArray[i]);
|
||||
}
|
||||
|
||||
//create two threads
|
||||
int32 retval = pthread_create(&_worker1Id, NULL, testWorker1, NULL);
|
||||
if(retval != 0)
|
||||
{
|
||||
assert(true);
|
||||
}
|
||||
//create two threads
|
||||
int32 retval = pthread_create(&_worker1Id, NULL, testWorker1, NULL);
|
||||
if(retval != 0)
|
||||
{
|
||||
assert(true);
|
||||
}
|
||||
|
||||
retval = pthread_create(&_worker2Id, NULL, testWorker2, NULL);
|
||||
if(retval != 0)
|
||||
{
|
||||
assert(true);
|
||||
}
|
||||
retval = pthread_create(&_worker2Id, NULL, testWorker2, NULL);
|
||||
if(retval != 0)
|
||||
{
|
||||
assert(true);
|
||||
}
|
||||
|
||||
retval = pthread_join(_worker1Id, NULL);
|
||||
if(retval != 0)
|
||||
{
|
||||
assert(true);
|
||||
}
|
||||
retval = pthread_join(_worker1Id, NULL);
|
||||
if(retval != 0)
|
||||
{
|
||||
assert(true);
|
||||
}
|
||||
|
||||
retval = pthread_join(_worker2Id, NULL);
|
||||
if(retval != 0)
|
||||
{
|
||||
assert(true);
|
||||
}
|
||||
retval = pthread_join(_worker2Id, NULL);
|
||||
if(retval != 0)
|
||||
{
|
||||
assert(true);
|
||||
}
|
||||
|
||||
manager->cancel();
|
||||
manager->cancel();
|
||||
|
||||
context->destroy();
|
||||
epicsExitCallAtExits();
|
||||
CDRMonitor::get().show(stdout);
|
||||
|
||||
for(int i = 0; i < max_channels; i++)
|
||||
{
|
||||
if(chanArray[i]) delete chanArray[i];
|
||||
}
|
||||
if(chanArray) delete [] chanArray;
|
||||
if(manager) delete manager;
|
||||
if(context) delete context;
|
||||
return(0);
|
||||
context->destroy();
|
||||
epicsExitCallAtExits();
|
||||
CDRMonitor::get().show(stdout);
|
||||
|
||||
for(int i = 0; i < max_channels; i++)
|
||||
{
|
||||
if(chanArray[i]) delete chanArray[i];
|
||||
}
|
||||
if(chanArray) delete [] chanArray;
|
||||
if(manager) delete manager;
|
||||
if(context) delete context;
|
||||
return(0);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ using namespace epics::pvAccess;
|
||||
|
||||
class ChannelFindRequesterImpl : public ChannelFindRequester
|
||||
{
|
||||
virtual void channelFindResult(const epics::pvData::Status& status,ChannelFind *channelFind,bool wasFound)
|
||||
virtual void channelFindResult(const epics::pvData::Status& status,ChannelFind::shared_pointer& channelFind,bool wasFound)
|
||||
{
|
||||
std::cout << "[ChannelFindRequesterImpl] channelFindResult("
|
||||
<< status.toString() << ", ..., " << wasFound << ")" << std::endl;
|
||||
@@ -35,13 +35,13 @@ class ChannelRequesterImpl : public ChannelRequester
|
||||
std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl;
|
||||
}
|
||||
|
||||
virtual void channelCreated(const epics::pvData::Status& status, Channel *channel)
|
||||
virtual void channelCreated(const epics::pvData::Status& status, Channel::shared_pointer& channel)
|
||||
{
|
||||
std::cout << "channelCreated(" << status.toString() << ", "
|
||||
<< (channel ? channel->getChannelName() : "(0)") << ")" << std::endl;
|
||||
}
|
||||
|
||||
virtual void channelStateChange(Channel *c, Channel::ConnectionState connectionState)
|
||||
virtual void channelStateChange(Channel::shared_pointer& c, Channel::ConnectionState connectionState)
|
||||
{
|
||||
std::cout << "channelStateChange(" << c->getChannelName() << ", " << Channel::ConnectionStateNames[connectionState] << ")" << std::endl;
|
||||
}
|
||||
@@ -59,7 +59,7 @@ class GetFieldRequesterImpl : public GetFieldRequester
|
||||
std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl;
|
||||
}
|
||||
|
||||
virtual void getDone(const epics::pvData::Status& status,epics::pvData::FieldConstPtr field)
|
||||
virtual void getDone(const epics::pvData::Status& status,epics::pvData::FieldConstPtr& field)
|
||||
{
|
||||
std::cout << "getDone(" << status.toString() << ", ";
|
||||
if (status.isSuccess() && field)
|
||||
@@ -76,15 +76,14 @@ class GetFieldRequesterImpl : public GetFieldRequester
|
||||
|
||||
class ChannelGetRequesterImpl : public ChannelGetRequester
|
||||
{
|
||||
Mutex m_mutex;
|
||||
ChannelGet *m_channelGet;
|
||||
epics::pvData::PVStructure *m_pvStructure;
|
||||
epics::pvData::BitSet *m_bitSet;
|
||||
private:
|
||||
|
||||
//ChannelGet::shared_pointer m_channelGet;
|
||||
epics::pvData::PVStructure::shared_pointer m_pvStructure;
|
||||
epics::pvData::BitSet::shared_pointer m_bitSet;
|
||||
|
||||
public:
|
||||
|
||||
ChannelGetRequesterImpl() : m_channelGet(0), m_pvStructure(0), m_bitSet(0) {}
|
||||
|
||||
virtual String getRequesterName()
|
||||
{
|
||||
return "ChannelGetRequesterImpl";
|
||||
@@ -95,8 +94,8 @@ class ChannelGetRequesterImpl : public ChannelGetRequester
|
||||
std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl;
|
||||
}
|
||||
|
||||
virtual void channelGetConnect(const epics::pvData::Status& status,ChannelGet *channelGet,
|
||||
epics::pvData::PVStructure *pvStructure,epics::pvData::BitSet *bitSet)
|
||||
virtual void channelGetConnect(const epics::pvData::Status& status,ChannelGet::shared_pointer& channelGet,
|
||||
epics::pvData::PVStructure::shared_pointer& pvStructure,epics::pvData::BitSet::shared_pointer& bitSet)
|
||||
{
|
||||
std::cout << "channelGetConnect(" << status.toString() << ")" << std::endl;
|
||||
if (status.isSuccess())
|
||||
@@ -106,17 +105,15 @@ class ChannelGetRequesterImpl : public ChannelGetRequester
|
||||
std::cout << st << std::endl;
|
||||
}
|
||||
|
||||
m_mutex.lock();
|
||||
m_channelGet = channelGet;
|
||||
//m_channelGet = channelGet;
|
||||
m_pvStructure = pvStructure;
|
||||
m_bitSet = bitSet;
|
||||
m_mutex.unlock();
|
||||
}
|
||||
|
||||
virtual void getDone(const epics::pvData::Status& status)
|
||||
{
|
||||
std::cout << "getDone(" << status.toString() << ")" << std::endl;
|
||||
Lock guard(m_mutex);
|
||||
|
||||
if (status.isSuccess())
|
||||
{
|
||||
String str;
|
||||
@@ -129,10 +126,14 @@ class ChannelGetRequesterImpl : public ChannelGetRequester
|
||||
|
||||
class ChannelPutRequesterImpl : public ChannelPutRequester
|
||||
{
|
||||
ChannelPut *m_channelPut;
|
||||
epics::pvData::PVStructure *m_pvStructure;
|
||||
epics::pvData::BitSet *m_bitSet;
|
||||
private:
|
||||
|
||||
//ChannelPut::shared_pointer m_channelPut;
|
||||
epics::pvData::PVStructure::shared_pointer m_pvStructure;
|
||||
epics::pvData::BitSet::shared_pointer m_bitSet;
|
||||
|
||||
public:
|
||||
|
||||
virtual String getRequesterName()
|
||||
{
|
||||
return "ChannelPutRequesterImpl";
|
||||
@@ -143,13 +144,12 @@ class ChannelPutRequesterImpl : public ChannelPutRequester
|
||||
std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl;
|
||||
}
|
||||
|
||||
virtual void channelPutConnect(const epics::pvData::Status& status,ChannelPut *channelPut,
|
||||
epics::pvData::PVStructure *pvStructure,epics::pvData::BitSet *bitSet)
|
||||
virtual void channelPutConnect(const epics::pvData::Status& status,ChannelPut::shared_pointer& channelPut,
|
||||
epics::pvData::PVStructure::shared_pointer& pvStructure,epics::pvData::BitSet::shared_pointer& bitSet)
|
||||
{
|
||||
std::cout << "channelPutConnect(" << status.toString() << ")" << std::endl;
|
||||
|
||||
// TODO sync
|
||||
m_channelPut = channelPut;
|
||||
//m_channelPut = channelPut;
|
||||
m_pvStructure = pvStructure;
|
||||
m_bitSet = bitSet;
|
||||
}
|
||||
@@ -182,15 +182,13 @@ class ChannelPutRequesterImpl : public ChannelPutRequester
|
||||
|
||||
class ChannelPutGetRequesterImpl : public ChannelPutGetRequester
|
||||
{
|
||||
public:
|
||||
|
||||
ChannelPutGetRequesterImpl() : m_channelPutGet(0), m_putData(0), m_getData(0) {};
|
||||
|
||||
private:
|
||||
|
||||
ChannelPutGet *m_channelPutGet;
|
||||
epics::pvData::PVStructure *m_putData;
|
||||
epics::pvData::PVStructure *m_getData;
|
||||
//ChannelPutGet::shared_pointer m_channelPutGet;
|
||||
epics::pvData::PVStructure::shared_pointer m_putData;
|
||||
epics::pvData::PVStructure::shared_pointer m_getData;
|
||||
|
||||
public:
|
||||
|
||||
virtual String getRequesterName()
|
||||
{
|
||||
@@ -202,12 +200,12 @@ class ChannelPutGetRequesterImpl : public ChannelPutGetRequester
|
||||
std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl;
|
||||
}
|
||||
|
||||
virtual void channelPutGetConnect(const epics::pvData::Status& status,ChannelPutGet *channelPutGet,
|
||||
epics::pvData::PVStructure *putData,epics::pvData::PVStructure *getData)
|
||||
virtual void channelPutGetConnect(const epics::pvData::Status& status, ChannelPutGet::shared_pointer& channelPutGet,
|
||||
epics::pvData::PVStructure::shared_pointer& putData,epics::pvData::PVStructure::shared_pointer& getData)
|
||||
{
|
||||
std::cout << "channelGetPutConnect(" << status.toString() << ")" << std::endl;
|
||||
// TODO sync
|
||||
m_channelPutGet = channelPutGet;
|
||||
|
||||
//m_channelPutGet = channelPutGet;
|
||||
m_putData = putData;
|
||||
m_getData = getData;
|
||||
|
||||
@@ -268,9 +266,9 @@ class ChannelPutGetRequesterImpl : public ChannelPutGetRequester
|
||||
|
||||
class ChannelRPCRequesterImpl : public ChannelRPCRequester
|
||||
{
|
||||
ChannelRPC *m_channelRPC;
|
||||
epics::pvData::PVStructure *m_pvStructure;
|
||||
epics::pvData::BitSet *m_bitSet;
|
||||
//ChannelRPC::shared_pointer m_channelRPC;
|
||||
epics::pvData::PVStructure::shared_pointer m_pvStructure;
|
||||
epics::pvData::BitSet::shared_pointer m_bitSet;
|
||||
|
||||
virtual String getRequesterName()
|
||||
{
|
||||
@@ -282,8 +280,8 @@ class ChannelRPCRequesterImpl : public ChannelRPCRequester
|
||||
std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl;
|
||||
}
|
||||
|
||||
virtual void channelRPCConnect(const epics::pvData::Status& status,ChannelRPC *channelRPC,
|
||||
epics::pvData::PVStructure *pvStructure,epics::pvData::BitSet *bitSet)
|
||||
virtual void channelRPCConnect(const epics::pvData::Status& status,ChannelRPC::shared_pointer& channelRPC,
|
||||
epics::pvData::PVStructure::shared_pointer& pvStructure,epics::pvData::BitSet::shared_pointer& bitSet)
|
||||
{
|
||||
std::cout << "channelRPCConnect(" << status.toString() << ")" << std::endl;
|
||||
if (status.isSuccess())
|
||||
@@ -293,13 +291,12 @@ class ChannelRPCRequesterImpl : public ChannelRPCRequester
|
||||
std::cout << st << std::endl;
|
||||
}
|
||||
|
||||
// TODO sync
|
||||
m_channelRPC = channelRPC;
|
||||
//m_channelRPC = channelRPC;
|
||||
m_pvStructure = pvStructure;
|
||||
m_bitSet = bitSet;
|
||||
}
|
||||
|
||||
virtual void requestDone(const epics::pvData::Status& status,epics::pvData::PVStructure *pvResponse)
|
||||
virtual void requestDone(const epics::pvData::Status& status,epics::pvData::PVStructure::shared_pointer& pvResponse)
|
||||
{
|
||||
std::cout << "requestDone(" << status.toString() << ")" << std::endl;
|
||||
if (status.isSuccess())
|
||||
@@ -314,15 +311,13 @@ class ChannelRPCRequesterImpl : public ChannelRPCRequester
|
||||
|
||||
class ChannelArrayRequesterImpl : public ChannelArrayRequester
|
||||
{
|
||||
public:
|
||||
|
||||
ChannelArrayRequesterImpl() : m_channelArray(0), m_pvArray(0) {};
|
||||
|
||||
private:
|
||||
|
||||
ChannelArray *m_channelArray;
|
||||
epics::pvData::PVArray *m_pvArray;
|
||||
//ChannelArray::shared_pointer m_channelArray;
|
||||
epics::pvData::PVArray::shared_pointer m_pvArray;
|
||||
|
||||
public:
|
||||
|
||||
virtual String getRequesterName()
|
||||
{
|
||||
return "ChannelArrayRequesterImpl";
|
||||
@@ -333,8 +328,8 @@ class ChannelArrayRequesterImpl : public ChannelArrayRequester
|
||||
std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl;
|
||||
}
|
||||
|
||||
virtual void channelArrayConnect(const epics::pvData::Status& status,ChannelArray *channelArray,
|
||||
epics::pvData::PVArray *pvArray)
|
||||
virtual void channelArrayConnect(const epics::pvData::Status& status,ChannelArray::shared_pointer& channelArray,
|
||||
epics::pvData::PVArray::shared_pointer& pvArray)
|
||||
{
|
||||
std::cout << "channelArrayConnect(" << status.toString() << ")" << std::endl;
|
||||
if (status.isSuccess())
|
||||
@@ -344,8 +339,7 @@ class ChannelArrayRequesterImpl : public ChannelArrayRequester
|
||||
std::cout << st << std::endl;
|
||||
}
|
||||
|
||||
// TODO sync
|
||||
m_channelArray = channelArray;
|
||||
//m_channelArray = channelArray;
|
||||
m_pvArray = pvArray;
|
||||
}
|
||||
|
||||
@@ -384,7 +378,7 @@ class MonitorRequesterImpl : public MonitorRequester
|
||||
std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl;
|
||||
}
|
||||
|
||||
virtual void monitorConnect(const epics::pvData::Status& status, Monitor* monitor, StructureConstPtr structure)
|
||||
virtual void monitorConnect(const epics::pvData::Status& status, Monitor::shared_pointer& monitor, StructureConstPtr& structure)
|
||||
{
|
||||
std::cout << "monitorConnect(" << status.toString() << ")" << std::endl;
|
||||
if (status.isSuccess() && structure)
|
||||
@@ -395,11 +389,11 @@ class MonitorRequesterImpl : public MonitorRequester
|
||||
}
|
||||
}
|
||||
|
||||
virtual void monitorEvent(Monitor* monitor)
|
||||
virtual void monitorEvent(Monitor::shared_pointer& monitor)
|
||||
{
|
||||
std::cout << "monitorEvent" << std::endl;
|
||||
|
||||
MonitorElement* element = monitor->poll();
|
||||
MonitorElement::shared_pointer element = monitor->poll();
|
||||
|
||||
String str("changed/overrun ");
|
||||
element->getChangedBitSet()->toString(&str);
|
||||
@@ -412,7 +406,7 @@ class MonitorRequesterImpl : public MonitorRequester
|
||||
monitor->release(element);
|
||||
}
|
||||
|
||||
virtual void unlisten(Monitor* monitor)
|
||||
virtual void unlisten(Monitor::shared_pointer& monitor)
|
||||
{
|
||||
std::cout << "unlisten" << std::endl;
|
||||
}
|
||||
@@ -421,7 +415,7 @@ class MonitorRequesterImpl : public MonitorRequester
|
||||
|
||||
class ChannelProcessRequesterImpl : public ChannelProcessRequester
|
||||
{
|
||||
ChannelProcess *m_channelProcess;
|
||||
//ChannelProcess::shared_pointer& m_channelProcess;
|
||||
|
||||
virtual String getRequesterName()
|
||||
{
|
||||
@@ -433,12 +427,11 @@ class ChannelProcessRequesterImpl : public ChannelProcessRequester
|
||||
std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl;
|
||||
}
|
||||
|
||||
virtual void channelProcessConnect(const epics::pvData::Status& status,ChannelProcess *channelProcess)
|
||||
virtual void channelProcessConnect(const epics::pvData::Status& status,ChannelProcess::shared_pointer& channelProcess)
|
||||
{
|
||||
std::cout << "channelProcessConnect(" << status.toString() << ")" << std::endl;
|
||||
|
||||
// TODO sync
|
||||
m_channelProcess = channelProcess;
|
||||
//m_channelProcess = channelProcess;
|
||||
}
|
||||
|
||||
virtual void processDone(const epics::pvData::Status& status)
|
||||
@@ -451,8 +444,10 @@ class ChannelProcessRequesterImpl : public ChannelProcessRequester
|
||||
|
||||
int main(int argc,char *argv[])
|
||||
{
|
||||
for (int i = 0; i < 10; i++) {
|
||||
{
|
||||
/*
|
||||
ClientContextImpl* context = createClientContextImpl();
|
||||
ClientContextImpl::shared_pointer context = createClientContextImpl();
|
||||
context->printInfo();
|
||||
|
||||
context->initialize();
|
||||
@@ -460,63 +455,65 @@ int main(int argc,char *argv[])
|
||||
|
||||
epicsThreadSleep ( 1.0 );
|
||||
|
||||
ChannelProvider* provider = context->getProvider();
|
||||
ChannelProvider::shared_pointer provider = context->getProvider();
|
||||
*/
|
||||
|
||||
ClientFactory::start();
|
||||
ChannelProvider* provider = getChannelAccess()->getProvider("pvAccess");
|
||||
ChannelProvider::shared_pointer provider = getChannelAccess()->getProvider("pvAccess");
|
||||
|
||||
/*
|
||||
ChannelFindRequesterImpl findRequester;
|
||||
ChannelFind* channelFind = provider->channelFind("something", &findRequester);
|
||||
ChannelFindRequester::shared_pointer findRequester(new ChannelFindRequesterImpl());
|
||||
ChannelFind::shared_pointer channelFind = provider->channelFind("something", findRequester);
|
||||
epicsThreadSleep ( 1.0 );
|
||||
channelFind->destroy();
|
||||
*/
|
||||
ChannelRequesterImpl channelRequester;
|
||||
Channel* channel = provider->createChannel("structureArrayTest", &channelRequester);
|
||||
//channelFind->destroy();
|
||||
|
||||
ChannelRequester::shared_pointer channelRequester(new ChannelRequesterImpl());
|
||||
Channel::shared_pointer channel = provider->createChannel("structureArrayTest", channelRequester);
|
||||
epicsThreadSleep ( 1.0 );
|
||||
|
||||
channel->printInfo();
|
||||
|
||||
PVStructure* pvRequest;
|
||||
|
||||
GetFieldRequesterImpl getFieldRequesterImpl;
|
||||
channel->getField(&getFieldRequesterImpl, "");
|
||||
|
||||
{
|
||||
GetFieldRequester::shared_pointer getFieldRequesterImpl(new GetFieldRequesterImpl());
|
||||
channel->getField(getFieldRequesterImpl, "");
|
||||
epicsThreadSleep ( 1.0 );
|
||||
|
||||
ChannelProcessRequesterImpl channelProcessRequester;
|
||||
ChannelProcess* channelProcess = channel->createChannelProcess(&channelProcessRequester, 0);
|
||||
}
|
||||
|
||||
{
|
||||
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 );
|
||||
channelProcess->destroy();
|
||||
epicsThreadSleep ( 1.0 );
|
||||
|
||||
ChannelGetRequesterImpl channelGetRequesterImpl;
|
||||
pvRequest = getCreateRequest()->createRequest("field()",&channelGetRequesterImpl);
|
||||
ChannelGet* channelGet = channel->createChannelGet(&channelGetRequesterImpl, pvRequest);
|
||||
}
|
||||
|
||||
{
|
||||
ChannelGetRequester::shared_pointer channelGetRequesterImpl(new ChannelGetRequesterImpl());
|
||||
PVStructure::shared_pointer pvRequest = getCreateRequest()->createRequest("field()");
|
||||
ChannelGet::shared_pointer channelGet = channel->createChannelGet(channelGetRequesterImpl, pvRequest);
|
||||
epicsThreadSleep ( 3.0 );
|
||||
channelGet->get(false);
|
||||
epicsThreadSleep ( 3.0 );
|
||||
|
||||
channelGet->destroy();
|
||||
delete pvRequest;
|
||||
|
||||
ChannelPutRequesterImpl channelPutRequesterImpl;
|
||||
pvRequest = getCreateRequest()->createRequest("field(value,timeStamp)",&channelPutRequesterImpl);
|
||||
ChannelPut* channelPut = channel->createChannelPut(&channelPutRequesterImpl, pvRequest);
|
||||
}
|
||||
|
||||
{
|
||||
ChannelPutRequester::shared_pointer channelPutRequesterImpl(new ChannelPutRequesterImpl());
|
||||
PVStructure::shared_pointer pvRequest = getCreateRequest()->createRequest("field(value,timeStamp)");
|
||||
ChannelPut::shared_pointer channelPut = channel->createChannelPut(channelPutRequesterImpl, pvRequest);
|
||||
epicsThreadSleep ( 1.0 );
|
||||
channelPut->get();
|
||||
epicsThreadSleep ( 1.0 );
|
||||
channelPut->put(false);
|
||||
epicsThreadSleep ( 1.0 );
|
||||
channelPut->destroy();
|
||||
delete pvRequest;
|
||||
}
|
||||
|
||||
ChannelPutGetRequesterImpl channelPutGetRequesterImpl;
|
||||
pvRequest = getCreateRequest()->createRequest("putField(value,timeStamp)getField(timeStamp)",&channelPutGetRequesterImpl);
|
||||
ChannelPutGet* channelPutGet = channel->createChannelPutGet(&channelPutGetRequesterImpl, pvRequest);
|
||||
{
|
||||
ChannelPutGetRequester::shared_pointer channelPutGetRequesterImpl(new ChannelPutGetRequesterImpl());
|
||||
PVStructure::shared_pointer pvRequest = getCreateRequest()->createRequest("putField(value,timeStamp)getField(timeStamp)");
|
||||
ChannelPutGet::shared_pointer channelPutGet = channel->createChannelPutGet(channelPutGetRequesterImpl, pvRequest);
|
||||
epicsThreadSleep ( 1.0 );
|
||||
channelPutGet->getGet();
|
||||
epicsThreadSleep ( 1.0 );
|
||||
@@ -525,26 +522,26 @@ int main(int argc,char *argv[])
|
||||
channelPutGet->putGet(false);
|
||||
epicsThreadSleep ( 1.0 );
|
||||
channelPutGet->destroy();
|
||||
delete pvRequest;
|
||||
}
|
||||
|
||||
|
||||
ChannelRPCRequesterImpl channelRPCRequesterImpl;
|
||||
pvRequest = getCreateRequest()->createRequest("record[]field(arguments)",&channelRPCRequesterImpl);
|
||||
ChannelRPC* channelRPC = channel->createChannelRPC(&channelRPCRequesterImpl, pvRequest);
|
||||
{
|
||||
ChannelRPCRequester::shared_pointer channelRPCRequesterImpl(new ChannelRPCRequesterImpl());
|
||||
PVStructure::shared_pointer pvRequest = getCreateRequest()->createRequest("record[]field(arguments)");
|
||||
ChannelRPC::shared_pointer channelRPC = channel->createChannelRPC(channelRPCRequesterImpl, pvRequest);
|
||||
epicsThreadSleep ( 1.0 );
|
||||
channelRPC->request(false);
|
||||
epicsThreadSleep ( 1.0 );
|
||||
channelRPC->destroy();
|
||||
delete pvRequest;
|
||||
|
||||
ChannelArrayRequesterImpl channelArrayRequesterImpl;
|
||||
//pvRequest = getCreateRequest()->createRequest("value",&channelArrayRequesterImpl);
|
||||
pvRequest = getPVDataCreate()->createPVStructure(0, "", 0);
|
||||
PVString* pvFieldName = (PVString*)getPVDataCreate()->createPVScalar(pvRequest, "field", pvString);
|
||||
}
|
||||
|
||||
{
|
||||
ChannelArrayRequester::shared_pointer channelArrayRequesterImpl(new ChannelArrayRequesterImpl());
|
||||
PVStructure::shared_pointer pvRequest(getPVDataCreate()->createPVStructure(0, "", 0));
|
||||
PVString* pvFieldName = (PVString*)getPVDataCreate()->createPVScalar(pvRequest.get(), "field", pvString);
|
||||
pvFieldName->put("value");
|
||||
pvRequest->appendPVField(pvFieldName);
|
||||
|
||||
ChannelArray* channelArray = channel->createChannelArray(&channelArrayRequesterImpl, pvRequest);
|
||||
ChannelArray::shared_pointer channelArray = channel->createChannelArray(channelArrayRequesterImpl, pvRequest);
|
||||
epicsThreadSleep ( 1.0 );
|
||||
channelArray->getArray(false,0,-1);
|
||||
epicsThreadSleep ( 1.0 );
|
||||
@@ -553,11 +550,12 @@ int main(int argc,char *argv[])
|
||||
channelArray->setLength(false,3,4);
|
||||
epicsThreadSleep ( 1.0 );
|
||||
channelArray->destroy();
|
||||
delete pvRequest;
|
||||
}
|
||||
|
||||
MonitorRequesterImpl monitorRequesterImpl;
|
||||
pvRequest = getCreateRequest()->createRequest("field()",&monitorRequesterImpl);
|
||||
Monitor* monitor = channel->createMonitor(&monitorRequesterImpl, pvRequest);
|
||||
{
|
||||
MonitorRequester::shared_pointer monitorRequesterImpl(new MonitorRequesterImpl());
|
||||
PVStructure::shared_pointer pvRequest = getCreateRequest()->createRequest("field()");
|
||||
Monitor::shared_pointer monitor = channel->createMonitor(monitorRequesterImpl, pvRequest);
|
||||
|
||||
epicsThreadSleep( 1.0 );
|
||||
|
||||
@@ -571,23 +569,26 @@ int main(int argc,char *argv[])
|
||||
|
||||
|
||||
monitor->destroy();
|
||||
delete pvRequest;
|
||||
|
||||
}
|
||||
|
||||
epicsThreadSleep ( 3.0 );
|
||||
printf("Destroying channel... \n");
|
||||
channel->destroy();
|
||||
printf("done.\n");
|
||||
|
||||
epicsThreadSleep ( 3.0 );
|
||||
|
||||
|
||||
}
|
||||
|
||||
ClientFactory::stop();
|
||||
|
||||
/*
|
||||
printf("Destroying context... \n");
|
||||
context->destroy();
|
||||
printf("done.\n");
|
||||
*/
|
||||
|
||||
epicsThreadSleep ( 1.0 );
|
||||
epicsThreadSleep ( 1.0 ); }
|
||||
std::cout << "-----------------------------------------------------------------------" << std::endl;
|
||||
epicsExitCallAtExits();
|
||||
CDRMonitor::get().show(stdout);
|
||||
|
||||
@@ -11,36 +11,33 @@
|
||||
using namespace epics::pvAccess;
|
||||
using namespace epics::pvData;
|
||||
using namespace std;
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
|
||||
|
||||
PVDATA_REFCOUNT_MONITOR_DEFINE(mockChannelProcess);
|
||||
|
||||
class MockChannelProcess : public ChannelProcess
|
||||
class MockChannelProcess :
|
||||
public ChannelProcess,
|
||||
public std::tr1::enable_shared_from_this<MockChannelProcess>
|
||||
{
|
||||
private:
|
||||
ChannelProcessRequester* m_channelProcessRequester;
|
||||
PVStructure* m_pvStructure;
|
||||
ChannelProcessRequester::shared_pointer m_channelProcessRequester;
|
||||
PVStructure::shared_pointer m_pvStructure;
|
||||
PVScalar* m_valueField;
|
||||
|
||||
private:
|
||||
~MockChannelProcess()
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_DESTRUCT(mockChannelProcess);
|
||||
}
|
||||
|
||||
public:
|
||||
MockChannelProcess(ChannelProcessRequester* channelProcessRequester, PVStructure *pvStructure, PVStructure *pvRequest) :
|
||||
protected:
|
||||
MockChannelProcess(ChannelProcessRequester::shared_pointer& channelProcessRequester, PVStructure::shared_pointer& pvStructure, PVStructure::shared_pointer& pvRequest) :
|
||||
m_channelProcessRequester(channelProcessRequester), m_pvStructure(pvStructure)
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(mockChannelProcess);
|
||||
|
||||
// TODO wrong
|
||||
ChannelProcess::shared_pointer thisPtr = static_pointer_cast<ChannelProcess>(shared_from_this());
|
||||
PVField* field = pvStructure->getSubField(String("value"));
|
||||
if (field == 0)
|
||||
{
|
||||
Status noValueFieldStatus(Status::STATUSTYPE_ERROR, "no 'value' field");
|
||||
m_channelProcessRequester->channelProcessConnect(noValueFieldStatus, this);
|
||||
|
||||
m_channelProcessRequester->channelProcessConnect(noValueFieldStatus, thisPtr);
|
||||
// NOTE client must destroy this instance...
|
||||
// do not access any fields and return ASAP
|
||||
return;
|
||||
@@ -49,19 +46,32 @@ class MockChannelProcess : public ChannelProcess
|
||||
if (field->getField()->getType() != scalar)
|
||||
{
|
||||
Status notAScalarStatus(Status::STATUSTYPE_ERROR, "'value' field not scalar type");
|
||||
m_channelProcessRequester->channelProcessConnect(notAScalarStatus, this);
|
||||
|
||||
m_channelProcessRequester->channelProcessConnect(notAScalarStatus, thisPtr);
|
||||
// NOTE client must destroy this instance….
|
||||
// do not access any fields and return ASAP
|
||||
return;
|
||||
}
|
||||
|
||||
m_valueField = static_cast<PVScalar*>(field);
|
||||
}
|
||||
|
||||
public:
|
||||
static ChannelProcess::shared_pointer create(ChannelProcessRequester::shared_pointer& channelProcessRequester, PVStructure::shared_pointer& pvStructure, PVStructure::shared_pointer& pvRequest)
|
||||
{
|
||||
ChannelProcess::shared_pointer thisPtr(new MockChannelProcess(channelProcessRequester, pvStructure, pvRequest));
|
||||
|
||||
// TODO pvRequest
|
||||
m_channelProcessRequester->channelProcessConnect(Status::OK, this);
|
||||
channelProcessRequester->channelProcessConnect(Status::OK, thisPtr);
|
||||
|
||||
return thisPtr;
|
||||
}
|
||||
|
||||
virtual ~MockChannelProcess()
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_DESTRUCT(mockChannelProcess);
|
||||
}
|
||||
|
||||
|
||||
virtual void process(bool lastRequest)
|
||||
{
|
||||
switch (m_valueField->getScalar()->getScalarType())
|
||||
@@ -143,7 +153,7 @@ class MockChannelProcess : public ChannelProcess
|
||||
|
||||
virtual void destroy()
|
||||
{
|
||||
delete this;
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
@@ -158,26 +168,32 @@ PVDATA_REFCOUNT_MONITOR_DEFINE(mockChannelGet);
|
||||
class MockChannelGet : public ChannelGet
|
||||
{
|
||||
private:
|
||||
ChannelGetRequester* m_channelGetRequester;
|
||||
PVStructure* m_pvStructure;
|
||||
BitSet* m_bitSet;
|
||||
ChannelGetRequester::shared_pointer m_channelGetRequester;
|
||||
PVStructure::shared_pointer m_pvStructure;
|
||||
BitSet::shared_pointer m_bitSet;
|
||||
bool m_first;
|
||||
|
||||
private:
|
||||
~MockChannelGet()
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_DESTRUCT(mockChannelGet);
|
||||
}
|
||||
|
||||
public:
|
||||
MockChannelGet(ChannelGetRequester* channelGetRequester, PVStructure *pvStructure, PVStructure *pvRequest) :
|
||||
protected:
|
||||
MockChannelGet(ChannelGetRequester::shared_pointer& channelGetRequester, PVStructure::shared_pointer& pvStructure, PVStructure::shared_pointer& pvRequest) :
|
||||
m_channelGetRequester(channelGetRequester), m_pvStructure(pvStructure),
|
||||
m_bitSet(new BitSet(pvStructure->getNumberFields())), m_first(true)
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(mockChannelGet);
|
||||
}
|
||||
|
||||
public:
|
||||
static ChannelGet::shared_pointer create(ChannelGetRequester::shared_pointer& channelGetRequester, PVStructure::shared_pointer& pvStructure, PVStructure::shared_pointer& pvRequest)
|
||||
{
|
||||
ChannelGet::shared_pointer thisPtr(new MockChannelGet(channelGetRequester, pvStructure, pvRequest));
|
||||
// TODO pvRequest
|
||||
m_channelGetRequester->channelGetConnect(Status::OK, this, m_pvStructure, m_bitSet);
|
||||
channelGetRequester->channelGetConnect(Status::OK, thisPtr, pvStructure, static_cast<MockChannelGet*>(thisPtr.get())->m_bitSet);
|
||||
|
||||
return thisPtr;
|
||||
}
|
||||
|
||||
virtual ~MockChannelGet()
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_DESTRUCT(mockChannelGet);
|
||||
}
|
||||
|
||||
virtual void get(bool lastRequest)
|
||||
@@ -195,8 +211,6 @@ class MockChannelGet : public ChannelGet
|
||||
|
||||
virtual void destroy()
|
||||
{
|
||||
delete m_bitSet;
|
||||
delete this;
|
||||
}
|
||||
|
||||
};
|
||||
@@ -204,36 +218,39 @@ class MockChannelGet : public ChannelGet
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
PVDATA_REFCOUNT_MONITOR_DEFINE(mockChannelPut);
|
||||
|
||||
class MockChannelPut : public ChannelPut
|
||||
{
|
||||
private:
|
||||
ChannelPutRequester* m_channelPutRequester;
|
||||
PVStructure* m_pvStructure;
|
||||
BitSet* m_bitSet;
|
||||
ChannelPutRequester::shared_pointer m_channelPutRequester;
|
||||
PVStructure::shared_pointer m_pvStructure;
|
||||
BitSet::shared_pointer m_bitSet;
|
||||
|
||||
private:
|
||||
~MockChannelPut()
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_DESTRUCT(mockChannelPut);
|
||||
}
|
||||
|
||||
public:
|
||||
MockChannelPut(ChannelPutRequester* channelPutRequester, PVStructure *pvStructure, PVStructure *pvRequest) :
|
||||
protected:
|
||||
MockChannelPut(ChannelPutRequester::shared_pointer& channelPutRequester, PVStructure::shared_pointer& pvStructure, PVStructure::shared_pointer& pvRequest) :
|
||||
m_channelPutRequester(channelPutRequester), m_pvStructure(pvStructure),
|
||||
m_bitSet(new BitSet(pvStructure->getNumberFields()))
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(mockChannelPut);
|
||||
|
||||
// TODO pvRequest
|
||||
m_channelPutRequester->channelPutConnect(Status::OK, this, m_pvStructure, m_bitSet);
|
||||
}
|
||||
|
||||
public:
|
||||
static ChannelPut::shared_pointer create(ChannelPutRequester::shared_pointer& channelPutRequester, PVStructure::shared_pointer& pvStructure, PVStructure::shared_pointer& pvRequest)
|
||||
{
|
||||
ChannelPut::shared_pointer thisPtr(new MockChannelPut(channelPutRequester, pvStructure, pvRequest));
|
||||
// TODO pvRequest
|
||||
channelPutRequester->channelPutConnect(Status::OK, thisPtr, pvStructure, static_cast<MockChannelPut*>(thisPtr.get())->m_bitSet);
|
||||
|
||||
return thisPtr;
|
||||
}
|
||||
|
||||
virtual ~MockChannelPut()
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_DESTRUCT(mockChannelPut);
|
||||
}
|
||||
|
||||
|
||||
virtual void put(bool lastRequest)
|
||||
{
|
||||
m_channelPutRequester->putDone(Status::OK);
|
||||
@@ -248,8 +265,6 @@ class MockChannelPut : public ChannelPut
|
||||
|
||||
virtual void destroy()
|
||||
{
|
||||
delete m_bitSet;
|
||||
delete this;
|
||||
}
|
||||
|
||||
};
|
||||
@@ -257,31 +272,34 @@ class MockChannelPut : public ChannelPut
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
PVDATA_REFCOUNT_MONITOR_DEFINE(mockChannelPutGet);
|
||||
|
||||
class MockChannelPutGet : public ChannelPutGet
|
||||
{
|
||||
private:
|
||||
ChannelPutGetRequester* m_channelPutGetRequester;
|
||||
PVStructure* m_pvStructure;
|
||||
ChannelPutGetRequester::shared_pointer m_channelPutGetRequester;
|
||||
PVStructure::shared_pointer m_pvStructure;
|
||||
|
||||
private:
|
||||
~MockChannelPutGet()
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_DESTRUCT(mockChannelPutGet);
|
||||
}
|
||||
|
||||
public:
|
||||
MockChannelPutGet(ChannelPutGetRequester* channelPutGetRequester, PVStructure *pvStructure, PVStructure *pvRequest) :
|
||||
protected:
|
||||
MockChannelPutGet(ChannelPutGetRequester::shared_pointer& channelPutGetRequester, PVStructure::shared_pointer& pvStructure, PVStructure::shared_pointer& pvRequest) :
|
||||
m_channelPutGetRequester(channelPutGetRequester), m_pvStructure(pvStructure)
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(mockChannelPutGet);
|
||||
}
|
||||
|
||||
public:
|
||||
static ChannelPutGet::shared_pointer create(ChannelPutGetRequester::shared_pointer& channelPutGetRequester, PVStructure::shared_pointer& pvStructure, PVStructure::shared_pointer& pvRequest)
|
||||
{
|
||||
ChannelPutGet::shared_pointer thisPtr(new MockChannelPutGet(channelPutGetRequester, pvStructure, pvRequest));
|
||||
// TODO pvRequest
|
||||
m_channelPutGetRequester->channelPutGetConnect(Status::OK, this, m_pvStructure, m_pvStructure);
|
||||
channelPutGetRequester->channelPutGetConnect(Status::OK, thisPtr, pvStructure, pvStructure);
|
||||
|
||||
return thisPtr;
|
||||
}
|
||||
|
||||
virtual ~MockChannelPutGet()
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_DESTRUCT(mockChannelPutGet);
|
||||
}
|
||||
|
||||
virtual void putGet(bool lastRequest)
|
||||
@@ -303,7 +321,6 @@ class MockChannelPutGet : public ChannelPutGet
|
||||
|
||||
virtual void destroy()
|
||||
{
|
||||
delete this;
|
||||
}
|
||||
|
||||
};
|
||||
@@ -318,25 +335,30 @@ PVDATA_REFCOUNT_MONITOR_DEFINE(mockChannelRPC);
|
||||
class MockChannelRPC : public ChannelRPC
|
||||
{
|
||||
private:
|
||||
ChannelRPCRequester* m_channelRPCRequester;
|
||||
PVStructure* m_pvStructure;
|
||||
BitSet* m_bitSet;
|
||||
ChannelRPCRequester::shared_pointer m_channelRPCRequester;
|
||||
PVStructure::shared_pointer m_pvStructure;
|
||||
BitSet::shared_pointer m_bitSet;
|
||||
|
||||
private:
|
||||
~MockChannelRPC()
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_DESTRUCT(mockChannelRPC);
|
||||
}
|
||||
|
||||
public:
|
||||
MockChannelRPC(ChannelRPCRequester* channelRPCRequester, PVStructure *pvStructure, PVStructure *pvRequest) :
|
||||
protected:
|
||||
MockChannelRPC(ChannelRPCRequester::shared_pointer& channelRPCRequester, PVStructure::shared_pointer& pvStructure, PVStructure::shared_pointer& pvRequest) :
|
||||
m_channelRPCRequester(channelRPCRequester), m_pvStructure(pvStructure),
|
||||
m_bitSet(new BitSet(pvStructure->getNumberFields()))
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(mockChannelRPC);
|
||||
}
|
||||
|
||||
public:
|
||||
static ChannelRPC::shared_pointer create(ChannelRPCRequester::shared_pointer& channelRPCRequester, PVStructure::shared_pointer& pvStructure, PVStructure::shared_pointer& pvRequest)
|
||||
{
|
||||
ChannelRPC::shared_pointer thisPtr(new MockChannelRPC(channelRPCRequester, pvStructure, pvRequest));
|
||||
// TODO pvRequest
|
||||
m_channelRPCRequester->channelRPCConnect(Status::OK, this, m_pvStructure, m_bitSet);
|
||||
channelRPCRequester->channelRPCConnect(Status::OK, thisPtr, pvStructure, static_cast<MockChannelRPC*>(thisPtr.get())->m_bitSet);
|
||||
return thisPtr;
|
||||
}
|
||||
|
||||
virtual ~MockChannelRPC()
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_DESTRUCT(mockChannelRPC);
|
||||
}
|
||||
|
||||
virtual void request(bool lastRequest)
|
||||
@@ -348,8 +370,6 @@ class MockChannelRPC : public ChannelRPC
|
||||
|
||||
virtual void destroy()
|
||||
{
|
||||
delete m_bitSet;
|
||||
delete this;
|
||||
}
|
||||
|
||||
};
|
||||
@@ -368,25 +388,31 @@ PVDATA_REFCOUNT_MONITOR_DEFINE(mockChannelArray);
|
||||
class MockChannelArray : public ChannelArray
|
||||
{
|
||||
private:
|
||||
ChannelArrayRequester* m_channelArrayRequester;
|
||||
PVArray* m_pvArray;
|
||||
ChannelArrayRequester::shared_pointer m_channelArrayRequester;
|
||||
PVArray::shared_pointer m_pvArray;
|
||||
|
||||
private:
|
||||
~MockChannelArray()
|
||||
protected:
|
||||
MockChannelArray(ChannelArrayRequester::shared_pointer& channelArrayRequester, PVStructure::shared_pointer& pvStructure, PVStructure::shared_pointer& pvRequest) :
|
||||
m_channelArrayRequester(channelArrayRequester),
|
||||
m_pvArray(getPVDataCreate()->createPVScalarArray(0, "", pvDouble))
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_DESTRUCT(mockChannelArray);
|
||||
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(mockChannelArray);
|
||||
}
|
||||
|
||||
public:
|
||||
MockChannelArray(ChannelArrayRequester* channelArrayRequester, PVStructure *pvStructure, PVStructure *pvRequest) :
|
||||
m_channelArrayRequester(channelArrayRequester)
|
||||
static ChannelArray::shared_pointer create(ChannelArrayRequester::shared_pointer& channelArrayRequester, PVStructure::shared_pointer& pvStructure, PVStructure::shared_pointer& pvRequest)
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(mockChannelArray);
|
||||
|
||||
m_pvArray = getPVDataCreate()->createPVScalarArray(0, "", pvDouble);
|
||||
ChannelArray::shared_pointer thisPtr(new MockChannelArray(channelArrayRequester, pvStructure, pvRequest));
|
||||
|
||||
// TODO pvRequest
|
||||
m_channelArrayRequester->channelArrayConnect(Status::OK, this, m_pvArray);
|
||||
channelArrayRequester->channelArrayConnect(Status::OK, thisPtr, static_cast<MockChannelArray*>(thisPtr.get())->m_pvArray);
|
||||
|
||||
return thisPtr;
|
||||
}
|
||||
|
||||
virtual ~MockChannelArray()
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_DESTRUCT(mockChannelArray);
|
||||
}
|
||||
|
||||
virtual void putArray(bool lastRequest, int offset, int count)
|
||||
@@ -415,8 +441,6 @@ class MockChannelArray : public ChannelArray
|
||||
|
||||
virtual void destroy()
|
||||
{
|
||||
delete m_pvArray;
|
||||
delete this;
|
||||
}
|
||||
|
||||
};
|
||||
@@ -428,25 +452,19 @@ class MockChannelArray : public ChannelArray
|
||||
|
||||
PVDATA_REFCOUNT_MONITOR_DEFINE(mockMonitor);
|
||||
|
||||
class MockMonitor : public Monitor, public MonitorElement
|
||||
class MockMonitor : public Monitor, public MonitorElement, public std::tr1::enable_shared_from_this<MockMonitor>
|
||||
{
|
||||
private:
|
||||
MonitorRequester* m_monitorRequester;
|
||||
PVStructure* m_pvStructure;
|
||||
BitSet* m_changedBitSet;
|
||||
BitSet* m_overrunBitSet;
|
||||
MonitorRequester::shared_pointer m_monitorRequester;
|
||||
PVStructure::shared_pointer m_pvStructure;
|
||||
BitSet::shared_pointer m_changedBitSet;
|
||||
BitSet::shared_pointer m_overrunBitSet;
|
||||
bool m_first;
|
||||
Mutex m_lock;
|
||||
int m_count;
|
||||
|
||||
private:
|
||||
~MockMonitor()
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_DESTRUCT(mockMonitor);
|
||||
}
|
||||
|
||||
public:
|
||||
MockMonitor(MonitorRequester* monitorRequester, PVStructure *pvStructure, PVStructure *pvRequest) :
|
||||
protected:
|
||||
MockMonitor(MonitorRequester::shared_pointer& monitorRequester, PVStructure::shared_pointer& pvStructure, PVStructure::shared_pointer& pvRequest) :
|
||||
m_monitorRequester(monitorRequester), m_pvStructure(pvStructure),
|
||||
m_changedBitSet(new BitSet(pvStructure->getNumberFields())),
|
||||
m_overrunBitSet(new BitSet(pvStructure->getNumberFields())),
|
||||
@@ -457,15 +475,30 @@ class MockMonitor : public Monitor, public MonitorElement
|
||||
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(mockMonitor);
|
||||
|
||||
m_changedBitSet->set(0);
|
||||
}
|
||||
|
||||
public:
|
||||
static Monitor::shared_pointer create(MonitorRequester::shared_pointer& monitorRequester, PVStructure::shared_pointer& pvStructure, PVStructure::shared_pointer& pvRequest)
|
||||
{
|
||||
Monitor::shared_pointer thisPtr(new MockMonitor(monitorRequester, pvStructure, pvRequest));
|
||||
|
||||
// TODO pvRequest
|
||||
m_monitorRequester->monitorConnect(Status::OK, this, const_cast<Structure*>(m_pvStructure->getStructure()));
|
||||
StructureConstPtr structurePtr = static_cast<MockMonitor*>(thisPtr.get())->m_pvStructure->getStructure();
|
||||
monitorRequester->monitorConnect(Status::OK, thisPtr, structurePtr);
|
||||
|
||||
return thisPtr;
|
||||
}
|
||||
|
||||
virtual ~MockMonitor()
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_DESTRUCT(mockMonitor);
|
||||
}
|
||||
|
||||
virtual Status start()
|
||||
{
|
||||
// first monitor
|
||||
m_monitorRequester->monitorEvent(this);
|
||||
Monitor::shared_pointer thisPtr = shared_from_this();
|
||||
m_monitorRequester->monitorEvent(thisPtr);
|
||||
|
||||
return Status::OK;
|
||||
}
|
||||
@@ -475,21 +508,22 @@ class MockMonitor : public Monitor, public MonitorElement
|
||||
return Status::OK;
|
||||
}
|
||||
|
||||
virtual MonitorElement* poll()
|
||||
virtual MonitorElement::shared_pointer poll()
|
||||
{
|
||||
Lock xx(m_lock);
|
||||
if (m_count)
|
||||
{
|
||||
return 0;
|
||||
return MonitorElement::shared_pointer();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_count++;
|
||||
return this;
|
||||
MonitorElement::shared_pointer thisPtr = shared_from_this();
|
||||
return thisPtr;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void release(MonitorElement* monitorElement)
|
||||
virtual void release(MonitorElement::shared_pointer& monitorElement)
|
||||
{
|
||||
Lock xx(m_lock);
|
||||
if (m_count)
|
||||
@@ -499,25 +533,21 @@ class MockMonitor : public Monitor, public MonitorElement
|
||||
virtual void destroy()
|
||||
{
|
||||
stop();
|
||||
|
||||
delete m_overrunBitSet;
|
||||
delete m_changedBitSet;
|
||||
delete this;
|
||||
}
|
||||
|
||||
// ============ MonitorElement ============
|
||||
|
||||
virtual PVStructure* getPVStructure()
|
||||
virtual PVStructure::shared_pointer getPVStructure()
|
||||
{
|
||||
return m_pvStructure;
|
||||
}
|
||||
|
||||
virtual BitSet* getChangedBitSet()
|
||||
virtual BitSet::shared_pointer getChangedBitSet()
|
||||
{
|
||||
return m_changedBitSet;
|
||||
}
|
||||
|
||||
virtual BitSet* getOverrunBitSet()
|
||||
virtual BitSet::shared_pointer getOverrunBitSet()
|
||||
{
|
||||
return m_overrunBitSet;
|
||||
}
|
||||
@@ -526,35 +556,28 @@ class MockMonitor : public Monitor, public MonitorElement
|
||||
};
|
||||
|
||||
|
||||
|
||||
PVDATA_REFCOUNT_MONITOR_DEFINE(mockChannel);
|
||||
|
||||
class MockChannel : public Channel {
|
||||
private:
|
||||
ChannelProvider* m_provider;
|
||||
ChannelRequester* m_requester;
|
||||
ChannelProvider::shared_pointer m_provider;
|
||||
ChannelRequester::shared_pointer m_requester;
|
||||
String m_name;
|
||||
String m_remoteAddress;
|
||||
PVStructure::shared_pointer m_pvStructure;
|
||||
|
||||
PVStructure* m_pvStructure;
|
||||
|
||||
private:
|
||||
~MockChannel()
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_DESTRUCT(mockChannel);
|
||||
}
|
||||
|
||||
public:
|
||||
protected:
|
||||
|
||||
MockChannel(
|
||||
ChannelProvider* provider,
|
||||
ChannelRequester* requester,
|
||||
ChannelProvider::shared_pointer provider,
|
||||
ChannelRequester::shared_pointer requester,
|
||||
String name,
|
||||
String remoteAddress) :
|
||||
m_provider(provider),
|
||||
m_requester(requester),
|
||||
m_name(name),
|
||||
m_remoteAddress(remoteAddress)
|
||||
m_remoteAddress(remoteAddress),
|
||||
m_pvStructure()
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_CONSTRUCT(mockChannel);
|
||||
|
||||
@@ -562,20 +585,34 @@ class MockChannel : public Channel {
|
||||
ScalarType stype = pvDouble;
|
||||
String allProperties("alarm,timeStamp,display,control,valueAlarm");
|
||||
|
||||
m_pvStructure = getStandardPVField()->scalar(
|
||||
0,name,stype,allProperties);
|
||||
m_pvStructure.reset(getStandardPVField()->scalar(0,name,stype,allProperties));
|
||||
PVDouble *pvField = m_pvStructure->getDoubleField(String("value"));
|
||||
pvField->put(1.123);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
static Channel::shared_pointer create(
|
||||
ChannelProvider::shared_pointer provider,
|
||||
ChannelRequester::shared_pointer requester,
|
||||
String name,
|
||||
String remoteAddress)
|
||||
{
|
||||
Channel::shared_pointer channelPtr(new MockChannel(provider, requester, name, remoteAddress));
|
||||
|
||||
// already connected, report state
|
||||
m_requester->channelStateChange(this, CONNECTED);
|
||||
requester->channelStateChange(channelPtr, CONNECTED);
|
||||
|
||||
return channelPtr;
|
||||
}
|
||||
|
||||
virtual ~MockChannel()
|
||||
{
|
||||
PVDATA_REFCOUNT_MONITOR_DESTRUCT(mockChannel);
|
||||
}
|
||||
|
||||
virtual void destroy()
|
||||
{
|
||||
delete m_pvStructure;
|
||||
delete this;
|
||||
};
|
||||
|
||||
virtual String getRequesterName()
|
||||
@@ -588,7 +625,7 @@ class MockChannel : public Channel {
|
||||
std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl;
|
||||
}
|
||||
|
||||
virtual ChannelProvider* getProvider()
|
||||
virtual ChannelProvider::shared_pointer getProvider()
|
||||
{
|
||||
return m_provider;
|
||||
}
|
||||
@@ -603,7 +640,7 @@ class MockChannel : public Channel {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
virtual ChannelRequester* getChannelRequester()
|
||||
virtual std::tr1::shared_ptr<ChannelRequester> getChannelRequester()
|
||||
{
|
||||
return m_requester;
|
||||
}
|
||||
@@ -618,17 +655,17 @@ class MockChannel : public Channel {
|
||||
return getConnectionState() == CONNECTED;
|
||||
}
|
||||
|
||||
virtual AccessRights getAccessRights(epics::pvData::PVField *pvField)
|
||||
virtual AccessRights getAccessRights(epics::pvData::PVField::shared_pointer& pvField)
|
||||
{
|
||||
return readWrite;
|
||||
}
|
||||
|
||||
virtual void getField(GetFieldRequester *requester,epics::pvData::String subField)
|
||||
virtual void getField(GetFieldRequester::shared_pointer& requester,epics::pvData::String subField)
|
||||
{
|
||||
PVFieldPtr pvField;
|
||||
if(subField == "")
|
||||
{
|
||||
pvField = m_pvStructure;
|
||||
pvField = m_pvStructure.get();
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -638,59 +675,61 @@ class MockChannel : public Channel {
|
||||
if(pvField == NULL)
|
||||
{
|
||||
string errMsg = "field '" + subField + "' not found";
|
||||
FieldConstPtr nullPtr;
|
||||
Status errorStatus(Status::STATUSTYPE_ERROR, errMsg);
|
||||
requester->getDone(errorStatus,NULL);
|
||||
requester->getDone(errorStatus,nullPtr);
|
||||
return;
|
||||
}
|
||||
requester->getDone(Status::OK,pvField->getField());
|
||||
FieldConstPtr fieldPtr = pvField->getField();
|
||||
requester->getDone(Status::OK, fieldPtr);
|
||||
}
|
||||
|
||||
virtual ChannelProcess* createChannelProcess(
|
||||
ChannelProcessRequester *channelProcessRequester,
|
||||
epics::pvData::PVStructure *pvRequest)
|
||||
virtual ChannelProcess::shared_pointer createChannelProcess(
|
||||
ChannelProcessRequester::shared_pointer& channelProcessRequester,
|
||||
epics::pvData::PVStructure::shared_pointer& pvRequest)
|
||||
{
|
||||
return new MockChannelProcess(channelProcessRequester, m_pvStructure, pvRequest);
|
||||
return MockChannelProcess::create(channelProcessRequester, m_pvStructure, pvRequest);
|
||||
}
|
||||
|
||||
virtual ChannelGet* createChannelGet(
|
||||
ChannelGetRequester *channelGetRequester,
|
||||
epics::pvData::PVStructure *pvRequest)
|
||||
virtual ChannelGet::shared_pointer createChannelGet(
|
||||
ChannelGetRequester::shared_pointer& channelGetRequester,
|
||||
epics::pvData::PVStructure::shared_pointer& pvRequest)
|
||||
{
|
||||
return new MockChannelGet(channelGetRequester, m_pvStructure, pvRequest);
|
||||
return MockChannelGet::create(channelGetRequester, m_pvStructure, pvRequest);
|
||||
}
|
||||
|
||||
virtual ChannelPut* createChannelPut(
|
||||
ChannelPutRequester *channelPutRequester,
|
||||
epics::pvData::PVStructure *pvRequest)
|
||||
virtual ChannelPut::shared_pointer createChannelPut(
|
||||
ChannelPutRequester::shared_pointer& channelPutRequester,
|
||||
epics::pvData::PVStructure::shared_pointer& pvRequest)
|
||||
{
|
||||
return new MockChannelPut(channelPutRequester, m_pvStructure, pvRequest);
|
||||
return MockChannelPut::create(channelPutRequester, m_pvStructure, pvRequest);
|
||||
}
|
||||
|
||||
virtual ChannelPutGet* createChannelPutGet(
|
||||
ChannelPutGetRequester *channelPutGetRequester,
|
||||
epics::pvData::PVStructure *pvRequest)
|
||||
virtual ChannelPutGet::shared_pointer createChannelPutGet(
|
||||
ChannelPutGetRequester::shared_pointer& channelPutGetRequester,
|
||||
epics::pvData::PVStructure::shared_pointer& pvRequest)
|
||||
{
|
||||
return new MockChannelPutGet(channelPutGetRequester, m_pvStructure, pvRequest);
|
||||
return MockChannelPutGet::create(channelPutGetRequester, m_pvStructure, pvRequest);
|
||||
}
|
||||
|
||||
virtual ChannelRPC* createChannelRPC(ChannelRPCRequester *channelRPCRequester,
|
||||
epics::pvData::PVStructure *pvRequest)
|
||||
virtual ChannelRPC::shared_pointer createChannelRPC(ChannelRPCRequester::shared_pointer& channelRPCRequester,
|
||||
epics::pvData::PVStructure::shared_pointer& pvRequest)
|
||||
{
|
||||
return new MockChannelRPC(channelRPCRequester, m_pvStructure, pvRequest);
|
||||
return MockChannelRPC::create(channelRPCRequester, m_pvStructure, pvRequest);
|
||||
}
|
||||
|
||||
virtual epics::pvData::Monitor* createMonitor(
|
||||
epics::pvData::MonitorRequester *monitorRequester,
|
||||
epics::pvData::PVStructure *pvRequest)
|
||||
virtual epics::pvData::Monitor::shared_pointer createMonitor(
|
||||
epics::pvData::MonitorRequester::shared_pointer& monitorRequester,
|
||||
epics::pvData::PVStructure::shared_pointer& pvRequest)
|
||||
{
|
||||
return new MockMonitor(monitorRequester, m_pvStructure, pvRequest);
|
||||
return MockMonitor::create(monitorRequester, m_pvStructure, pvRequest);
|
||||
}
|
||||
|
||||
virtual ChannelArray* createChannelArray(
|
||||
ChannelArrayRequester *channelArrayRequester,
|
||||
epics::pvData::PVStructure *pvRequest)
|
||||
virtual ChannelArray::shared_pointer createChannelArray(
|
||||
ChannelArrayRequester::shared_pointer& channelArrayRequester,
|
||||
epics::pvData::PVStructure::shared_pointer& pvRequest)
|
||||
{
|
||||
return new MockChannelArray(channelArrayRequester, m_pvStructure, pvRequest);
|
||||
return MockChannelArray::create(channelArrayRequester, m_pvStructure, pvRequest);
|
||||
}
|
||||
|
||||
virtual void printInfo() {
|
||||
@@ -720,18 +759,23 @@ class MockServerChannelProvider;
|
||||
class MockChannelFind : public ChannelFind
|
||||
{
|
||||
public:
|
||||
MockChannelFind(ChannelProvider* provider) : m_provider(provider)
|
||||
typedef std::tr1::shared_ptr<MockChannelFind> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const MockChannelFind> const_shared_pointer;
|
||||
|
||||
MockChannelFind(ChannelProvider::shared_pointer &provider) : m_provider(provider)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~MockChannelFind() {}
|
||||
|
||||
virtual void destroy()
|
||||
{
|
||||
// one instance for all, do not delete at all
|
||||
}
|
||||
|
||||
virtual ChannelProvider* getChannelProvider()
|
||||
virtual ChannelProvider::shared_pointer getChannelProvider()
|
||||
{
|
||||
return m_provider;
|
||||
return m_provider.lock();
|
||||
};
|
||||
|
||||
virtual void cancelChannelFind()
|
||||
@@ -740,22 +784,26 @@ class MockChannelFind : public ChannelFind
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
// only to be destroyed by it
|
||||
friend class MockServerChannelProvider;
|
||||
virtual ~MockChannelFind() {}
|
||||
|
||||
ChannelProvider* m_provider;
|
||||
ChannelProvider::weak_pointer m_provider;
|
||||
};
|
||||
|
||||
|
||||
class MockServerChannelProvider : public ChannelProvider {
|
||||
class MockServerChannelProvider : public ChannelProvider,
|
||||
public std::tr1::enable_shared_from_this<MockServerChannelProvider>
|
||||
{
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<MockServerChannelProvider> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const MockServerChannelProvider> const_shared_pointer;
|
||||
|
||||
MockServerChannelProvider() : m_mockChannelFind(new MockChannelFind(this)) {
|
||||
MockServerChannelProvider() : m_mockChannelFind()
|
||||
{
|
||||
}
|
||||
|
||||
~MockServerChannelProvider() {};
|
||||
void initialize()
|
||||
{
|
||||
ChannelProvider::shared_pointer chProviderPtr = shared_from_this();
|
||||
m_mockChannelFind.reset(new MockChannelFind(chProviderPtr));
|
||||
}
|
||||
|
||||
virtual epics::pvData::String getProviderName()
|
||||
{
|
||||
@@ -764,56 +812,55 @@ class MockServerChannelProvider : public ChannelProvider {
|
||||
|
||||
virtual void destroy()
|
||||
{
|
||||
delete m_mockChannelFind;
|
||||
delete this;
|
||||
}
|
||||
|
||||
virtual ChannelFind* channelFind(
|
||||
virtual ChannelFind::shared_pointer channelFind(
|
||||
epics::pvData::String channelName,
|
||||
ChannelFindRequester *channelFindRequester)
|
||||
ChannelFindRequester::shared_pointer& channelFindRequester)
|
||||
{
|
||||
// channel always exists
|
||||
channelFindRequester->channelFindResult(Status::OK, m_mockChannelFind, true);
|
||||
return m_mockChannelFind;
|
||||
}
|
||||
|
||||
virtual Channel* createChannel(
|
||||
virtual Channel::shared_pointer createChannel(
|
||||
epics::pvData::String channelName,
|
||||
ChannelRequester *channelRequester,
|
||||
ChannelRequester::shared_pointer& channelRequester,
|
||||
short priority)
|
||||
{
|
||||
return createChannel(channelName, channelRequester, priority, "local");
|
||||
}
|
||||
|
||||
virtual Channel* createChannel(
|
||||
virtual Channel::shared_pointer createChannel(
|
||||
epics::pvData::String channelName,
|
||||
ChannelRequester *channelRequester,
|
||||
ChannelRequester::shared_pointer& channelRequester,
|
||||
short priority,
|
||||
epics::pvData::String address)
|
||||
{
|
||||
if (address == "local")
|
||||
{
|
||||
Channel* channel = new MockChannel(this, channelRequester, channelName, address);
|
||||
ChannelProvider::shared_pointer chProviderPtr = shared_from_this();
|
||||
Channel::shared_pointer channel = MockChannel::create(chProviderPtr, channelRequester, channelName, address);
|
||||
channelRequester->channelCreated(Status::OK, channel);
|
||||
return channel;
|
||||
}
|
||||
else
|
||||
{
|
||||
Channel::shared_pointer nullPtr;
|
||||
Status errorStatus(Status::STATUSTYPE_ERROR, "only local supported");
|
||||
channelRequester->channelCreated(errorStatus, 0);
|
||||
return 0;
|
||||
channelRequester->channelCreated(errorStatus, nullPtr);
|
||||
return nullPtr;
|
||||
}
|
||||
}
|
||||
private:
|
||||
|
||||
|
||||
MockChannelFind* m_mockChannelFind;
|
||||
|
||||
ChannelFind::shared_pointer m_mockChannelFind;
|
||||
};
|
||||
|
||||
|
||||
class ChannelFindRequesterImpl : public ChannelFindRequester
|
||||
{
|
||||
virtual void channelFindResult(const epics::pvData::Status& status,ChannelFind *channelFind,bool wasFound)
|
||||
virtual void channelFindResult(const epics::pvData::Status& status,ChannelFind::shared_pointer &channelFind,bool wasFound)
|
||||
{
|
||||
std::cout << "[ChannelFindRequesterImpl] channelFindResult("
|
||||
<< status.toString() << ", ..., " << wasFound << ")" << std::endl;
|
||||
@@ -832,15 +879,15 @@ class ChannelRequesterImpl : public ChannelRequester
|
||||
std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl;
|
||||
}
|
||||
|
||||
virtual void channelCreated(const epics::pvData::Status& status, Channel *channel)
|
||||
virtual void channelCreated(const epics::pvData::Status& status, Channel::shared_pointer &channel)
|
||||
{
|
||||
std::cout << "channelCreated(" << status.toString() << ", "
|
||||
<< (channel ? channel->getChannelName() : "(null)") << ")" << std::endl;
|
||||
}
|
||||
|
||||
virtual void channelStateChange(Channel *c, Channel::ConnectionState connectionState)
|
||||
virtual void channelStateChange(Channel::shared_pointer &channel, Channel::ConnectionState connectionState)
|
||||
{
|
||||
std::cout << "channelStateChange(" << c->getChannelName() << ", " << Channel::ConnectionStateNames[connectionState] << ")" << std::endl;
|
||||
std::cout << "channelStateChange(" << channel->getChannelName() << ", " << Channel::ConnectionStateNames[connectionState] << ")" << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -873,9 +920,9 @@ class GetFieldRequesterImpl : public GetFieldRequester
|
||||
|
||||
class ChannelGetRequesterImpl : public ChannelGetRequester
|
||||
{
|
||||
ChannelGet *m_channelGet;
|
||||
epics::pvData::PVStructure *m_pvStructure;
|
||||
epics::pvData::BitSet *m_bitSet;
|
||||
//TODO weak ChannelGet::shared_pointer m_channelGet;
|
||||
epics::pvData::PVStructure::shared_pointer m_pvStructure;
|
||||
epics::pvData::BitSet::shared_pointer m_bitSet;
|
||||
|
||||
virtual String getRequesterName()
|
||||
{
|
||||
@@ -887,13 +934,12 @@ class ChannelGetRequesterImpl : public ChannelGetRequester
|
||||
std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl;
|
||||
}
|
||||
|
||||
virtual void channelGetConnect(const epics::pvData::Status& status,ChannelGet *channelGet,
|
||||
epics::pvData::PVStructure *pvStructure,epics::pvData::BitSet *bitSet)
|
||||
virtual void channelGetConnect(const epics::pvData::Status& status, ChannelGet::shared_pointer& channelGet,
|
||||
epics::pvData::PVStructure::shared_pointer& pvStructure, epics::pvData::BitSet::shared_pointer& bitSet)
|
||||
{
|
||||
std::cout << "channelGetConnect(" << status.toString() << ")" << std::endl;
|
||||
|
||||
// TODO sync
|
||||
m_channelGet = channelGet;
|
||||
//m_channelGet = channelGet;
|
||||
m_pvStructure = pvStructure;
|
||||
m_bitSet = bitSet;
|
||||
}
|
||||
@@ -910,9 +956,9 @@ class ChannelGetRequesterImpl : public ChannelGetRequester
|
||||
|
||||
class ChannelPutRequesterImpl : public ChannelPutRequester
|
||||
{
|
||||
ChannelPut *m_channelPut;
|
||||
epics::pvData::PVStructure *m_pvStructure;
|
||||
epics::pvData::BitSet *m_bitSet;
|
||||
//TODO weak ChannelPut::shared_pointer m_channelPut;
|
||||
epics::pvData::PVStructure::shared_pointer m_pvStructure;
|
||||
epics::pvData::BitSet::shared_pointer m_bitSet;
|
||||
|
||||
virtual String getRequesterName()
|
||||
{
|
||||
@@ -924,13 +970,12 @@ class ChannelPutRequesterImpl : public ChannelPutRequester
|
||||
std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl;
|
||||
}
|
||||
|
||||
virtual void channelPutConnect(const epics::pvData::Status& status,ChannelPut *channelPut,
|
||||
epics::pvData::PVStructure *pvStructure,epics::pvData::BitSet *bitSet)
|
||||
virtual void channelPutConnect(const epics::pvData::Status& status,ChannelPut::shared_pointer& channelPut,
|
||||
epics::pvData::PVStructure::shared_pointer& pvStructure, epics::pvData::BitSet::shared_pointer& bitSet)
|
||||
{
|
||||
std::cout << "channelPutConnect(" << status.toString() << ")" << std::endl;
|
||||
|
||||
// TODO sync
|
||||
m_channelPut = channelPut;
|
||||
//m_channelPut = channelPut;
|
||||
m_pvStructure = pvStructure;
|
||||
m_bitSet = bitSet;
|
||||
}
|
||||
@@ -968,7 +1013,7 @@ class MonitorRequesterImpl : public MonitorRequester
|
||||
std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl;
|
||||
}
|
||||
|
||||
virtual void monitorConnect(const Status& status, Monitor* monitor, Structure* structure)
|
||||
virtual void monitorConnect(const Status& status, Monitor::shared_pointer& monitor, StructureConstPtr& structure)
|
||||
{
|
||||
std::cout << "monitorConnect(" << status.toString() << ")" << std::endl;
|
||||
if (structure)
|
||||
@@ -979,11 +1024,11 @@ class MonitorRequesterImpl : public MonitorRequester
|
||||
}
|
||||
}
|
||||
|
||||
virtual void monitorEvent(Monitor* monitor)
|
||||
virtual void monitorEvent(Monitor::shared_pointer& monitor)
|
||||
{
|
||||
std::cout << "monitorEvent" << std::endl;
|
||||
|
||||
MonitorElement* element = monitor->poll();
|
||||
MonitorElement::shared_pointer element = monitor->poll();
|
||||
|
||||
String str("changed/overrun ");
|
||||
element->getChangedBitSet()->toString(&str);
|
||||
@@ -996,7 +1041,7 @@ class MonitorRequesterImpl : public MonitorRequester
|
||||
monitor->release(element);
|
||||
}
|
||||
|
||||
virtual void unlisten(Monitor* monitor)
|
||||
virtual void unlisten(Monitor::shared_pointer& monitor)
|
||||
{
|
||||
std::cout << "unlisten" << std::endl;
|
||||
}
|
||||
@@ -1005,7 +1050,7 @@ class MonitorRequesterImpl : public MonitorRequester
|
||||
|
||||
class ChannelProcessRequesterImpl : public ChannelProcessRequester
|
||||
{
|
||||
ChannelProcess *m_channelProcess;
|
||||
//TODO weak ChannelProcess::shared_pointer m_channelProcess;
|
||||
|
||||
virtual String getRequesterName()
|
||||
{
|
||||
@@ -1017,12 +1062,11 @@ class ChannelProcessRequesterImpl : public ChannelProcessRequester
|
||||
std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl;
|
||||
}
|
||||
|
||||
virtual void channelProcessConnect(const epics::pvData::Status& status,ChannelProcess *channelProcess)
|
||||
virtual void channelProcessConnect(const epics::pvData::Status& status,ChannelProcess::shared_pointer& channelProcess)
|
||||
{
|
||||
std::cout << "channelProcessConnect(" << status.toString() << ")" << std::endl;
|
||||
|
||||
// TODO sync
|
||||
m_channelProcess = channelProcess;
|
||||
//m_channelProcess = channelProcess;
|
||||
}
|
||||
|
||||
virtual void processDone(const epics::pvData::Status& status)
|
||||
@@ -1035,21 +1079,25 @@ class ChannelProcessRequesterImpl : public ChannelProcessRequester
|
||||
|
||||
void testServer()
|
||||
{
|
||||
ChannelAccess* channelAccess = getChannelAccess();
|
||||
MockServerChannelProvider* channelProvider = new MockServerChannelProvider();
|
||||
registerChannelProvider(static_cast<ChannelProvider*>(channelProvider));
|
||||
|
||||
MockServerChannelProvider::shared_pointer channelProvider(new MockServerChannelProvider());
|
||||
channelProvider->initialize();
|
||||
|
||||
ChannelProvider::shared_pointer ptr = channelProvider;
|
||||
registerChannelProvider(ptr);
|
||||
|
||||
ServerContextImpl ctx;
|
||||
ctx.initialize(channelAccess);
|
||||
ServerContextImpl::shared_pointer ctx = ServerContextImpl::create();
|
||||
ChannelAccess::shared_pointer channelAccess = getChannelAccess();
|
||||
ctx->initialize(channelAccess);
|
||||
|
||||
ctx.printInfo();
|
||||
ctx->printInfo();
|
||||
|
||||
ctx.run(100);
|
||||
ctx->run(10);
|
||||
|
||||
ctx.destroy();
|
||||
ctx->destroy();
|
||||
|
||||
unregisterChannelProvider(ptr);
|
||||
|
||||
unregisterChannelProvider(static_cast<ChannelProvider*>(channelProvider));
|
||||
delete channelProvider;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
@@ -1058,6 +1106,8 @@ int main(int argc, char *argv[])
|
||||
|
||||
cout << "Done" << endl;
|
||||
|
||||
epicsThreadSleep ( 1.0 );
|
||||
std::cout << "-----------------------------------------------------------------------" << std::endl;
|
||||
epicsExitCallAtExits();
|
||||
CDRMonitor::get().show(stdout);
|
||||
return (0);
|
||||
|
||||
@@ -10,18 +10,81 @@ using namespace epics::pvAccess;
|
||||
using namespace epics::pvData;
|
||||
using namespace std;
|
||||
|
||||
class TestChannelProvider : public ChannelProvider
|
||||
{
|
||||
public:
|
||||
|
||||
epics::pvData::String getProviderName() { return "local"; };
|
||||
|
||||
|
||||
ChannelFind::shared_pointer channelFind(epics::pvData::String channelName,
|
||||
ChannelFindRequester::shared_pointer& channelFindRequester)
|
||||
{
|
||||
ChannelFind::shared_pointer nullCF;
|
||||
channelFindRequester->channelFindResult(Status::OK, nullCF, false);
|
||||
return nullCF;
|
||||
}
|
||||
|
||||
Channel::shared_pointer createChannel(
|
||||
epics::pvData::String channelName,
|
||||
ChannelRequester::shared_pointer& channelRequester,
|
||||
short priority = PRIORITY_DEFAULT)
|
||||
{
|
||||
return createChannel(channelName, channelRequester, priority, "");
|
||||
}
|
||||
|
||||
Channel::shared_pointer createChannel(
|
||||
epics::pvData::String channelName,
|
||||
ChannelRequester::shared_pointer& channelRequester,
|
||||
short priority, epics::pvData::String address)
|
||||
{
|
||||
Channel::shared_pointer nullC;
|
||||
channelRequester->channelCreated(Status::OK, nullC);
|
||||
return nullC;
|
||||
}
|
||||
|
||||
void destroy()
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
class TestChannelAccess : public ChannelAccess {
|
||||
public:
|
||||
|
||||
virtual ~TestChannelAccess() {};
|
||||
|
||||
ChannelProvider::shared_pointer getProvider(epics::pvData::String providerName)
|
||||
{
|
||||
if (providerName == "local")
|
||||
{
|
||||
return ChannelProvider::shared_pointer(new TestChannelProvider());
|
||||
}
|
||||
else
|
||||
return ChannelProvider::shared_pointer();
|
||||
}
|
||||
|
||||
std::auto_ptr<stringVector_t> getProviderNames()
|
||||
{
|
||||
std::auto_ptr<stringVector_t> pn(new stringVector_t());
|
||||
pn->push_back("local");
|
||||
return pn;
|
||||
}
|
||||
};
|
||||
|
||||
void testServerContext()
|
||||
{
|
||||
|
||||
ServerContextImpl ctx;
|
||||
ServerContextImpl::shared_pointer ctx = ServerContextImpl::create();
|
||||
|
||||
ctx.initialize(NULL);
|
||||
ChannelAccess::shared_pointer ca(new TestChannelAccess());
|
||||
ctx->initialize(ca);
|
||||
|
||||
ctx.printInfo();
|
||||
ctx->printInfo();
|
||||
|
||||
ctx.run(1);
|
||||
ctx->run(1);
|
||||
|
||||
ctx.destroy();
|
||||
ctx->destroy();
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
|
||||
@@ -10,14 +10,6 @@ PROD_HOST += wildcharMatcherTest
|
||||
wildcharMatcherTest_SRCS += wildcharMatcherTest.cpp
|
||||
wildcharMatcherTest_LIBS += pvAccess pvData Com
|
||||
|
||||
PROD_HOST += arrayFIFOTest
|
||||
arrayFIFOTest_SRCS += arrayFIFOTest.cpp
|
||||
arrayFIFOTest_LIBS += pvAccess pvData Com
|
||||
|
||||
PROD_HOST += growingCircularBufferTest
|
||||
growingCircularBufferTest_SRCS += growingCircularBufferTest.cpp
|
||||
growingCircularBufferTest_LIBS += pvAccess pvData Com
|
||||
|
||||
PROD_HOST += inetAddressUtilsTest
|
||||
inetAddressUtilsTest_SRCS += inetAddressUtilsTest.cpp
|
||||
inetAddressUtilsTest_LIBS += pvAccess pvData Com
|
||||
|
||||
@@ -1,271 +0,0 @@
|
||||
/*
|
||||
* arrayFIFOTest.cpp
|
||||
*
|
||||
* Created on: Nov 9, 2010
|
||||
* Author: Miha Vitorovic
|
||||
*/
|
||||
|
||||
#define ARRAY_FIFO_DEBUG 1
|
||||
#include "arrayFIFO.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <epicsAssert.h>
|
||||
|
||||
using namespace epics::pvAccess;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
void testSimpleType() {
|
||||
cout<<"\nTests for simple type template."<<endl;
|
||||
|
||||
ArrayFIFO<int> fifoInt;
|
||||
|
||||
assert(fifoInt.size()==0);
|
||||
assert(fifoInt.isEmpty());
|
||||
|
||||
cout<<"Testing clear."<<endl;
|
||||
fifoInt.push(3);
|
||||
assert(fifoInt.size()==1);
|
||||
|
||||
fifoInt.clear();
|
||||
assert(fifoInt.isEmpty());
|
||||
|
||||
cout<<"Testing push/pop."<<endl;
|
||||
fifoInt.push(5);
|
||||
fifoInt.push(6);
|
||||
fifoInt.push(7);
|
||||
assert(fifoInt.size()==3);
|
||||
|
||||
assert(fifoInt.pop()==7);
|
||||
assert(fifoInt.size()==2);
|
||||
|
||||
assert(fifoInt.pop()==6);
|
||||
assert(fifoInt.size()==1);
|
||||
|
||||
assert(fifoInt.pop()==5);
|
||||
assert(fifoInt.size()==0);
|
||||
|
||||
cout<<"Testing FIFO ops (first/last)."<<endl;
|
||||
fifoInt.addFirst(100);
|
||||
fifoInt.addFirst(200);
|
||||
fifoInt.addFirst(300);
|
||||
fifoInt.addFirst(400);
|
||||
fifoInt.addFirst(500);
|
||||
|
||||
assert(fifoInt.size()==5);
|
||||
assert(fifoInt.pollLast()==100);
|
||||
assert(fifoInt.pollLast()==200);
|
||||
assert(fifoInt.pollLast()==300);
|
||||
assert(fifoInt.pollLast()==400);
|
||||
assert(fifoInt.pollLast()==500);
|
||||
assert(fifoInt.isEmpty());
|
||||
|
||||
cout<<"Testing FIFO ops (last/first)."<<endl;
|
||||
fifoInt.addLast(150);
|
||||
fifoInt.addLast(250);
|
||||
fifoInt.addLast(350);
|
||||
fifoInt.addLast(450);
|
||||
fifoInt.addLast(550);
|
||||
assert(fifoInt.size()==5);
|
||||
|
||||
assert(fifoInt.pollFirst()==150);
|
||||
assert(fifoInt.pollFirst()==250);
|
||||
assert(fifoInt.pollFirst()==350);
|
||||
assert(fifoInt.pollFirst()==450);
|
||||
assert(fifoInt.pollFirst()==550);
|
||||
assert(fifoInt.isEmpty());
|
||||
|
||||
cout<<"Testing remove, peek."<<endl;
|
||||
fifoInt.addFirst(1000);
|
||||
fifoInt.addFirst(2000);
|
||||
fifoInt.addFirst(3000);
|
||||
fifoInt.addFirst(4000);
|
||||
fifoInt.addFirst(5000);
|
||||
fifoInt.addFirst(6000);
|
||||
fifoInt.addFirst(7000);
|
||||
// - - - - - - - - - - - -
|
||||
fifoInt.addFirst(8000);
|
||||
fifoInt.addFirst(9000);
|
||||
fifoInt.addFirst(10000);
|
||||
|
||||
assert(fifoInt.peekFirst()==10000);
|
||||
assert(fifoInt.peekLast()==1000);
|
||||
|
||||
assert(fifoInt.size()==10);
|
||||
assert(fifoInt.remove(9000));
|
||||
assert(fifoInt.size()==9);
|
||||
assert(!fifoInt.remove(3500));
|
||||
assert(fifoInt.size()==9);
|
||||
|
||||
assert(fifoInt.pollLast()==1000);
|
||||
assert(fifoInt.pollLast()==2000);
|
||||
assert(fifoInt.pollLast()==3000);
|
||||
assert(fifoInt.pollLast()==4000);
|
||||
assert(fifoInt.pollLast()==5000);
|
||||
assert(fifoInt.pollLast()==6000);
|
||||
assert(fifoInt.pollLast()==7000);
|
||||
// - - - - - - - - - - - -
|
||||
assert(fifoInt.pollLast()==8000);
|
||||
assert(fifoInt.pollLast()==10000);
|
||||
assert(fifoInt.isEmpty());
|
||||
|
||||
cout<<"Testing increase buffer."<<endl;
|
||||
fifoInt.addLast(100100);
|
||||
fifoInt.addLast(100200);
|
||||
fifoInt.addLast(100300);
|
||||
fifoInt.addLast(100400);
|
||||
fifoInt.addLast(100500);
|
||||
fifoInt.addLast(100600);
|
||||
fifoInt.addLast(100700);
|
||||
fifoInt.addLast(100800);
|
||||
fifoInt.addLast(100900);
|
||||
fifoInt.addLast(101000);
|
||||
fifoInt.addLast(101100);
|
||||
fifoInt.addLast(101200);
|
||||
fifoInt.addLast(101300);
|
||||
fifoInt.addLast(101400);
|
||||
fifoInt.addLast(101500);
|
||||
fifoInt.addLast(101600);
|
||||
fifoInt.addLast(101700);
|
||||
fifoInt.addLast(101800);
|
||||
|
||||
assert(fifoInt.size()==18);
|
||||
fifoInt.debugState();
|
||||
fifoInt.clear();
|
||||
assert(fifoInt.isEmpty());
|
||||
|
||||
cout<<"\nPASSED!\n";
|
||||
}
|
||||
|
||||
void testPointerType() {
|
||||
cout<<"\nTests for pointer type template."<<endl;
|
||||
|
||||
int testVals[] = {0,1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19,20};
|
||||
|
||||
ArrayFIFO<int*> fifoInt;
|
||||
|
||||
assert(fifoInt.size()==0);
|
||||
assert(fifoInt.isEmpty());
|
||||
|
||||
cout<<"Testing clear."<<endl;
|
||||
fifoInt.push(&testVals[3]);
|
||||
assert(fifoInt.size()==1);
|
||||
|
||||
fifoInt.clear();
|
||||
assert(fifoInt.isEmpty());
|
||||
|
||||
cout<<"Testing push/pop."<<endl;
|
||||
fifoInt.push(&testVals[5]);
|
||||
fifoInt.push(&testVals[6]);
|
||||
fifoInt.push(&testVals[7]);
|
||||
assert(fifoInt.size()==3);
|
||||
|
||||
assert(fifoInt.pop()==&testVals[7]);
|
||||
assert(fifoInt.size()==2);
|
||||
|
||||
assert(fifoInt.pop()==&testVals[6]);
|
||||
assert(fifoInt.size()==1);
|
||||
|
||||
assert(fifoInt.pop()==&testVals[5]);
|
||||
assert(fifoInt.size()==0);
|
||||
|
||||
cout<<"Testing FIFO ops (first/last)."<<endl;
|
||||
fifoInt.addFirst(&testVals[1]);
|
||||
fifoInt.addFirst(&testVals[2]);
|
||||
fifoInt.addFirst(&testVals[3]);
|
||||
fifoInt.addFirst(&testVals[4]);
|
||||
fifoInt.addFirst(&testVals[5]);
|
||||
|
||||
assert(fifoInt.size()==5);
|
||||
assert(fifoInt.pollLast()==&testVals[1]);
|
||||
assert(fifoInt.pollLast()==&testVals[2]);
|
||||
assert(fifoInt.pollLast()==&testVals[3]);
|
||||
assert(fifoInt.pollLast()==&testVals[4]);
|
||||
assert(fifoInt.pollLast()==&testVals[5]);
|
||||
assert(fifoInt.isEmpty());
|
||||
|
||||
cout<<"Testing FIFO ops (last/first)."<<endl;
|
||||
fifoInt.addLast(&testVals[7]);
|
||||
fifoInt.addLast(&testVals[8]);
|
||||
fifoInt.addLast(&testVals[9]);
|
||||
fifoInt.addLast(&testVals[10]);
|
||||
fifoInt.addLast(&testVals[11]);
|
||||
assert(fifoInt.size()==5);
|
||||
|
||||
assert(fifoInt.pollFirst()==&testVals[7]);
|
||||
assert(fifoInt.pollFirst()==&testVals[8]);
|
||||
assert(fifoInt.pollFirst()==&testVals[9]);
|
||||
assert(fifoInt.pollFirst()==&testVals[10]);
|
||||
assert(fifoInt.pollFirst()==&testVals[11]);
|
||||
assert(fifoInt.isEmpty());
|
||||
|
||||
cout<<"Testing remove, peek."<<endl;
|
||||
fifoInt.addFirst(&testVals[1]);
|
||||
fifoInt.addFirst(&testVals[2]);
|
||||
fifoInt.addFirst(&testVals[3]);
|
||||
fifoInt.addFirst(&testVals[4]);
|
||||
fifoInt.addFirst(&testVals[5]);
|
||||
fifoInt.addFirst(&testVals[6]);
|
||||
fifoInt.addFirst(&testVals[7]);
|
||||
// - - - - - - - - - - - -
|
||||
fifoInt.addFirst(&testVals[8]);
|
||||
fifoInt.addFirst(&testVals[9]);
|
||||
fifoInt.addFirst(&testVals[10]);
|
||||
|
||||
assert(fifoInt.peekFirst()==&testVals[10]);
|
||||
assert(fifoInt.peekLast()==&testVals[1]);
|
||||
|
||||
assert(fifoInt.size()==10);
|
||||
assert(fifoInt.remove(&testVals[9]));
|
||||
assert(fifoInt.size()==9);
|
||||
assert(!fifoInt.remove(&testVals[15]));
|
||||
assert(fifoInt.size()==9);
|
||||
|
||||
assert(fifoInt.pollLast()==&testVals[1]);
|
||||
assert(fifoInt.pollLast()==&testVals[2]);
|
||||
assert(fifoInt.pollLast()==&testVals[3]);
|
||||
assert(fifoInt.pollLast()==&testVals[4]);
|
||||
assert(fifoInt.pollLast()==&testVals[5]);
|
||||
assert(fifoInt.pollLast()==&testVals[6]);
|
||||
assert(fifoInt.pollLast()==&testVals[7]);
|
||||
assert(fifoInt.pollLast()==&testVals[8]);
|
||||
// - - - - - - - - - - - -
|
||||
assert(fifoInt.pollLast()==&testVals[10]);
|
||||
assert(fifoInt.isEmpty());
|
||||
|
||||
cout<<"Testing increase buffer."<<endl;
|
||||
fifoInt.addLast(&testVals[2]);
|
||||
fifoInt.addLast(&testVals[3]);
|
||||
fifoInt.addLast(&testVals[4]);
|
||||
fifoInt.addLast(&testVals[5]);
|
||||
fifoInt.addLast(&testVals[6]);
|
||||
fifoInt.addLast(&testVals[7]);
|
||||
fifoInt.addLast(&testVals[8]);
|
||||
fifoInt.addLast(&testVals[9]);
|
||||
fifoInt.addLast(&testVals[10]);
|
||||
fifoInt.addLast(&testVals[11]);
|
||||
fifoInt.addLast(&testVals[12]);
|
||||
fifoInt.addLast(&testVals[13]);
|
||||
fifoInt.addLast(&testVals[14]);
|
||||
fifoInt.addLast(&testVals[15]);
|
||||
fifoInt.addLast(&testVals[16]);
|
||||
fifoInt.addLast(&testVals[17]);
|
||||
fifoInt.addLast(&testVals[18]);
|
||||
fifoInt.addLast(&testVals[19]);
|
||||
|
||||
assert(fifoInt.size()==18);
|
||||
fifoInt.debugState();
|
||||
fifoInt.clear();
|
||||
assert(fifoInt.isEmpty());
|
||||
|
||||
|
||||
cout<<"\nPASSED!\n";
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
testSimpleType();
|
||||
cout<<endl;
|
||||
testPointerType();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1,89 +0,0 @@
|
||||
/*
|
||||
* growingCircularBufferTest.cpp
|
||||
*
|
||||
* Created on: Nov 11, 2010
|
||||
* Author: Miha Vitorovic
|
||||
*/
|
||||
|
||||
#include <growingCircularBuffer.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <epicsAssert.h>
|
||||
|
||||
using namespace epics::pvAccess;
|
||||
using std::cout;
|
||||
using std::endl;
|
||||
|
||||
const size_t CAPACITY = 10;
|
||||
|
||||
void testSimpleType() {
|
||||
GrowingCircularBuffer<int> cb(CAPACITY);
|
||||
|
||||
cout<<"Testing circular buffer simple type."<<endl;
|
||||
|
||||
assert(cb.capacity()==CAPACITY);
|
||||
assert(cb.size()==0);
|
||||
|
||||
// insert, get test
|
||||
bool first = cb.insert(1);
|
||||
assert(first);
|
||||
assert(cb.size()==1);
|
||||
assert(cb.extract()==1);
|
||||
assert(cb.size()==0);
|
||||
|
||||
for(size_t i = 0; i<2*CAPACITY; i++) {
|
||||
first = cb.insert(i);
|
||||
assert(cb.size()==i+1);
|
||||
assert((cb.size() == 1)==first);
|
||||
}
|
||||
assert(cb.size()==2*CAPACITY);
|
||||
|
||||
for(size_t i = 0; i<2*CAPACITY; i++) {
|
||||
assert(cb.extract()==(int)i);
|
||||
assert(cb.size()==2*CAPACITY-i-1);
|
||||
}
|
||||
assert(cb.size()==0);
|
||||
|
||||
cout<<"\nPASSED!\n";
|
||||
}
|
||||
|
||||
void testPointerType() {
|
||||
GrowingCircularBuffer<int*> cb(CAPACITY);
|
||||
int testVals[] = {0,1,2,3,4,5,6,7,8,9,11,12,13,14,15,16,17,18,19,20};
|
||||
|
||||
cout<<"Testing circular buffer pointer type."<<endl;
|
||||
|
||||
assert(cb.capacity()==CAPACITY);
|
||||
assert(cb.size()==0);
|
||||
|
||||
// insert, get test
|
||||
bool first = cb.insert(&testVals[1]);
|
||||
assert(first);
|
||||
assert(cb.size()==1);
|
||||
assert(cb.extract()==&testVals[1]);
|
||||
assert(cb.size()==0);
|
||||
|
||||
for(size_t i = 0; i<2*CAPACITY; i++) {
|
||||
first = cb.insert(&testVals[i]);
|
||||
assert(cb.size()==i+1);
|
||||
assert((cb.size() == 1)==first);
|
||||
}
|
||||
assert(cb.size()==2*CAPACITY);
|
||||
|
||||
for(size_t i = 0; i<2*CAPACITY; i++) {
|
||||
assert(cb.extract()==&testVals[i]);
|
||||
assert(cb.size()==2*CAPACITY-i-1);
|
||||
}
|
||||
assert(cb.size()==0);
|
||||
|
||||
cout<<"\nPASSED!\n";
|
||||
}
|
||||
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
testSimpleType();
|
||||
cout<<endl;
|
||||
testPointerType();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -14,6 +14,9 @@
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <CDRMonitor.h>
|
||||
#include <convert.h>
|
||||
|
||||
using std::tr1::static_pointer_cast;
|
||||
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
@@ -139,45 +142,45 @@ void testRegistryPutGet()
|
||||
registry->registerIntrospectionInterface(id,structureArrayIn);
|
||||
|
||||
id = 0;
|
||||
ScalarConstPtr scalarOut = static_cast<ScalarConstPtr>(registry->getIntrospectionInterface(id));
|
||||
ScalarConstPtr scalarOut = static_pointer_cast<const Scalar>(registry->getIntrospectionInterface(id));
|
||||
assert(scalarIn == scalarOut);
|
||||
|
||||
id++;
|
||||
ScalarArrayConstPtr scalarArrayOut = static_cast<ScalarArrayConstPtr>(registry->getIntrospectionInterface(id));
|
||||
ScalarArrayConstPtr scalarArrayOut = static_pointer_cast<const ScalarArray>(registry->getIntrospectionInterface(id));
|
||||
assert(scalarArrayIn == scalarArrayOut);
|
||||
|
||||
id++;
|
||||
StructureConstPtr structureOut = static_cast<StructureConstPtr>(registry->getIntrospectionInterface(id));
|
||||
StructureConstPtr structureOut = static_pointer_cast<const Structure>(registry->getIntrospectionInterface(id));
|
||||
assert(structureIn == structureOut);
|
||||
|
||||
id++;
|
||||
StructureArrayConstPtr structureArrayOut = static_cast<StructureArrayConstPtr>(registry->getIntrospectionInterface(id));
|
||||
StructureArrayConstPtr structureArrayOut = static_pointer_cast<const StructureArray>(registry->getIntrospectionInterface(id));
|
||||
assert(structureArrayIn == structureArrayOut);
|
||||
|
||||
bool existing;
|
||||
id = registry->registerIntrospectionInterface(static_cast<FieldConstPtr>(scalarIn),existing);
|
||||
id = registry->registerIntrospectionInterface(static_pointer_cast<const Field>(scalarIn),existing);
|
||||
assert(existing == true);
|
||||
assert(id == 0);
|
||||
|
||||
id = registry->registerIntrospectionInterface(static_cast<FieldConstPtr>(scalarArrayIn),existing);
|
||||
id = registry->registerIntrospectionInterface(static_pointer_cast<const Field>(scalarArrayIn),existing);
|
||||
assert(existing == true);
|
||||
assert(id == 1);
|
||||
|
||||
id = registry->registerIntrospectionInterface(static_cast<FieldConstPtr>(structureIn),existing);
|
||||
id = registry->registerIntrospectionInterface(static_pointer_cast<const Field>(structureIn),existing);
|
||||
assert(existing == true);
|
||||
assert(id == 2);
|
||||
|
||||
id = registry->registerIntrospectionInterface(static_cast<FieldConstPtr>(structureArrayIn),existing);
|
||||
id = registry->registerIntrospectionInterface(static_pointer_cast<const Field>(structureArrayIn),existing);
|
||||
assert(existing == true);
|
||||
assert(id == 3);
|
||||
|
||||
//should exist
|
||||
ScalarConstPtr scalarInNew = getScalar("field1");
|
||||
id = registry->registerIntrospectionInterface(static_cast<FieldConstPtr>(scalarInNew),existing);
|
||||
id = registry->registerIntrospectionInterface(static_pointer_cast<const Field>(scalarInNew),existing);
|
||||
assert(existing == true);
|
||||
assert(id == 0);
|
||||
|
||||
scalarOut = static_cast<ScalarConstPtr>(registry->getIntrospectionInterface(id));
|
||||
scalarOut = static_pointer_cast<const Scalar>(registry->getIntrospectionInterface(id));
|
||||
assert(scalarIn == scalarOut);
|
||||
}
|
||||
|
||||
@@ -186,7 +189,7 @@ void testRegistryReset()
|
||||
registry->reset();
|
||||
|
||||
short id = 0;
|
||||
assert(static_cast<ScalarConstPtr>(registry->getIntrospectionInterface(id)) == 0);
|
||||
assert(static_pointer_cast<const Scalar>(registry->getIntrospectionInterface(id)) == 0);
|
||||
}
|
||||
|
||||
void serialize(FieldConstPtr field, IntrospectionRegistry* registry)
|
||||
@@ -214,6 +217,7 @@ FieldConstPtr deserialize(IntrospectionRegistry* registry)
|
||||
void checkTypeCode(int8 typeCodeIn)
|
||||
{
|
||||
int8 typeCode = buffer->getByte();
|
||||
printf("%d == %d\n", typeCode, typeCodeIn);
|
||||
assert(typeCode == typeCodeIn);
|
||||
buffer->rewind();
|
||||
}
|
||||
@@ -275,7 +279,7 @@ void testSerialize()
|
||||
j++;
|
||||
ss << j;
|
||||
name2 = "field" + ss.str();
|
||||
testSerializeCommon(static_cast<FieldConstPtr>(getScalar(name1)),static_cast<FieldConstPtr>(getScalar(name2)));
|
||||
testSerializeCommon(static_pointer_cast<const Field>(getScalar(name1)),static_pointer_cast<const Field>(getScalar(name2)));
|
||||
|
||||
name1.clear();
|
||||
name2.clear();
|
||||
@@ -286,7 +290,7 @@ void testSerialize()
|
||||
j++;
|
||||
ss << j;
|
||||
name2 = "fieldArray" + ss.str();
|
||||
testSerializeCommon(static_cast<FieldConstPtr>(getScalarArray(name1)),static_cast<FieldConstPtr>(getScalarArray(name2)));
|
||||
testSerializeCommon(static_pointer_cast<const Field>(getScalarArray(name1)),static_pointer_cast<const Field>(getScalarArray(name2)));
|
||||
|
||||
name1.clear();
|
||||
name2.clear();
|
||||
@@ -297,7 +301,7 @@ void testSerialize()
|
||||
j++;
|
||||
ss << j;
|
||||
name2 = "structure" + ss.str();
|
||||
testSerializeCommon(static_cast<FieldConstPtr>(getStructure(name1)),static_cast<FieldConstPtr>(getStructure(name2)));
|
||||
testSerializeCommon(static_pointer_cast<const Field>(getStructure(name1)),static_pointer_cast<const Field>(getStructure(name2)));
|
||||
|
||||
name1.clear();
|
||||
name2.clear();
|
||||
@@ -312,7 +316,7 @@ void testSerialize()
|
||||
ss << j;
|
||||
name3 = "structure" + ss.str();
|
||||
name4 = "structureArray" + ss.str();
|
||||
testSerializeCommon(static_cast<FieldConstPtr>(getStructureArray(name1,name2)),static_cast<FieldConstPtr>(getStructureArray(name3,name4)));
|
||||
testSerializeCommon(static_pointer_cast<const Field>(getStructureArray(name1,name2)),static_pointer_cast<const Field>(getStructureArray(name3,name4)));
|
||||
}
|
||||
|
||||
//serverRegistry->printKeysAndValues("server");
|
||||
@@ -323,9 +327,9 @@ void testSerializeFull()
|
||||
{
|
||||
buffer->clear();
|
||||
ScalarConstPtr scalarIn = getScalar("field1");
|
||||
IntrospectionRegistry::serializeFull(static_cast<FieldConstPtr>(scalarIn),buffer,flusher);
|
||||
IntrospectionRegistry::serializeFull(static_pointer_cast<const Field>(scalarIn),buffer,flusher);
|
||||
buffer->flip();
|
||||
ScalarConstPtr scalarOut = static_cast<ScalarConstPtr>(IntrospectionRegistry::deserializeFull(buffer,control));
|
||||
ScalarConstPtr scalarOut = static_pointer_cast<const Scalar>(IntrospectionRegistry::deserializeFull(buffer,control));
|
||||
PVField *pvField = pvDataCreate->createPVField(0,scalarOut);
|
||||
pvFieldArray.push_back(pvField);
|
||||
assert(scalarIn->getFieldName() == scalarOut->getFieldName());
|
||||
@@ -333,9 +337,9 @@ void testSerializeFull()
|
||||
|
||||
buffer->clear();
|
||||
ScalarArrayConstPtr scalarArrayIn = getScalarArray("fieldArray1");
|
||||
IntrospectionRegistry::serializeFull(static_cast<FieldConstPtr>(scalarArrayIn),buffer,flusher);
|
||||
IntrospectionRegistry::serializeFull(static_pointer_cast<const Field>(scalarArrayIn),buffer,flusher);
|
||||
buffer->flip();
|
||||
ScalarArrayConstPtr scalarArrayOut = static_cast<ScalarArrayConstPtr>(IntrospectionRegistry::deserializeFull(buffer,control));
|
||||
ScalarArrayConstPtr scalarArrayOut = static_pointer_cast<const ScalarArray>(IntrospectionRegistry::deserializeFull(buffer,control));
|
||||
pvField = pvDataCreate->createPVField(0,scalarArrayOut);
|
||||
pvFieldArray.push_back(pvField);
|
||||
assert(scalarArrayIn->getFieldName() == scalarArrayOut->getFieldName());
|
||||
@@ -343,9 +347,9 @@ void testSerializeFull()
|
||||
|
||||
buffer->clear();
|
||||
StructureConstPtr structureIn = getStructure("struct1");
|
||||
IntrospectionRegistry::serializeFull(static_cast<FieldConstPtr>(structureIn),buffer,flusher);
|
||||
IntrospectionRegistry::serializeFull(static_pointer_cast<const Field>(structureIn),buffer,flusher);
|
||||
buffer->flip();
|
||||
StructureConstPtr structureOut = static_cast<StructureConstPtr>(IntrospectionRegistry::deserializeFull(buffer,control));
|
||||
StructureConstPtr structureOut = static_pointer_cast<const Structure>(IntrospectionRegistry::deserializeFull(buffer,control));
|
||||
pvField = pvDataCreate->createPVField(0,structureOut);
|
||||
pvFieldArray.push_back(pvField);
|
||||
assert(structureIn->getFieldName() == structureOut->getFieldName());
|
||||
@@ -353,9 +357,9 @@ void testSerializeFull()
|
||||
|
||||
buffer->clear();
|
||||
StructureArrayConstPtr structureArrayIn = getStructureArray("struct1","structArray1");
|
||||
IntrospectionRegistry::serializeFull(static_cast<FieldConstPtr>(structureArrayIn),buffer,flusher);
|
||||
IntrospectionRegistry::serializeFull(static_pointer_cast<const Field>(structureArrayIn),buffer,flusher);
|
||||
buffer->flip();
|
||||
StructureArrayConstPtr structureArrayOut = static_cast<StructureArrayConstPtr>(IntrospectionRegistry::deserializeFull(buffer,control));
|
||||
StructureArrayConstPtr structureArrayOut = static_pointer_cast<const StructureArray>(IntrospectionRegistry::deserializeFull(buffer,control));
|
||||
pvField = pvDataCreate->createPVField(0,structureArrayOut);
|
||||
pvFieldArray.push_back(pvField);
|
||||
assert(structureArrayIn->getFieldName() == structureArrayOut->getFieldName());
|
||||
|
||||
@@ -12,12 +12,16 @@
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace epics {
|
||||
namespace pvAccess {
|
||||
|
||||
|
||||
class TestTransport : public Transport{
|
||||
public:
|
||||
typedef std::tr1::shared_ptr<TestTransport> shared_pointer;
|
||||
typedef std::tr1::shared_ptr<const TestTransport> const_shared_pointer;
|
||||
|
||||
TestTransport(string type, int16 priority, osiSockAddr* address): _type(type), _priority(priority), _address(address) {/*cout << "Transport::Transport" << endl;*/};
|
||||
~TestTransport(){/*cout << "Transport::~Transport" << endl;*/};
|
||||
virtual const string getType() const {return _type;};
|
||||
@@ -39,7 +43,7 @@ namespace epics {
|
||||
virtual bool isClosed() {return false;};
|
||||
virtual bool isVerified() {return false;};
|
||||
virtual void verified(){};
|
||||
virtual void enqueueSendRequest(TransportSender* sender){};
|
||||
virtual void enqueueSendRequest(TransportSender::shared_pointer& sender){};
|
||||
virtual void ensureData(int) {};
|
||||
virtual IntrospectionRegistry* getIntrospectionRegistry() {return NULL;};
|
||||
private:
|
||||
@@ -57,68 +61,77 @@ using namespace std;
|
||||
static TransportRegistry* registry;
|
||||
static const int16 address_max = 10;
|
||||
static const int16 priority_max = 100;
|
||||
typedef std::vector<osiSockAddr*> osiSockAddrVector_t;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
registry = new TransportRegistry();
|
||||
int32 size;
|
||||
TestTransport** transportArrayOut;
|
||||
TestTransport** transportArrayIn = new TestTransport*[address_max * priority_max];
|
||||
osiSockAddr** addrArray = new osiSockAddr*[address_max];
|
||||
auto_ptr<TransportRegistry::transportVector_t> transportArrayOut;
|
||||
std::vector<Transport::shared_pointer> transportArrayIn (address_max * priority_max);
|
||||
osiSockAddrVector_t addrArray (address_max);
|
||||
//address
|
||||
for(int32 i = 0; i < address_max; i++)
|
||||
{
|
||||
osiSockAddr* addr = new osiSockAddr;
|
||||
addrArray[i] = addr;
|
||||
addr->ia.sin_addr.s_addr = i;
|
||||
addr->ia.sin_port = i;
|
||||
addr->ia.sin_family = AF_INET;
|
||||
addrArray.at(i) = addr;
|
||||
|
||||
//priority
|
||||
for(int16 j = 0; j < priority_max; j++)
|
||||
{
|
||||
TestTransport* transportIn = new TestTransport("tcp", j, addr);
|
||||
transportArrayIn[i * priority_max + j] = transportIn;
|
||||
registry->put(static_cast<Transport*>(transportIn));
|
||||
Transport::shared_pointer testTransportIn(new TestTransport("tcp", j, addr));
|
||||
transportArrayIn.at(i * priority_max + j) = testTransportIn;
|
||||
registry->put(testTransportIn);
|
||||
|
||||
TestTransport* transportOut = static_cast<TestTransport*>(registry->get("tcp",addr,(const int16)j));
|
||||
assert(transportIn == transportOut);
|
||||
Transport::shared_pointer testTransportOut(registry->get("tcp",addr,(const int16)j));
|
||||
assert(testTransportIn.get() == testTransportOut.get());
|
||||
}
|
||||
|
||||
|
||||
transportArrayOut = reinterpret_cast<TestTransport**>(registry->get("tcp",addr,size));
|
||||
assert(size == priority_max);
|
||||
transportArrayOut = registry->get("tcp",addr);
|
||||
assert((int16)transportArrayOut->size() == priority_max);
|
||||
for(int32 k = 0; k < priority_max; k++)
|
||||
{
|
||||
assert(transportArrayIn[i * priority_max + k] == transportArrayOut[k]);
|
||||
assert(transportArrayIn.at(i * priority_max + k).get() == transportArrayOut->at(k).get());
|
||||
}
|
||||
|
||||
delete[] transportArrayOut;
|
||||
}
|
||||
|
||||
//add one transport which has same addr and priority as last one and check that the size does not increase
|
||||
osiSockAddr* addr = new osiSockAddr;
|
||||
addr->ia.sin_addr.s_addr = address_max - 1;
|
||||
addr->ia.sin_port = address_max - 1;
|
||||
addr->ia.sin_family = AF_INET;
|
||||
Transport::shared_pointer testTransportIn(new TestTransport("tcp", priority_max - 1, addr));
|
||||
registry->put(testTransportIn);
|
||||
Transport::shared_pointer testTransportOut(registry->get("tcp",addr,(const int16)priority_max - 1));
|
||||
assert(testTransportIn.get() == testTransportOut.get());
|
||||
delete addr;
|
||||
//put back the old one
|
||||
registry->put(transportArrayIn.at((address_max - 1) * priority_max + priority_max - 1));
|
||||
|
||||
assert(registry->numberOfActiveTransports() == (address_max * priority_max));
|
||||
|
||||
transportArrayOut = reinterpret_cast<TestTransport**>(registry->toArray("tcp",size));
|
||||
assert(size == (address_max * priority_max));
|
||||
transportArrayOut = registry->toArray("tcp");
|
||||
assert((int16)transportArrayOut->size() == (address_max * priority_max));
|
||||
for(int32 i = 0; i < address_max * priority_max; i++)
|
||||
{
|
||||
assert(transportArrayIn[i] == transportArrayOut[i]);
|
||||
assert(transportArrayIn.at(i).get() == transportArrayOut->at(i).get());
|
||||
}
|
||||
delete[] transportArrayOut;
|
||||
|
||||
transportArrayOut = reinterpret_cast<TestTransport**>(registry->toArray(size));
|
||||
assert(size == (address_max * priority_max));
|
||||
|
||||
transportArrayOut = registry->toArray();
|
||||
assert((int16)transportArrayOut->size() == (address_max * priority_max));
|
||||
for(int32 i = 0; i < address_max * priority_max; i++)
|
||||
{
|
||||
assert(transportArrayIn[i] == transportArrayOut[i]);
|
||||
assert(transportArrayIn.at(i).get() == transportArrayOut->at(i).get());
|
||||
}
|
||||
delete[] transportArrayOut;
|
||||
|
||||
for(int32 i = 0; i < address_max; i++)
|
||||
{
|
||||
for(int16 j = 0; j < priority_max; j++)
|
||||
{
|
||||
assert(transportArrayIn[i * priority_max + j] == registry->remove(static_cast<Transport*>(transportArrayIn[i * priority_max + j])));
|
||||
assert(transportArrayIn.at(i * priority_max + j) == registry->remove(transportArrayIn.at(i * priority_max + j)));
|
||||
}
|
||||
}
|
||||
assert(registry->numberOfActiveTransports() == 0);
|
||||
@@ -127,27 +140,21 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
for(int16 j = 0; j < priority_max; j++)
|
||||
{
|
||||
registry->put(static_cast<Transport*>(transportArrayIn[i * priority_max + j]));;
|
||||
registry->put(transportArrayIn.at(i * priority_max + j));
|
||||
}
|
||||
}
|
||||
assert(registry->numberOfActiveTransports() == (priority_max * address_max));
|
||||
registry->clear();
|
||||
assert(registry->numberOfActiveTransports() == 0);
|
||||
|
||||
for(int32 i = 0; i < address_max; i++)
|
||||
for(osiSockAddrVector_t::iterator iter = addrArray.begin(); iter != addrArray.end(); iter++)
|
||||
{
|
||||
if( addrArray[i]) delete addrArray[i];
|
||||
for(int16 j = 0; j < priority_max; j++)
|
||||
{
|
||||
if(transportArrayIn[i * priority_max + j]) delete transportArrayIn[i * priority_max + j];
|
||||
}
|
||||
delete *iter;
|
||||
}
|
||||
|
||||
if(addrArray) delete[] addrArray;
|
||||
if(transportArrayIn) delete[] transportArrayIn;
|
||||
addrArray.clear();
|
||||
if(registry) delete registry;
|
||||
epicsExitCallAtExits();
|
||||
CDRMonitor::get().show(stdout);
|
||||
epicsExitCallAtExits();
|
||||
CDRMonitor::get().show(stdout);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user