diff --git a/pvAccessApp/client/pvAccess.h b/pvAccessApp/client/pvAccess.h
index 2758c93..c85a9da 100644
--- a/pvAccessApp/client/pvAccess.h
+++ b/pvAccessApp/client/pvAccess.h
@@ -32,6 +32,8 @@ namespace epics { namespace pvAccess {
enum ConnectionState {
NEVER_CONNECTED, CONNECTED, DISCONNECTED, DESTROYED
};
+
+ const char* ConnectionStateNames[] = { "NEVER_CONNECTED", "CONNECTED", "DISCONNECTED", "DESTROYED" };
class Channel;
@@ -118,7 +120,7 @@ namespace epics { namespace pvAccess {
* @author mrk
*
*/
- class ChannelFind {
+ class ChannelFind : public epics::pvData::Destroyable, private epics::pvData::NoDefaultMethods {
public:
virtual ChannelProvider* getChannelProvider() = 0;
virtual void cancelChannelFind() = 0;
@@ -403,7 +405,7 @@ namespace epics { namespace pvAccess {
* @param status Completion status.
* @param field The Structure for the request.
*/
- virtual void getDone(epics::pvData::Status *status,epics::pvData::Field *field) = 0;
+ virtual void getDone(epics::pvData::Status *status,epics::pvData::FieldConstPtr field) = 0;
};
@@ -592,6 +594,7 @@ namespace epics { namespace pvAccess {
*/
class ChannelAccess : private epics::pvData::NoDefaultMethods {
public:
+ virtual ~ChannelAccess() {};
/**
* Get the provider with the specified name.
@@ -617,7 +620,7 @@ namespace epics { namespace pvAccess {
* @author mrk
*
*/
- class ChannelProvider : private epics::pvData::NoDefaultMethods {
+ class ChannelProvider : public epics::pvData::Destroyable, private epics::pvData::NoDefaultMethods {
public:
/** Minimal priority. */
@@ -633,11 +636,6 @@ namespace epics { namespace pvAccess {
/** OPI priority. */
static const short PRIORITY_OPI = PRIORITY_MIN;
- /**
- * Terminate.
- */
- virtual void destroy() = 0;
-
/**
* Get the provider name.
* @return The name.
@@ -659,7 +657,7 @@ namespace epics { namespace pvAccess {
* @param priority channel priority, must be PRIORITY_MIN <= priority <= PRIORITY_MAX.
* @return Channel instance. If channel does not exist null is returned and channelRequester notified.
*/
- virtual Channel* createChannel(epics::pvData::String channelName,ChannelRequester *channelRequester,short priority) = 0;
+ virtual Channel* createChannel(epics::pvData::String channelName,ChannelRequester *channelRequester,short priority = PRIORITY_DEFAULT) = 0;
/**
* Create a channel.
@@ -684,7 +682,7 @@ namespace epics { namespace pvAccess {
* Get context implementation version.
* @return version of the context implementation.
*/
- virtual const Version* getVersion() = 0;
+ virtual Version* getVersion() = 0;
/**
* Initialize client context. This method is called immediately after instance construction (call of constructor).
@@ -695,7 +693,7 @@ namespace epics { namespace pvAccess {
* Get channel provider implementation.
* @return the channel provider.
*/
- virtual const ChannelProvider* getProvider() = 0;
+ virtual ChannelProvider* getProvider() = 0;
/**
* Prints detailed information about the context to the standard output stream.
diff --git a/testApp/client/MockClientImpl.cpp b/testApp/client/MockClientImpl.cpp
index 5bb0392..5558625 100644
--- a/testApp/client/MockClientImpl.cpp
+++ b/testApp/client/MockClientImpl.cpp
@@ -4,14 +4,242 @@
#include
#include
+#include
+#include
+#include
using namespace epics::pvData;
using namespace epics::pvAccess;
+static volatile int64 mockChannel_totalConstruct = 0;
+static volatile int64 mockChannel_totalDestruct = 0;
+static Mutex *mockChannel_globalMutex = 0;
+static int64 mockChannel_getTotalConstruct()
+{
+ Lock xx(mockChannel_globalMutex);
+ return mockChannel_totalConstruct;
+}
+
+static int64 mockChannel_getTotalDestruct()
+{
+ Lock xx(mockChannel_globalMutex);
+ return mockChannel_totalDestruct;
+}
+
+static ConstructDestructCallback *mockChannel_pConstructDestructCallback;
+
+static void mockChannel_init()
+{
+ static Mutex mutex = Mutex();
+ Lock xx(&mutex);
+ if(mockChannel_globalMutex==0) {
+ mockChannel_globalMutex = new Mutex();
+ mockChannel_pConstructDestructCallback = new ConstructDestructCallback(
+ String("mockChannel"),
+ mockChannel_getTotalConstruct,mockChannel_getTotalDestruct,0);
+ }
+}
+
+
+class MockChannel : public Channel {
+ private:
+ ChannelProvider* m_provider;
+ ChannelRequester* m_requester;
+ String m_name;
+ String m_remoteAddress;
+
+ PVStructure* pvStructure;
+
+ private:
+ ~MockChannel()
+ {
+ delete pvStructure;
+
+ Lock xx(mockChannel_globalMutex);
+ mockChannel_totalDestruct++;
+ }
+
+ public:
+
+ MockChannel(
+ ChannelProvider* provider,
+ ChannelRequester* requester,
+ String name,
+ String remoteAddress) :
+ m_provider(provider),
+ m_requester(requester),
+ m_name(name),
+ m_remoteAddress(remoteAddress)
+ {
+ mockChannel_init();
+
+ Lock xx(mockChannel_globalMutex);
+ mockChannel_totalConstruct++;
+
+
+ ScalarType stype = pvDouble;
+ String allProperties("alarm,timeStamp,display,control,valueAlarm");
+
+ pvStructure = getStandardPVField()->scalar(
+ 0,name,stype,allProperties);
+ PVDouble *pvField = pvStructure->getDoubleField(String("value"));
+ pvField->put(1.123e35);
+
+
+ // already connected, report state
+ m_requester->channelStateChange(this, CONNECTED);
+ }
+
+ virtual void destroy()
+ {
+ delete this;
+ };
+
+ virtual String getRequesterName()
+ {
+ return getChannelName();
+ };
+
+ virtual void message(String message,MessageType messageType)
+ {
+ std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl;
+ }
+
+ virtual ChannelProvider* getProvider()
+ {
+ return m_provider;
+ }
+
+ virtual epics::pvData::String getRemoteAddress()
+ {
+ return m_remoteAddress;
+ }
+
+ virtual epics::pvData::String getChannelName()
+ {
+ return m_name;
+ }
+
+ virtual ChannelRequester* getChannelRequester()
+ {
+ return m_requester;
+ }
+
+ virtual ConnectionState getConnectionState()
+ {
+ return CONNECTED;
+ }
+
+ virtual bool isConnected()
+ {
+ return getConnectionState() == CONNECTED;
+ }
+
+ virtual AccessRights getAccessRights(epics::pvData::PVField *pvField)
+ {
+ return readWrite;
+ }
+
+ virtual void getField(GetFieldRequester *requester,epics::pvData::String subField)
+ {
+ requester->getDone(getStatusCreate()->getStatusOK(),pvStructure->getSubField(subField)->getField());
+ }
+
+ virtual ChannelProcess* createChannelProcess(
+ ChannelProcessRequester *channelProcessRequester,
+ epics::pvData::PVStructure *pvRequest)
+ {
+ // TODO
+ return 0;
+ }
+
+ virtual ChannelGet* createChannelGet(
+ ChannelGetRequester *channelGetRequester,
+ epics::pvData::PVStructure *pvRequest)
+ {
+ // TODO
+ return 0;
+ }
+
+ virtual ChannelPut* createChannelPut(
+ ChannelPutRequester *channelPutRequester,
+ epics::pvData::PVStructure *pvRequest)
+ {
+ // TODO
+ return 0;
+ }
+
+ virtual ChannelPutGet* createChannelPutGet(
+ ChannelPutGetRequester *channelPutGetRequester,
+ epics::pvData::PVStructure *pvRequest)
+ {
+ // TODO
+ return 0;
+ }
+
+ virtual ChannelRPC* createChannelRPC(ChannelRPCRequester *channelRPCRequester,
+ epics::pvData::PVStructure *pvRequest)
+ {
+ // TODO
+ return 0;
+ }
+
+ virtual epics::pvData::Monitor* createMonitor(
+ epics::pvData::MonitorRequester *monitorRequester,
+ epics::pvData::PVStructure *pvRequest)
+ {
+ // TODO
+ return 0;
+ }
+
+ virtual ChannelArray* createChannelArray(
+ ChannelArrayRequester *channelArrayRequester,
+ epics::pvData::PVStructure *pvRequest)
+ {
+ // TODO
+ return 0;
+ }
+};
+
+class MockChannelProvider;
+
+class MockChannelFind : public ChannelFind
+{
+ public:
+ MockChannelFind(ChannelProvider* provider) : m_provider(provider)
+ {
+ }
+
+ virtual void destroy()
+ {
+ // one instance for all, do not delete at all
+ }
+
+ virtual ChannelProvider* getChannelProvider()
+ {
+ return m_provider;
+ };
+
+ virtual void cancelChannelFind()
+ {
+ throw std::runtime_error("not supported");
+ }
+
+ private:
+
+ // only to be destroyed by it
+ friend class MockChannelProvider;
+ virtual ~MockChannelFind() {}
+
+ ChannelProvider* m_provider;
+};
class MockChannelProvider : public ChannelProvider {
-public:
+ public:
+
+ MockChannelProvider() : m_mockChannelFind(new MockChannelFind(this)) {
+ }
virtual epics::pvData::String getProviderName()
{
@@ -20,6 +248,7 @@ public:
virtual void destroy()
{
+ delete m_mockChannelFind;
delete this;
}
@@ -27,9 +256,8 @@ public:
epics::pvData::String channelName,
ChannelFindRequester *channelFindRequester)
{
- ChannelFind* channelFind = 0; // TODO
- channelFindRequester->channelFindResult(getStatusCreate()->getStatusOK(), channelFind, true);
- return channelFind;
+ channelFindRequester->channelFindResult(getStatusCreate()->getStatusOK(), m_mockChannelFind, true);
+ return m_mockChannelFind;
}
virtual Channel* createChannel(
@@ -48,15 +276,15 @@ public:
{
if (address == "local")
{
- Channel* channel = 0;
+ Channel* channel = new MockChannel(this, channelRequester, channelName, address);
channelRequester->channelCreated(getStatusCreate()->getStatusOK(), channel);
- // TODO state change
return channel;
}
else
{
Status* errorStatus = getStatusCreate()->createStatus(STATUSTYPE_ERROR, "only local supported", 0);
channelRequester->channelCreated(errorStatus, 0);
+ delete errorStatus; // TODO guard from CB
return 0;
}
}
@@ -64,6 +292,8 @@ public:
private:
~MockChannelProvider() {};
+ MockChannelFind* m_mockChannelFind;
+
};
@@ -78,11 +308,11 @@ class MockClientContext : public ClientContext
initialize();
}
- virtual const Version* getVersion() {
+ virtual Version* getVersion() {
return m_version;
}
- virtual const ChannelProvider* getProvider() {
+ virtual ChannelProvider* getProvider() {
return m_provider;
}
@@ -120,12 +350,98 @@ class MockClientContext : public ClientContext
};
+class ChannelFindRequesterImpl : public ChannelFindRequester
+{
+ virtual void channelFindResult(epics::pvData::Status *status,ChannelFind *channelFind,bool wasFound)
+ {
+ std::cout << "[ChannelFindRequesterImpl] channelFindResult(";
+ String str;
+ status->toString(&str);
+ std::cout << str << ", ..., " << wasFound << ")" << std::endl;
+ }
+};
+
+class ChannelRequesterImpl : public ChannelRequester
+{
+ virtual String getRequesterName()
+ {
+ return "ChannelRequesterImpl";
+ };
+
+ virtual void message(String message,MessageType messageType)
+ {
+ std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl;
+ }
+
+ virtual void channelCreated(epics::pvData::Status* status, Channel *channel)
+ {
+ std::cout << "channelCreated(";
+ String str;
+ status->toString(&str);
+ std::cout << str << ", " << (channel ? channel->getChannelName() : "(null)") << ")" << std::endl;
+ }
+
+ virtual void channelStateChange(Channel *c, ConnectionState connectionState)
+ {
+ std::cout << "channelStateChange(" << c->getChannelName() << ", " << ConnectionStateNames[connectionState] << ")" << std::endl;
+ }
+};
+
+class GetFieldRequesterImpl : public GetFieldRequester
+{
+ virtual String getRequesterName()
+ {
+ return "GetFieldRequesterImpl";
+ };
+
+ virtual void message(String message,MessageType messageType)
+ {
+ std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl;
+ }
+
+ virtual void getDone(epics::pvData::Status *status,epics::pvData::FieldConstPtr field)
+ {
+ std::cout << "getDone(";
+ String str;
+ status->toString(&str);
+ std::cout << str << ", ";
+ if (field)
+ {
+ str.clear();
+ field->toString(&str);
+ std::cout << str;
+ }
+ else
+ std::cout << "(null)";
+ std::cout << ")" << std::endl;
+ }
+};
+
int main(int argc,char *argv[])
{
MockClientContext* context = new MockClientContext();
context->printInfo();
+
+ ChannelFindRequesterImpl findRequester;
+ context->getProvider()->channelFind("something", &findRequester);
+
+ ChannelRequesterImpl channelRequester;
+ /*Channel* noChannel =*/ context->getProvider()->createChannel("test", &channelRequester, ChannelProvider::PRIORITY_DEFAULT, "over the rainbow");
+
+ Channel* channel = context->getProvider()->createChannel("test", &channelRequester);
+ std::cout << channel->getChannelName() << std::endl;
+
+ GetFieldRequesterImpl getFieldRequesterImpl;
+ channel->getField(&getFieldRequesterImpl, "timeStamp.secondsPastEpoch");
+
+ channel->destroy();
+
+
context->destroy();
+
+ std::cout << "-----------------------------------------------------------------------" << std::endl;
+ getShowConstructDestruct()->constuctDestructTotals(stdout);
return(0);
}