blob: d6915b94e27ec71d96bd3a1d33bbb9443a758fe1 [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 <gfcpp/DistributedSystem.hpp>
#include "statistics/StatisticsManager.hpp"
#include <gfcpp/SystemProperties.hpp>
#include <CppCacheLibrary.hpp>
#include <Utils.hpp>
#include <gfcpp/Log.hpp>
#include <gfcpp/CacheFactory.hpp>
#include <ace/OS.h>
#include <ExpiryTaskManager.hpp>
#include <CacheImpl.hpp>
#include <ace/Guard_T.h>
#include <ace/Recursive_Thread_Mutex.h>
#include <gfcpp/DataOutput.hpp>
#include <TcrMessage.hpp>
#include <DistributedSystemImpl.hpp>
#include <RegionStats.hpp>
#include <PoolStatistics.hpp>
#include <DiffieHellman.hpp>
#include "version.h"
using namespace apache::geode::client;
using namespace apache::geode::statistics;
DistributedSystemPtr* DistributedSystem::m_instance_ptr = NULL;
bool DistributedSystem::m_connected = false;
DistributedSystemImpl* DistributedSystem::m_impl = NULL;
ACE_Recursive_Thread_Mutex* g_disconnectLock = new ACE_Recursive_Thread_Mutex();
namespace {
StatisticsManager* g_statMngr = NULL;
SystemProperties* g_sysProps = NULL;
} // namespace
namespace apache {
namespace geode {
namespace client {
void setLFH() {
#ifdef _WIN32
static HINSTANCE kernelMod = NULL;
if (kernelMod == NULL) {
kernelMod = GetModuleHandle("kernel32");
if (kernelMod != NULL) {
typedef BOOL(WINAPI * PHSI)(
HANDLE HeapHandle, HEAP_INFORMATION_CLASS HeapInformationClass,
PVOID HeapInformation, SIZE_T HeapInformationLength);
typedef HANDLE(WINAPI * PGPH)();
PHSI pHSI = NULL;
PGPH pGPH = NULL;
if ((pHSI = (PHSI)GetProcAddress(kernelMod, "HeapSetInformation")) !=
NULL) {
// The LFH API is available
/* Only set LFH for process heap; causes problems in C++ framework if
set for all heaps
HANDLE hProcessHeapHandles[1024];
DWORD dwRet;
ULONG heapFragValue = 2;
dwRet= GetProcessHeaps( 1024, hProcessHeapHandles );
for (DWORD i = 0; i < dwRet; i++)
{
HeapSetInformation( hProcessHeapHandles[i],
HeapCompatibilityInformation, &heapFragValue, sizeof(heapFragValue)
);
}
*/
HANDLE hProcessHeapHandle;
ULONG heapFragValue = 2;
if ((pGPH = (PGPH)GetProcAddress(kernelMod, "GetProcessHeap")) !=
NULL) {
hProcessHeapHandle = pGPH();
LOGCONFIG(
"Setting Microsoft Windows' low-fragmentation heap for use as "
"the main process heap.");
pHSI(hProcessHeapHandle, HeapCompatibilityInformation, &heapFragValue,
sizeof(heapFragValue));
}
}
}
}
#endif
}
} // namespace client
} // namespace geode
} // namespace apache
DistributedSystem::DistributedSystem(const char* name) : m_name(NULL) {
LOGDEBUG("DistributedSystem::DistributedSystem");
if (name != NULL) {
size_t len = strlen(name) + 1;
m_name = new char[len];
ACE_OS::strncpy(m_name, name, len);
}
if (strlen(g_sysProps->securityClientDhAlgo()) > 0) {
DiffieHellman::initOpenSSLFuncPtrs();
}
}
DistributedSystem::~DistributedSystem() { GF_SAFE_DELETE_ARRAY(m_name); }
DistributedSystemPtr DistributedSystem::connect(
const char* name, const PropertiesPtr& configPtr) {
ACE_Guard<ACE_Recursive_Thread_Mutex> disconnectGuard(*g_disconnectLock);
setLFH();
if (m_connected == true) {
throw AlreadyConnectedException(
"DistributedSystem::connect: already connected, call getInstance to "
"get it");
}
// make sure statics are initialized.
if (m_instance_ptr == NULL) {
m_instance_ptr = new DistributedSystemPtr();
}
if (g_sysProps == NULL) {
g_sysProps = new SystemProperties(configPtr, NULL);
}
Exception::setStackTraces(g_sysProps->debugStackTraceEnabled());
if (name == NULL) {
delete g_sysProps;
g_sysProps = NULL;
throw IllegalArgumentException(
"DistributedSystem::connect: "
"name cannot be NULL");
}
if (name[0] == '\0') {
name = "NativeDS";
}
// Fix for Ticket#866 on NC OR SR#13306117704
// Set client name via native client API
const char* propName = g_sysProps->name();
if (propName != NULL && strlen(propName) > 0) {
name = propName;
}
// Trigger other library initialization.
CppCacheLibrary::initLib();
if (!TcrMessage::init()) {
TcrMessage::cleanup();
throw IllegalArgumentException(
"DistributedSystem::connect: preallocate message buffer failed!");
}
const char* logFilename = g_sysProps->logFilename();
if (logFilename != NULL) {
try {
Log::close();
Log::init(g_sysProps->logLevel(), logFilename,
g_sysProps->logFileSizeLimit(),
g_sysProps->logDiskSpaceLimit());
} catch (const GeodeIOException&) {
Log::close();
TcrMessage::cleanup();
CppCacheLibrary::closeLib();
delete g_sysProps;
g_sysProps = NULL;
*m_instance_ptr = NULLPTR;
// delete g_disconnectLock;
throw;
}
} else {
Log::setLogLevel(g_sysProps->logLevel());
}
try {
std::string gfcpp = CppCacheLibrary::getProductDir();
LOGCONFIG("Using Geode Native Client Product Directory: %s", gfcpp.c_str());
} catch (const Exception&) {
LOGERROR(
"Unable to determine Product Directory. Please set the "
"GFCPP environment variable.");
throw;
}
// Add version information, source revision, current directory etc.
LOGCONFIG("Product version: %s", CacheFactory::getProductDescription());
LOGCONFIG("Source revision: %s", PRODUCT_SOURCE_REVISION);
LOGCONFIG("Source repository: %s", PRODUCT_SOURCE_REPOSITORY);
ACE_utsname u;
ACE_OS::uname(&u);
LOGCONFIG(
"Running on: SystemName=%s Machine=%s Host=%s Release=%s Version=%s",
u.sysname, u.machine, u.nodename, u.release, u.version);
#ifdef _WIN32
const uint32_t pathMax = _MAX_PATH;
#else
const uint32_t pathMax = PATH_MAX;
#endif
ACE_TCHAR cwd[pathMax + 1];
(void)ACE_OS::getcwd(cwd, pathMax);
LOGCONFIG("Current directory: %s", cwd);
LOGCONFIG("Current value of PATH: %s", ACE_OS::getenv("PATH"));
#ifndef _WIN32
const char* ld_libpath = ACE_OS::getenv("LD_LIBRARY_PATH");
LOGCONFIG("Current library path: %s",
ld_libpath == NULL ? "NULL" : ld_libpath);
#else
if (Utils::s_setNewAndDelete) {
LOGCONFIG("Operators new and delete have been set.");
}
#endif
// Log the Geode system properties
g_sysProps->logSettings();
/* if (strlen(g_sysProps->securityClientDhAlgo())>0) {
DiffieHellman::initDhKeys(g_sysProps->getSecurityProperties());
}*/
DistributedSystemPtr dptr;
try {
g_statMngr = StatisticsManager::initInstance(
g_sysProps->statisticsArchiveFile(),
g_sysProps->statisticsSampleInterval(), g_sysProps->statisticsEnabled(),
g_sysProps->statsFileSizeLimit(), g_sysProps->statsDiskSpaceLimit());
} catch (const NullPointerException&) {
// close all open handles, delete whatever was newed.
g_statMngr = NULL;
//:Merge issue
/*if (strlen(g_sysProps->securityClientDhAlgo())>0) {
DiffieHellman::clearDhKeys();
}*/
Log::close();
TcrMessage::cleanup();
CppCacheLibrary::closeLib();
delete g_sysProps;
g_sysProps = NULL;
*m_instance_ptr = NULLPTR;
// delete g_disconnectLock;
throw;
}
GF_D_ASSERT(g_statMngr != NULL);
CacheImpl::expiryTaskManager = new ExpiryTaskManager();
CacheImpl::expiryTaskManager->begin();
DistributedSystem* dp = new DistributedSystem(name);
if (!dp) {
throw NullPointerException("DistributedSystem::connect: new failed");
}
m_impl = new DistributedSystemImpl(name, dp);
try {
m_impl->connect();
} catch (const apache::geode::client::Exception& e) {
LOGERROR("Exception caught during client initialization: %s",
e.getMessage());
std::string msg = "DistributedSystem::connect: caught exception: ";
msg.append(e.getMessage());
throw NotConnectedException(msg.c_str());
} catch (const std::exception& e) {
LOGERROR("Exception caught during client initialization: %s", e.what());
std::string msg = "DistributedSystem::connect: caught exception: ";
msg.append(e.what());
throw NotConnectedException(msg.c_str());
} catch (...) {
LOGERROR("Unknown exception caught during client initialization");
throw NotConnectedException(
"DistributedSystem::connect: caught unknown exception");
}
m_connected = true;
dptr = dp;
*m_instance_ptr = dptr;
LOGCONFIG("Starting the Geode Native Client");
return dptr;
}
/**
*@brief disconnect from the distributed system
*/
void DistributedSystem::disconnect() {
ACE_Guard<ACE_Recursive_Thread_Mutex> disconnectGuard(*g_disconnectLock);
if (!m_connected) {
throw NotConnectedException(
"DistributedSystem::disconnect: connect "
"not called");
}
try {
CachePtr cache = CacheFactory::getAnyInstance();
if (cache != NULLPTR && !cache->isClosed()) {
cache->close();
}
} catch (const apache::geode::client::Exception& e) {
LOGWARN("Exception while closing: %s: %s", e.getName(), e.getMessage());
}
if (CacheImpl::expiryTaskManager != NULL) {
CacheImpl::expiryTaskManager->stopExpiryTaskManager();
}
if (m_impl) {
m_impl->disconnect();
delete m_impl;
m_impl = NULL;
}
LOGFINEST("Deleted DistributedSystemImpl");
if (strlen(g_sysProps->securityClientDhAlgo()) > 0) {
// DistributedSystem::getInstance()->m_dh->clearDhKeys();
}
// Clear DH Keys
/* if (strlen(g_sysProps->securityClientDhAlgo())>0) {
DiffieHellman::clearDhKeys();
}*/
GF_D_ASSERT(!!g_sysProps);
delete g_sysProps;
g_sysProps = NULL;
LOGFINEST("Deleted SystemProperties");
if (CacheImpl::expiryTaskManager != NULL) {
delete CacheImpl::expiryTaskManager;
CacheImpl::expiryTaskManager = NULL;
}
LOGFINEST("Deleted ExpiryTaskManager");
TcrMessage::cleanup();
LOGFINEST("Cleaned TcrMessage");
GF_D_ASSERT(!!g_statMngr);
g_statMngr->clean();
g_statMngr = NULL;
LOGFINEST("Cleaned StatisticsManager");
RegionStatType::clean();
LOGFINEST("Cleaned RegionStatType");
PoolStatType::clean();
LOGFINEST("Cleaned PoolStatType");
*m_instance_ptr = NULLPTR;
// Free up library resources
CppCacheLibrary::closeLib();
LOGCONFIG("Stopped the Geode Native Client");
Log::close();
m_connected = false;
}
SystemProperties* DistributedSystem::getSystemProperties() {
return g_sysProps;
}
const char* DistributedSystem::getName() const { return m_name; }
bool DistributedSystem::isConnected() {
CppCacheLibrary::initLib();
return m_connected;
}
DistributedSystemPtr DistributedSystem::getInstance() {
CppCacheLibrary::initLib();
if (m_instance_ptr == NULL) {
return NULLPTR;
}
return *m_instance_ptr;
}