Files
pvData/pvDataApp/misc/StatusCreateFactory.cpp
2011-01-12 10:28:00 -05:00

216 lines
4.6 KiB
C++

/*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 <cstddef>
#include <cstdlib>
#include <string>
#include <cstdio>
#include "lock.h"
#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;
static bool notInited = true;
static int64 getTotalConstruct()
{
Lock xx(&globalMutex);
return totalConstruct;
}
static int64 getTotalDestruct()
{
Lock xx(&globalMutex);
return totalDestruct;
}
static void init()
{
Lock xx(&globalMutex);
if(notInited) {
notInited = false;
ShowConstructDestruct::registerCallback(
String("status"),
getTotalConstruct,getTotalDestruct,0,0);
}
}
class StatusImpl : public Status
{
public:
StatusImpl(StatusType type, String message) :
m_type(type), m_message(message)
{
Lock xx(&globalMutex);
totalConstruct++;
}
StatusImpl(StatusType type, String message, String stackDump) :
m_type(type), m_message(message), m_stackDump(stackDump)
{
Lock xx(&globalMutex);
totalConstruct++;
}
virtual ~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 String toString()
{
String str;
toString(&str, 0);
return str;
}
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);
}
~StatusCreateImpl()
{
delete m_ok;
}
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;
Lock xx(&mutex);
if(statusCreate==0) statusCreate = new StatusCreateImpl();
return statusCreate;
}
}}