blob: f1b020bb4bc8760e124911e54e7f72200a4e050c [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <gfcpp/gfcpp_globals.hpp>
#include <ace/Atomic_Op_T.h>
#include <ace/Recursive_Thread_Mutex.h>
#include <ace/OS.h>
#include <ace/Thread_Mutex.h>
#include <ace/Time_Value.h>
#include <ace/Guard_T.h>
#include <gfcpp/Exception.hpp>
#include "StatisticsManager.hpp"
#include <gfcpp/Log.hpp>
#include "GeodeStatisticsFactory.hpp"
#include <string>
#include "AtomicStatisticsImpl.hpp"
#include "OsStatisticsImpl.hpp"
using namespace apache::geode::client;
using namespace apache::geode::statistics;
/**
* static member initialization
*/
StatisticsManager* StatisticsManager::s_singleton = NULL;
StatisticsManager::StatisticsManager(const char* filePath, int64 sampleInterval,
bool enabled, int64 statFileLimit,
int64 statDiskSpaceLimit)
: m_sampler(NULL), m_adminRegion(NULLPTR) {
m_sampleIntervalMs =
static_cast<int32_t>(sampleInterval) * 1000; /* convert to millis */
m_newlyAddedStatsList.reserve(16); // Allocate initial sizes
GeodeStatisticsFactory::initInstance(this);
try {
if (m_sampler == NULL && enabled) {
m_sampler = new HostStatSampler(filePath, m_sampleIntervalMs, this,
statFileLimit, statDiskSpaceLimit);
m_sampler->start();
}
} catch (...) {
delete m_sampler;
throw;
}
}
StatisticsManager* StatisticsManager::initInstance(const char* filePath,
int64 sampleIntervalMs,
bool enabled,
int64 statsFileLimit,
int64 statsDiskSpaceLimit) {
if (!s_singleton) {
s_singleton = new StatisticsManager(filePath, sampleIntervalMs, enabled,
statsFileLimit, statsDiskSpaceLimit);
}
return s_singleton;
}
StatisticsManager* StatisticsManager::getExistingInstance() {
if (s_singleton) {
return s_singleton;
}
return NULL;
}
void StatisticsManager::forceSample() {
if (m_sampler) m_sampler->forceSample();
}
/**************************Dtor*******************************************/
StatisticsManager::~StatisticsManager() {
try {
// Stop the sampler
closeSampler();
// List should be empty if close() is called on each Stats object
// If this is not done, delete all the pointers
ACE_Guard<ACE_Recursive_Thread_Mutex> guard(m_statsListLock);
int32 count = static_cast<int32>(m_statsList.size());
if (count > 0) {
LOGFINEST("~StatisticsManager has found %d leftover statistics:", count);
std::vector<Statistics*>::iterator iterFind = m_statsList.begin();
while (iterFind != m_statsList.end()) {
if (*iterFind != NULL) {
std::string temp((*iterFind)->getType()->getName());
LOGFINEST("Leftover statistic: %s", temp.c_str());
/* adongre
* Passing null variable "*iterFind" to function
* "apache::geode::statistics::StatisticsManager::deleteStatistics(apache::geode::statistics::Statistics
* *&)",
* which dereferences it.
* FIX : Put the call into the if condition
*/
deleteStatistics(*iterFind);
*iterFind = NULL;
}
++iterFind;
}
m_statsList.erase(m_statsList.begin(), m_statsList.end());
}
// Clean Factory: clean Type map etc.
GeodeStatisticsFactory::clean();
} catch (const Exception& ex) {
Log::warningCatch("~StatisticsManager swallowing Geode exception", ex);
} catch (const std::exception& ex) {
std::string what = "~StatisticsManager swallowing std::exception: ";
what += ex.what();
Log::warning(what.c_str());
} catch (...) {
Log::error("~StatisticsManager swallowing unknown exception");
}
}
void StatisticsManager::clean() {
if (s_singleton != NULL) {
delete s_singleton;
s_singleton = NULL;
}
}
////////////////////// Mutex methods ///////////////////////////
ACE_Recursive_Thread_Mutex& StatisticsManager::getListMutex() {
return m_statsListLock;
}
void StatisticsManager::closeSampler() {
if (m_sampler != NULL) {
m_sampler->stop();
delete m_sampler;
m_sampler = NULL;
}
}
void StatisticsManager::addStatisticsToList(Statistics* stat) {
if (stat) {
ACE_Guard<ACE_Recursive_Thread_Mutex> guard(m_statsListLock);
m_statsList.push_back(stat);
/* Add to m_newlyAddedStatsList also so that a fresh traversal not needed
before sampling.
After writing token to sampled file, stats ptrs will be deleted from list.
*/
m_newlyAddedStatsList.push_back(stat);
}
}
int32 StatisticsManager::getStatListModCount() {
ACE_Guard<ACE_Recursive_Thread_Mutex> guard(m_statsListLock);
return static_cast<int32>(m_statsList.size());
}
std::vector<Statistics*>& StatisticsManager::getStatsList() {
return this->m_statsList;
}
std::vector<Statistics*>& StatisticsManager::getNewlyAddedStatsList() {
return this->m_newlyAddedStatsList;
}
Statistics* StatisticsManager::findFirstStatisticsByType(StatisticsType* type) {
ACE_Guard<ACE_Recursive_Thread_Mutex> guard(m_statsListLock);
std::vector<Statistics*>::iterator start = m_statsList.begin();
while (start != m_statsList.end()) {
if (!((*start)->isClosed()) && ((*start)->getType() == type)) {
return *start;
}
start++;
}
return NULL;
}
std::vector<Statistics*> StatisticsManager::findStatisticsByType(
StatisticsType* type) {
std::vector<Statistics*> hits;
ACE_Guard<ACE_Recursive_Thread_Mutex> guard(m_statsListLock);
std::vector<Statistics*>::iterator start = m_statsList.begin();
while (start != m_statsList.end()) {
if (!((*start)->isClosed()) && ((*start)->getType() == type)) {
hits.push_back(*start);
}
start++;
}
return hits;
}
std::vector<Statistics*> StatisticsManager::findStatisticsByTextId(
char* textId) {
std::vector<Statistics*> hits;
ACE_Guard<ACE_Recursive_Thread_Mutex> guard(m_statsListLock);
std::vector<Statistics*>::iterator start = m_statsList.begin();
while (start != m_statsList.end()) {
if (!((*start)->isClosed()) && ((*start)->getTextId() == textId)) {
hits.push_back(*start);
}
start++;
}
return hits;
}
std::vector<Statistics*> StatisticsManager::findStatisticsByNumericId(
int64 numericId) {
std::vector<Statistics*> hits;
ACE_Guard<ACE_Recursive_Thread_Mutex> guard(m_statsListLock);
std::vector<Statistics*>::iterator start = m_statsList.begin();
while (start != m_statsList.end()) {
if (!((*start)->isClosed()) && ((*start)->getNumericId() == numericId)) {
hits.push_back(*start);
}
start++;
}
return hits;
}
Statistics* StatisticsManager::findStatisticsByUniqueId(int64 uniqueId) {
ACE_Guard<ACE_Recursive_Thread_Mutex> guard(m_statsListLock);
std::vector<Statistics*>::iterator start = m_statsList.begin();
while (start != m_statsList.end()) {
if (!((*start)->isClosed()) && ((*start)->getUniqueId() == uniqueId)) {
Statistics* ret = *start;
return ret;
}
start++;
}
return NULL;
}
void StatisticsManager::deleteStatistics(Statistics*& stat) {
if (stat->isAtomic()) {
AtomicStatisticsImpl* ptr = dynamic_cast<AtomicStatisticsImpl*>(stat);
delete ptr;
} else {
OsStatisticsImpl* ptr = dynamic_cast<OsStatisticsImpl*>(stat);
delete ptr;
}
stat = NULL;
}