diff --git a/configure/CONFIG_SITE b/configure/CONFIG_SITE index 72b399d..f3bfd36 100644 --- a/configure/CONFIG_SITE +++ b/configure/CONFIG_SITE @@ -8,14 +8,6 @@ # CONFIG_SITE.Common.$(T_A) # CONFIG_SITE.$(EPICS_HOST_ARCH).$(T_A) -# CHECK_RELEASE controls the consistency checking of the support -# applications pointed to by the RELEASE* files. -# Normally CHECK_RELEASE should be set to YES. -# Set CHECK_RELEASE to NO to disable checking completely. -# Set CHECK_RELEASE to WARN to perform consistency checking but -# continue building anyway if conflicts are found. -CHECK_RELEASE = YES - # Set this when you only want to compile this application # for a subset of the cross-compiled target architectures # that Base is built for. diff --git a/configure/Makefile b/configure/Makefile index 9254309..1cd830e 100644 --- a/configure/Makefile +++ b/configure/Makefile @@ -2,6 +2,14 @@ TOP=.. include $(TOP)/configure/CONFIG +# CHECK_RELEASE controls the consistency checking of the support +# applications pointed to by the RELEASE* files. +# Normally CHECK_RELEASE should be set to YES. +# Set CHECK_RELEASE to NO to disable checking completely. +# Set CHECK_RELEASE to WARN to perform consistency checking but +# continue building anyway if conflicts are found. +CHECK_RELEASE = YES + TARGETS = $(CONFIG_TARGETS) CONFIGS += $(subst ../,,$(wildcard $(CONFIG_INSTALLS))) diff --git a/testApp/client/MockClientImpl.cpp b/testApp/client/MockClientImpl.cpp index 4828643..bc825f2 100644 --- a/testApp/client/MockClientImpl.cpp +++ b/testApp/client/MockClientImpl.cpp @@ -11,6 +11,189 @@ using namespace epics::pvData; using namespace epics::pvAccess; + + + + + + + +static volatile int64 mockChannelProcess_totalConstruct = 0; +static volatile int64 mockChannelProcess_totalDestruct = 0; +static Mutex *mockChannelProcess_globalMutex = 0; + +static int64 mockChannelProcess_processTotalConstruct() +{ + Lock xx(mockChannelProcess_globalMutex); + return mockChannelProcess_totalConstruct; +} + +static int64 mockChannelProcess_processTotalDestruct() +{ + Lock xx(mockChannelProcess_globalMutex); + return mockChannelProcess_totalDestruct; +} + +static ConstructDestructCallback *mockChannelProcess_pConstructDestructCallback; + +static void mockChannelProcess_init() +{ + static Mutex mutex = Mutex(); + Lock xx(&mutex); + if(mockChannelProcess_globalMutex==0) { + mockChannelProcess_globalMutex = new Mutex(); + mockChannelProcess_pConstructDestructCallback = new ConstructDestructCallback( + String("mockChannelProcess"), + mockChannelProcess_processTotalConstruct,mockChannelProcess_processTotalDestruct,0); + } +} + +class MockChannelProcess : public ChannelProcess +{ + private: + ChannelProcessRequester* m_channelProcessRequester; + PVStructure* m_pvStructure; + PVScalar* m_valueField; + + private: + ~MockChannelProcess() + { + Lock xx(mockChannelProcess_globalMutex); + mockChannelProcess_totalDestruct++; + } + + public: + MockChannelProcess(ChannelProcessRequester* channelProcessRequester, PVStructure *pvStructure, PVStructure *pvRequest) : + m_channelProcessRequester(channelProcessRequester), m_pvStructure(pvStructure) + { + mockChannelProcess_init(); + + Lock xx(mockChannelProcess_globalMutex); + mockChannelProcess_totalConstruct++; + + + PVField* field = pvStructure->getSubField(String("value")); + if (field == 0) + { + Status* noValueFieldStatus = getStatusCreate()->createStatus(STATUSTYPE_ERROR, "no 'value' field"); + m_channelProcessRequester->channelProcessConnect(noValueFieldStatus, this); + delete noValueFieldStatus; + + // NOTE client must destroy this instance... + // do not access any fields and return ASAP + return; + } + + if (field->getField()->getType() != scalar) + { + Status* notAScalarStatus = getStatusCreate()->createStatus(STATUSTYPE_ERROR, "'value' field not scalar type"); + m_channelProcessRequester->channelProcessConnect(notAScalarStatus, this); + delete notAScalarStatus; + + // NOTE client must destroy this instance…. + // do not access any fields and return ASAP + return; + } + + m_valueField = static_cast(field); + + // TODO pvRequest + m_channelProcessRequester->channelProcessConnect(getStatusCreate()->getStatusOK(), this); + } + + virtual void process(bool lastRequest) + { + switch (m_valueField->getScalar()->getScalarType()) + { + case pvBoolean: + { + // negate + PVBoolean *pvBoolean = static_cast(m_valueField); + pvBoolean->put(!pvBoolean->get()); + break; + } + case pvByte: + { + // increment by one + PVByte *pvByte = static_cast(m_valueField); + pvByte->put(pvByte->get() + 1); + break; + } + case pvShort: + { + // increment by one + PVShort *pvShort = static_cast(m_valueField); + pvShort->put(pvShort->get() + 1); + break; + } + case pvInt: + { + // increment by one + PVInt *pvInt = static_cast(m_valueField); + pvInt->put(pvInt->get() + 1); + break; + } + case pvLong: + { + // increment by one + PVLong *pvLong = static_cast(m_valueField); + pvLong->put(pvLong->get() + 1); + break; + } + case pvFloat: + { + // increment by one + PVFloat *pvFloat = static_cast(m_valueField); + pvFloat->put(pvFloat->get() + 1.0f); + break; + } + case pvDouble: + { + // increment by one + PVDouble *pvDouble = static_cast(m_valueField); + pvDouble->put(pvDouble->get() + 1.0); + break; + } + case pvString: + { + // increment by one + PVString *pvString = static_cast(m_valueField); + String val = pvString->get(); + if (val.empty()) + pvString->put("gen0"); + else + { + char c = val[0]; + c++; + pvString->put("gen" + c); + } + break; + } + default: + // noop + break; + + } + m_channelProcessRequester->processDone(getStatusCreate()->getStatusOK()); + + if (lastRequest) + destroy(); + } + + virtual void destroy() + { + delete this; + } + +}; + + + + + + + + static volatile int64 mockChannelGet_totalConstruct = 0; static volatile int64 mockChannelGet_totalDestruct = 0; static Mutex *mockChannelGet_globalMutex = 0; @@ -401,7 +584,7 @@ class MockChannel : public Channel { m_pvStructure = getStandardPVField()->scalar( 0,name,stype,allProperties); PVDouble *pvField = m_pvStructure->getDoubleField(String("value")); - pvField->put(1.123e35); + pvField->put(1.123); // already connected, report state @@ -468,8 +651,7 @@ class MockChannel : public Channel { ChannelProcessRequester *channelProcessRequester, epics::pvData::PVStructure *pvRequest) { - // TODO - return 0; + return new MockChannelProcess(channelProcessRequester, m_pvStructure, pvRequest); } virtual ChannelGet* createChannelGet( @@ -857,6 +1039,36 @@ class MonitorRequesterImpl : public MonitorRequester }; +class ChannelProcessRequesterImpl : public ChannelProcessRequester +{ + ChannelProcess *m_channelProcess; + + virtual String getRequesterName() + { + return "ProcessRequesterImpl"; + }; + + virtual void message(String message,MessageType messageType) + { + std::cout << "[" << getRequesterName() << "] message(" << message << ", " << messageTypeName[messageType] << ")" << std::endl; + } + + virtual void channelProcessConnect(epics::pvData::Status *status,ChannelProcess *channelProcess) + { + std::cout << "channelProcessConnect(" << status->toString() << ")" << std::endl; + + // TODO sync + m_channelProcess = channelProcess; + } + + virtual void processDone(epics::pvData::Status *status) + { + std::cout << "processDone(" << status->toString() << ")" << std::endl; + } + +}; + + int main(int argc,char *argv[]) { MockClientContext* context = new MockClientContext(); @@ -894,10 +1106,18 @@ int main(int argc,char *argv[]) std::cout << "monitor->start() = " << status->toString() << std::endl; delete status; + + ChannelProcessRequesterImpl channelProcessRequester; + ChannelProcess* channelProcess = channel->createChannelProcess(&channelProcessRequester, 0); + channelProcess->process(false); + channelProcess->destroy(); + + status = monitor->stop(); std::cout << "monitor->stop() = " << status->toString() << std::endl; delete status; + monitor->destroy(); channel->destroy();