From e4ea15aff3fed9c534674e91998342d466c3076b Mon Sep 17 00:00:00 2001 From: Matej Sekoranja Date: Sun, 19 Dec 2010 21:17:59 +0100 Subject: [PATCH] Status factory added. --- pvDataApp/Makefile | 1 + pvDataApp/factory/StatusCreateFactory.cpp | 198 ++++++++++++++++++++++ pvDataApp/misc/destroyable.h | 6 + pvDataApp/misc/status.h | 52 +++++- 4 files changed, 253 insertions(+), 4 deletions(-) create mode 100644 pvDataApp/factory/StatusCreateFactory.cpp diff --git a/pvDataApp/Makefile b/pvDataApp/Makefile index e9b07ff..89e3d6d 100644 --- a/pvDataApp/Makefile +++ b/pvDataApp/Makefile @@ -83,6 +83,7 @@ LIBSRCS += PVDataCreateFactory.cpp LIBSRCS += Convert.cpp LIBSRCS += StandardField.cpp LIBSRCS += StandardPVField.cpp +LIBSRCS += StatusCreateFactory.cpp SRC_DIRS += $(PVDATA)/property diff --git a/pvDataApp/factory/StatusCreateFactory.cpp b/pvDataApp/factory/StatusCreateFactory.cpp new file mode 100644 index 0000000..f18a0f9 --- /dev/null +++ b/pvDataApp/factory/StatusCreateFactory.cpp @@ -0,0 +1,198 @@ +/*StatusCreateFactory.cpp*/ +/** + * Copyright - See the COPYRIGHT that is included with this distribution. + * EPICS pvDataCPP is distributed subject to a Software License Agreement found + * in file LICENSE that is included with this distribution. + */ +#include +#include +#include +#include +#include +#include "factory.h" +#include "byteBuffer.h" +#include "showConstructDestruct.h" +#include "status.h" +#include "serializeHelper.h" + +namespace epics { namespace pvData { + +//static DebugLevel debugLevel = lowDebug; + +static volatile int64 totalConstruct = 0; +static volatile int64 totalDestruct = 0; +static Mutex *globalMutex = 0; + +static int64 getTotalConstruct() +{ + Lock xx(globalMutex); + return totalConstruct; +} + +static int64 getTotalDestruct() +{ + Lock xx(globalMutex); + return totalDestruct; +} + +static ConstructDestructCallback *pConstructDestructCallback; + +static void init() +{ + static Mutex mutex = Mutex(); + Lock xx(&mutex); + if(globalMutex==0) { + globalMutex = new Mutex(); + pConstructDestructCallback = new ConstructDestructCallback( + String("status"), + getTotalConstruct,getTotalDestruct,0); + } +} + +class StatusImpl : public Status +{ + public: + + StatusImpl(StatusType type, String message, String stackDump) : + m_type(type), m_message(message), m_stackDump(stackDump) + { + Lock xx(globalMutex); + totalConstruct++; + } + + ~StatusImpl() { + Lock xx(globalMutex); + totalDestruct++; + } + + virtual StatusType getType() + { + return m_type; + } + + + virtual epics::pvData::String getMessage() + { + return m_message; + } + + virtual epics::pvData::String getStackDump() + { + return m_stackDump; + } + + virtual bool isOK() + { + return (m_type == STATUSTYPE_OK); + } + + virtual bool isSuccess() + { + return (m_type == STATUSTYPE_OK || m_type == STATUSTYPE_WARNING); + } + + virtual void serialize(ByteBuffer *buffer, SerializableControl *flusher) + { + flusher->ensureBuffer(1); + if (this == getStatusCreate()->getStatusOK()) + { + // special code for okStatus (optimization) + buffer->putByte((int8)-1); + } + else + { + buffer->putByte((int8)m_type); + SerializeHelper::serializeString(m_message, buffer, flusher); + SerializeHelper::serializeString(m_stackDump, buffer, flusher); + } + } + + virtual void deserialize(ByteBuffer *pbuffer, DeserializableControl *pflusher) + { + throw new std::runtime_error("use getStatusCreate()->deserialize()"); + } + + virtual void toString(StringBuilder buffer, int indentLevel) + { + *buffer += "StatusImpl [type="; + *buffer += StatusTypeName[m_type]; + if (!m_message.empty()) + { + *buffer += ", message="; + *buffer += m_message; + } + if (!m_stackDump.empty()) + { + *buffer += ", stackDump="; + *buffer += '\n'; + *buffer += m_stackDump; + } + *buffer += ']'; + } + + private: + + StatusType m_type; + String m_message; + String m_stackDump; + +}; + + + + +class StatusCreateImpl : public StatusCreate { + public: + + StatusCreateImpl() + { + init(); + m_ok = createStatus(STATUSTYPE_OK, "OK", 0); + } + + virtual Status* getStatusOK() { + return m_ok; + } + + virtual Status* createStatus(StatusType type, String message, BaseException* cause) { + if (cause == 0) + return new StatusImpl(type, message, ""); + else + { + std::string stackDump; + cause->toString(stackDump); + return new StatusImpl(type, message, stackDump); + } + } + + virtual Status* deserializeStatus(ByteBuffer* buffer, DeserializableControl* control) { + control->ensureData(1); + int8 typeCode = buffer->getByte(); + if (typeCode == (int8)-1) + return m_ok; + else { + String message = SerializeHelper::deserializeString(buffer, control); + String stackDump = SerializeHelper::deserializeString(buffer, control); + return new StatusImpl((StatusType)typeCode, message, stackDump); + } + } + + private: + + Status* m_ok; +}; + + + + +static StatusCreate* statusCreate = 0; + +StatusCreate* getStatusCreate() { + static Mutex mutex = Mutex(); + Lock xx(&mutex); + + if(statusCreate==0) statusCreate = new StatusCreateImpl(); + return statusCreate; +} + +}} diff --git a/pvDataApp/misc/destroyable.h b/pvDataApp/misc/destroyable.h index e2a63a3..0f5b7ed 100644 --- a/pvDataApp/misc/destroyable.h +++ b/pvDataApp/misc/destroyable.h @@ -19,6 +19,12 @@ namespace epics { namespace pvData { * Destroy this instance. */ virtual void destroy() = 0; + + private: + /** + * Do not allow delete on this instance. + */ + //~Destroyable() {}; }; }} diff --git a/pvDataApp/misc/status.h b/pvDataApp/misc/status.h index 6d2ca45..5e9b38b 100644 --- a/pvDataApp/misc/status.h +++ b/pvDataApp/misc/status.h @@ -8,6 +8,8 @@ #define STATUS_H #include "serialize.h" +#include "epicsException.h" +#include "byteBuffer.h" namespace epics { namespace pvData { @@ -16,14 +18,16 @@ namespace epics { namespace pvData { */ enum StatusType { /** Operation completed successfully. */ - OK, + STATUSTYPE_OK, /** Operation completed successfully, but there is a warning message. */ - WARNING, + STATUSTYPE_WARNING, /** Operation failed due to an error. */ - ERROR, + STATUSTYPE_ERROR, /** Operation failed due to an unexpected error. */ - FATAL + STATUSTYPE_FATAL }; + + const char* StatusTypeName[] = { "OK", "WARNING", "ERROR", "FATAL" }; /** * Status interface. @@ -64,7 +68,47 @@ namespace epics { namespace pvData { * @return operation success status. */ virtual bool isSuccess() = 0; + + + virtual void toString(StringBuilder buffer, int indentLevel = 0) = 0; + }; + + /** + * Interface for creating status. + * @author mse + */ + class StatusCreate : private epics::pvData::NoDefaultMethods { + public: + /** + * Get OK status. Static instance should be returned. + * @return OK Status instance. + */ + virtual Status* getStatusOK() = 0; + + /** + * Create status. + * @param type status type, non-null. + * @param message message describing an error, non-null. + * NOTE: Do NOT use throwable.getMessage() as message, since it will be supplied with the cause. + * @param cause exception that caused an error. Optional. + * @return status instance. + */ + virtual Status* createStatus(StatusType type, String message, BaseException* cause) = 0; + + /** + * Deserialize status. + * NOTE: use this method instead of Status.deserialize(), since this allows OK status optimization. + * @param buffer deserialization buffer. + * @param control deserialization control. + * @return status instance. + */ + virtual Status* deserializeStatus(ByteBuffer* buffer, DeserializableControl* control) = 0; + }; + + extern StatusCreate* getStatusCreate(); + + }} #endif /* STATUS_H */