blob: f93aa83b5d1358d3c40be7f8c5060dfb79da1b9e [file] [log] [blame]
/*=========================================================================
* Copyright (c) 2004-2014 Pivotal Software, Inc. All Rights Reserved.
* This product is protected by U.S. and international copyright
* and intellectual property laws. Pivotal products are covered by
* more patents listed at http://www.pivotal.io/patents.
*=========================================================================
*/
#include "../gfcpp_globals.hpp"
#include <ace/Atomic_Op_T.h>
#include <ace/Recursive_Thread_Mutex.h>
#include <ace/OS_NS_stdio.h>
#include "AtomicStatisticsImpl.hpp"
#include "StatisticsTypeImpl.hpp"
#include "StatisticDescriptorImpl.hpp"
using namespace gemfire_statistics;
/**
* An implementation of {@link Statistics} that stores its statistics
* in local memory and supports atomic operations.
*
*/
////////////////////// Static Methods //////////////////////
int64 AtomicStatisticsImpl::calcNumericId(StatisticsFactory* system, int64 userValue)
{
int64 result;
if (userValue != 0)
{
result = userValue;
}
else
{
result = system->getId();
}
return result;
}
const char* AtomicStatisticsImpl::calcTextId(StatisticsFactory* system, const char* userValue)
{
if(userValue != NULL && strcmp(userValue, "") != 0 )
{
return userValue;
}
else
{
if (system != NULL)
{
return system->getName();
}
else
{
return "";
}
}
}
/////////////////////// Constructors ///////////////////////
/**
* Creates a new statistics instance of the given type
*
* @param type
* A description of the statistics
* @param textId
* Text that identifies this statistic when it is monitored
* @param numericId
* A number that displayed when this statistic is monitored
* @param uniqueId
* A number that uniquely identifies this instance
* @param system
* The distributed system that determines whether or not these
* statistics are stored (and collected) in local memory
*/
AtomicStatisticsImpl::AtomicStatisticsImpl(StatisticsType* typeArg,
const char* textIdArg,
int64 numericIdArg,
int64 uniqueIdArg,
StatisticsFactory* system)
{
try
{
this->textId = calcTextId(system, textIdArg);
std::string tmp(this->textId);
textIdStr = tmp;
this->numericId = calcNumericId(system, numericIdArg);
this->uniqueId = uniqueIdArg;
this->closed = false;
this->statsType = dynamic_cast<StatisticsTypeImpl*>(typeArg);
GF_D_ASSERT(this->statsType != NULL);
int32 intCount = statsType->getIntStatCount();
int32 longCount = statsType->getLongStatCount();
int32 doubleCount = statsType->getDoubleStatCount();
if (intCount > 0)
{
intStorage = new int32[intCount];
for( int32 i = 0; i < intCount; i++ )
{
intStorage[i] = 0; //Un-initialized state
}
}
else
{
intStorage = NULL;
}
if (longCount > 0)
{
longStorage = new ACE_Atomic_Op<ACE_Recursive_Thread_Mutex, int64>[longCount];
for(int32 i=0; i< longCount; i++)
{
longStorage[i] = 0;//Un-initialized state
}
}
else
{
longStorage = NULL;
}
if (doubleCount > 0)
{
doubleStorage = new ACE_Atomic_Op<ACE_Recursive_Thread_Mutex, double>[doubleCount];
for(int32 i=0; i< doubleCount; i++)
{
doubleStorage[i] = 0;//Un-initialized state
}
}
else
{
doubleStorage = NULL;
}
}
catch(...)
{
statsType = NULL; //Will be deleted by the class who calls this ctor
}
}
AtomicStatisticsImpl::~AtomicStatisticsImpl()
{
try
{
statsType = NULL;
if (intStorage != NULL)
{
delete[] intStorage;
intStorage = NULL;
}
if (longStorage != NULL)
{
delete[] longStorage;
longStorage = NULL;
}
if ( doubleStorage != NULL)
{
delete[] doubleStorage;
doubleStorage = NULL;
}
}
catch(...)
{
}
}
////////////////////// Instance Methods //////////////////////
bool AtomicStatisticsImpl::isShared()
{
return false;
}
bool AtomicStatisticsImpl::isAtomic()
{
return true;//will always be true for this class
}
void AtomicStatisticsImpl::close()
{
//Just mark closed,Will be actually deleted when token written in archive file.
closed = true;
}
//////////////////////// store() Methods ///////////////////////
void AtomicStatisticsImpl::_setInt(int32 offset, int32 value)
{
if(offset >= statsType->getIntStatCount())
{
char s[128] = {'\0'};
ACE_OS::snprintf(s, 128, "setInt:The id (%d) of the Statistic Descriptor is not valid ", offset);
throw IllegalArgumentException(s);
}
intStorage[offset] = value;
}
void AtomicStatisticsImpl::_setLong(int32 offset, int64 value)
{
if(offset >=statsType->getLongStatCount())
{
char s[128] = {'\0'};
/* adongre - Coverity II
* CID 29273: Calling risky function (SECURE_CODING)[VERY RISKY]. Using "sprintf" can cause a
* buffer overflow when done incorrectly. Because sprintf() assumes an arbitrarily long string,
* callers must be careful not to overflow the actual space of the destination.
* Use snprintf() instead, or correct precision specifiers.
* Fix : using ACE_OS::snprintf
*/
//sprintf(s, "setLong:The id (%d) of the Statistic Descriptor is not valid ", offset);
ACE_OS::snprintf(s, 128, "setLong:The id (%d) of the Statistic Descriptor is not valid ", offset);
throw IllegalArgumentException(s);
}
longStorage[offset] = value;
}
void AtomicStatisticsImpl::_setDouble(int32 offset, double value)
{
if(offset >= statsType->getDoubleStatCount())
{
char s[128] = {'\0'};
ACE_OS::snprintf(s, 128, "setDouble:The id (%d) of the Statistic Descriptor is not valid ", offset);
throw IllegalArgumentException(s);
}
doubleStorage[offset] = value;
}
/////////////////////// get() Methods ///////////////////////
int32 AtomicStatisticsImpl::_getInt(int32 offset)
{
if(offset >= statsType->getIntStatCount())
{
char s[128] = {'\0'};
ACE_OS::snprintf(s, 128, "getInt:The id (%d) of the Statistic Descriptor is not valid ", offset);
throw IllegalArgumentException(s);
}
return intStorage[offset];
}
int64 AtomicStatisticsImpl::_getLong(int32 offset)
{
if(offset >= statsType->getLongStatCount())
{
char s[128] = {'\0'};
ACE_OS::snprintf(s, 128, "getLong:The id (%d) of the Statistic Descriptor is not valid ", offset);
throw IllegalArgumentException(s);
}
return longStorage[offset].value();
}
double AtomicStatisticsImpl::_getDouble(int32 offset)
{
if(offset >= statsType->getDoubleStatCount())
{
char s[128] = {'\0'};
ACE_OS::snprintf(s, 128, "getDouble:The id (%d) of the Statistic Descriptor is not valid ", offset);
throw IllegalArgumentException(s);
}
return doubleStorage[offset].value();
}
int64 AtomicStatisticsImpl::_getRawBits(StatisticDescriptor* statDscp)
{
StatisticDescriptorImpl* stat = dynamic_cast<StatisticDescriptorImpl*>(statDscp);
switch (stat->getTypeCode())
{
case INT_TYPE:
return getInt(stat->getId());
case LONG_TYPE:
return _getLong(stat->getId());
case DOUBLE_TYPE:
{
double value = _getDouble(stat->getId());
int64* temp = reinterpret_cast <int64*>(&value);
return *temp;
}
default: return 0;
/*throw new RuntimeException("unexpected stat descriptor type code: " +
stat->getTypeCode());*/
}
}
int64 AtomicStatisticsImpl::getRawBits(char* name)
{
return getRawBits(nameToDescriptor(name));
}
int64 AtomicStatisticsImpl::getRawBits(StatisticDescriptor* descriptor)
{
if (isOpen())
{
return _getRawBits(descriptor);
}
else
{
return 0;
}
}
//////////////////////// inc() Methods ////////////////////////
int32 AtomicStatisticsImpl::_incInt(int32 offset, int32 delta)
{
if(offset >= statsType->getIntStatCount())
{
char s[128] = {'\0'};
ACE_OS::snprintf(s, 128, "incInt:The id (%d) of the Statistic Descriptor is not valid ", offset);
throw IllegalArgumentException(s);
}
// return ( intStorage[offset] += delta);
#ifdef _WIN32
return InterlockedExchangeAdd((volatile LONG*)&(intStorage[offset]), delta) + delta;
#else
#if defined(_LINUX) || defined(_X86_SOLARIS)
return HostAsm::InterlockedExchangeAdd((volatile int32_t*)&(intStorage[offset]), delta) + delta;
#else
#ifdef _SPARC_SOLARIS
return InterlockedExchangeAdd((volatile int32_t*)&(intStorage[offset]), delta) + delta;
#else
//return 1;
//+++ porting error
#endif
#endif
#endif
}
int64 AtomicStatisticsImpl::_incLong(int32 offset, int64 delta)
{
if(offset >= statsType->getLongStatCount())
{
char s[128] = {'\0'};
/* adongre - Coverity II
* CID 29273: Calling risky function (SECURE_CODING)[VERY RISKY]. Using "sprintf" can cause a
* buffer overflow when done incorrectly. Because sprintf() assumes an arbitrarily long string,
* callers must be careful not to overflow the actual space of the destination.
* Use snprintf() instead, or correct precision specifiers.
* Fix : using ACE_OS::snprintf
*/
//sprintf(s, "incLong:The id (%d) of the Statistic Descriptor is not valid ", offset);
ACE_OS::snprintf(s, 128, "incLong:The id (%d) of the Statistic Descriptor is not valid ", offset);
throw IllegalArgumentException(s);
}
return ( longStorage[offset] += delta);
}
double AtomicStatisticsImpl::_incDouble(int32 offset, double delta)
{
if(offset >= statsType->getDoubleStatCount())
{
char s[128] = {'\0'};
ACE_OS::snprintf(s, 128, "incDouble:The id (%d) of the Statistic Descriptor is not valid ", offset);
throw IllegalArgumentException(s);
}
return ( doubleStorage[offset] += delta);
}
/**************************Base class methods ********************/
////////////////////// Instance Methods //////////////////////
int32 AtomicStatisticsImpl::nameToId(const char* name)
{
return statsType->nameToId(name);
}
StatisticDescriptor* AtomicStatisticsImpl::nameToDescriptor(const char* name)
{
return statsType->nameToDescriptor(name);
}
bool AtomicStatisticsImpl::isClosed()
{
return closed;
}
bool AtomicStatisticsImpl::isOpen()
{
return !closed;
}
//////////////////////// attribute Methods ///////////////////////
StatisticsType* AtomicStatisticsImpl::getType()
{
return statsType;
}
const char* AtomicStatisticsImpl::getTextId()
{
return textIdStr.c_str();
}
int64 AtomicStatisticsImpl::getNumericId()
{
return numericId;
}
/**
* Gets the unique id for this resource
*/
int64 AtomicStatisticsImpl::getUniqueId()
{
return uniqueId;
}
//////////////////////// set() Methods ///////////////////////
void AtomicStatisticsImpl::setInt(char* name, int32 value)
{
int32 id = getIntId(nameToDescriptor(name));
setInt( id, value );
}
void AtomicStatisticsImpl::setInt(StatisticDescriptor* descriptor, int32 value)
{
int32 id = getIntId(descriptor);
setInt( id, value );
}
void AtomicStatisticsImpl::setInt(int32 id, int32 value)
{
if (isOpen()) {
_setInt(id, value);
}
}
////////////////////////////////LONG METHODS/////////////////////////////
void AtomicStatisticsImpl::setLong(char* name, int64 value)
{
setLong(nameToDescriptor(name), value);
}
void AtomicStatisticsImpl::setLong(StatisticDescriptor* descriptor, int64 value){
setLong(getLongId(descriptor), value);
}
void AtomicStatisticsImpl::setLong(int32 id, int64 value)
{
if (isOpen()){
_setLong(id, value);
}
}
////////////////////////////////////////DOUBLE METHODS////////////////////
void AtomicStatisticsImpl::setDouble(char* name, double value)
{
setDouble(nameToDescriptor(name), value);
}
void AtomicStatisticsImpl::setDouble(StatisticDescriptor* descriptor, double value)
{
setDouble(getDoubleId(descriptor), value);
}
void AtomicStatisticsImpl::setDouble(int32 id, double value)
{
if (isOpen()){
_setDouble(id, value);
}
}
int32 AtomicStatisticsImpl::getInt(char* name)
{
int32 id = getIntId(nameToDescriptor(name));
return getInt( id );
}
int32 AtomicStatisticsImpl::getInt(StatisticDescriptor* descriptor)
{
int32 id = getIntId(descriptor);
return getInt( id );
}
int32 AtomicStatisticsImpl::getInt(int32 id)
{
if (isOpen()){
return _getInt(id);
}else {
return 0;
}
}
int64 AtomicStatisticsImpl::getLong(char* name)
{
return getLong(nameToDescriptor(name));
}
int64 AtomicStatisticsImpl::getLong(StatisticDescriptor* descriptor)
{
return getLong(getLongId(descriptor));
}
int64 AtomicStatisticsImpl::getLong(int32 id)
{
if (isOpen()){
return _getLong(id);
}else {
return 0;
}
}
double AtomicStatisticsImpl::getDouble(char* name)
{
return getDouble(nameToDescriptor(name));
}
double AtomicStatisticsImpl::getDouble(StatisticDescriptor* descriptor)
{
return getDouble(getDoubleId(descriptor));
}
double AtomicStatisticsImpl::getDouble(int32 id)
{
if (isOpen()){
return _getDouble(id);
}else {
return 0;
}
}
/*
*Increment the value of the int32 decriptor by delta
*/
int32 AtomicStatisticsImpl::incInt(char* name, int32 delta)
{
int32 id = getIntId( nameToDescriptor( name ) );
return incInt( id, delta );
}
int32 AtomicStatisticsImpl::incInt(StatisticDescriptor* descriptor, int32 delta)
{
int32 id = getIntId(descriptor);
return incInt( id, delta );
}
int32 AtomicStatisticsImpl::incInt(int32 id, int32 delta)
{
if (isOpen()){
return _incInt(id, delta);
}else {
return 0;
}
}
/*
*Increment the value of the int64 decriptor by delta
*/
int64 AtomicStatisticsImpl::incLong(char* name, int64 delta)
{
return incLong(nameToDescriptor(name), delta);
}
int64 AtomicStatisticsImpl::incLong(StatisticDescriptor* descriptor, int64 delta)
{
return incLong(getLongId(descriptor), delta);
}
int64 AtomicStatisticsImpl::incLong(int32 id, int64 delta)
{
if (isOpen()){
return _incLong(id, delta);
}else {
return 0;
}
}
/*
*Increment the value of the double decriptor by delta
*/
double AtomicStatisticsImpl::incDouble(char* name, double delta)
{
return incDouble(nameToDescriptor(name), delta);
}
double AtomicStatisticsImpl::incDouble(StatisticDescriptor* descriptor, double delta)
{
return incDouble(getDoubleId(descriptor), delta);
}
double AtomicStatisticsImpl::incDouble(int32 id, double delta)
{
if (isOpen()){
return _incDouble(id, delta);
}else {
return 0;
}
}
int32 AtomicStatisticsImpl::getIntId(StatisticDescriptor* descriptor)
{
StatisticDescriptorImpl* realDescriptor = dynamic_cast<StatisticDescriptorImpl*>(descriptor);
return realDescriptor->checkInt();
}
int32 AtomicStatisticsImpl::getLongId(StatisticDescriptor* descriptor)
{
StatisticDescriptorImpl* realDescriptor = dynamic_cast<StatisticDescriptorImpl*>(descriptor);
return realDescriptor->checkLong();
}
int32 AtomicStatisticsImpl::getDoubleId(StatisticDescriptor* descriptor)
{
StatisticDescriptorImpl* realDescriptor = dynamic_cast<StatisticDescriptorImpl*>(descriptor);
return realDescriptor->checkDouble();
}