port from pvAccessCPP-md

This commit is contained in:
Matej Sekoranja
2011-05-12 12:47:55 +02:00
parent a077d7d084
commit c36ba5264d
68 changed files with 4762 additions and 5612 deletions

3
README
View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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";
}
}

View File

@@ -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();
}

View File

@@ -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 */

View File

@@ -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();
}}

View File

@@ -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());
}

View File

@@ -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;
}

View File

@@ -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];

View File

@@ -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);
}
}}

View File

@@ -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;
}
}}

View File

@@ -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.
*/

View File

@@ -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 */

View File

@@ -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());
}
}
}

View File

@@ -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() {

View File

@@ -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);
};

View File

@@ -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);
}

View File

@@ -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;

View File

@@ -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();
}
}
*/
}
}

View File

@@ -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:

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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

View File

@@ -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();
}
}

View File

@@ -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
}
}
}

View File

@@ -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;
};
}

View 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);
}
}}

View File

@@ -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 */

View File

@@ -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;
}
}}

View 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 */

View File

@@ -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++;
}
}
}

View File

@@ -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

View File

@@ -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;
};
}

View File

@@ -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()

View File

@@ -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.

View File

@@ -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
}
}
}

View File

@@ -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.

View File

@@ -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_ */

View File

@@ -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.
*/

View File

@@ -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_ */

View File

@@ -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;
}

View File

@@ -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).

View File

@@ -1,7 +0,0 @@
/*
* namedLockPattern.cpp
*/
#include "namedLockPattern.h"
//NOTE NamedLockPattern is template so implementation is in header file

View 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;

View File

@@ -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;
}

View File

@@ -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;
};
}}

View File

@@ -1,6 +1,6 @@
TOP = ..
include $(TOP)/configure/CONFIG
DIRS += utils
DIRS += client
#DIRS += client
DIRS += remote
include $(TOP)/configure/RULES_DIRS

View File

@@ -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()

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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[]) {

View File

@@ -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();

View File

@@ -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[]) {

View File

@@ -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[]) {

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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);

View File

@@ -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[])

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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;
}

View File

@@ -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());

View File

@@ -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;
}