| /* | 
 |  * 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/ACE.h> | 
 | #include <ace/Thread_Mutex.h> | 
 | #include <ace/Task.h> | 
 | #include <ace/OS_NS_sys_utsname.h> | 
 | #include <ace/INET_Addr.h> | 
 | #include <ace/Dirent.h> | 
 | #include <ace/Dirent_Selector.h> | 
 | #include <ace/OS_NS_sys_stat.h> | 
 | #include <utility> | 
 | #include <vector> | 
 |  | 
 | #include "HostStatSampler.hpp" | 
 | #include "HostStatHelper.hpp" | 
 | #include "StatArchiveWriter.hpp" | 
 | #include <NanoTimer.hpp> | 
 | #include <gfcpp/DistributedSystem.hpp> | 
 | #include <gfcpp/SystemProperties.hpp> | 
 | #include <gfcpp/Log.hpp> | 
 | #include "GeodeStatisticsFactory.hpp" | 
 | #include <ClientHealthStats.hpp> | 
 | #include <ClientProxyMembershipID.hpp> | 
 | using namespace apache::geode::statistics; | 
 | using namespace apache::geode::client; | 
 |  | 
 | namespace apache { | 
 | namespace geode { | 
 | namespace statistics { | 
 | namespace globals { | 
 | std::string g_statFile; | 
 | std::string g_statFileWithExt; | 
 | int64 g_spaceUsed = 0; | 
 | int64 g_previoussamplesize = 0; | 
 | int64 g_previoussamplesizeLastFile = 0; | 
 | // Make a pair for the filename & its size | 
 | std::pair<std::string, size_t> g_fileInfoPair; | 
 | // Vector to hold the fileInformation | 
 | typedef std::vector<std::pair<std::string, int64> > g_fileInfo; | 
 | }  // namespace globals | 
 | }  // namespace statistics | 
 | }  // namespace geode | 
 | }  // namespace apache | 
 |  | 
 | using namespace apache::geode::statistics::globals; | 
 |  | 
 | extern "C" { | 
 |  | 
 | int selector(const dirent* d) { | 
 |   std::string inputname(d->d_name); | 
 |   std::string filebasename = ACE::basename( | 
 |       apache::geode::statistics::globals::g_statFileWithExt.c_str()); | 
 |   size_t actualHyphenPos = filebasename.find_last_of('.'); | 
 |   if (strcmp(filebasename.c_str(), d->d_name) == 0) return 1; | 
 |   size_t fileExtPos = inputname.find_last_of('.'); | 
 |   std::string extName = inputname.substr(fileExtPos + 1, inputname.length()); | 
 |   if (strcmp(extName.c_str(), "gfs") != 0) return 0; | 
 |   if (fileExtPos != std::string::npos) { | 
 |     std::string tempname = inputname.substr(0, fileExtPos); | 
 |     size_t fileHyphenPos = tempname.find_last_of('-'); | 
 |     if (fileHyphenPos != std::string::npos) { | 
 |       std::string buff1 = tempname.substr(0, fileHyphenPos); | 
 |       if (ACE_OS::strstr(filebasename.c_str(), buff1.c_str()) == 0) { | 
 |         return 0; | 
 |       } | 
 |       if (fileHyphenPos != actualHyphenPos) return 0; | 
 |       std::string buff = tempname.substr(fileHyphenPos + 1, | 
 |                                          tempname.length() - fileHyphenPos - 1); | 
 |       for (std::string::iterator iter = buff.begin(); iter != buff.end(); | 
 |            ++iter) { | 
 |         if (*iter < '0' || *iter > '9') { | 
 |           return 0; | 
 |         } | 
 |       } | 
 |       return 1; | 
 |     } else { | 
 |       return 0; | 
 |     } | 
 |   } else { | 
 |     return 0; | 
 |   } | 
 | } | 
 |  | 
 | int comparator(const dirent** d1, const dirent** d2) { | 
 |   if (strlen((*d1)->d_name) < strlen((*d2)->d_name)) { | 
 |     return -1; | 
 |   } else if (strlen((*d1)->d_name) > strlen((*d2)->d_name)) { | 
 |     return 1; | 
 |   } | 
 |   int diff = ACE_OS::strcmp((*d1)->d_name, (*d2)->d_name); | 
 |   if (diff < 0) { | 
 |     return -1; | 
 |   } else if (diff > 0) { | 
 |     return 1; | 
 |   } else { | 
 |     return 0; | 
 |   } | 
 | } | 
 | } | 
 |  | 
 | const char* HostStatSampler::NC_HSS_Thread = "NC HSS Thread"; | 
 |  | 
 | HostStatSampler::HostStatSampler(const char* filePath, int64 sampleIntervalMs, | 
 |                                  StatisticsManager* statMngr, | 
 |                                  int64 statFileLimit, | 
 |                                  int64 statDiskSpaceLimit) { | 
 |   m_isStatDiskSpaceEnabled = false; | 
 |   m_adminError = false; | 
 |   m_running = false; | 
 |   m_stopRequested = false; | 
 |   m_archiver = NULL; | 
 |   m_samplerStats = new StatSamplerStats(); | 
 |  | 
 |   ACE_Time_Value startTimeValue = ACE_OS::gettimeofday(); | 
 |   m_startTime = startTimeValue.msec(); | 
 |  | 
 |   m_pid = ACE_OS::getpid(); | 
 |   m_statMngr = statMngr; | 
 |   m_archiveFileName = filePath; | 
 |   g_statFile = filePath; | 
 |   m_sampleRate = sampleIntervalMs; | 
 |   rollIndex = 0; | 
 |   m_archiveDiskSpaceLimit = statDiskSpaceLimit; | 
 |   g_spaceUsed = 0; | 
 |  | 
 |   if (statDiskSpaceLimit != 0) { | 
 |     m_isStatDiskSpaceEnabled = true; | 
 |   } | 
 |  | 
 |   m_archiveFileSizeLimit = statFileLimit * 1024 * 1024;  // 10000000; | 
 |   if (m_archiveFileSizeLimit < 0 || | 
 |       m_archiveFileSizeLimit > GEMFIRE_MAX_STATS_FILE_LIMIT) { | 
 |     m_archiveFileSizeLimit = GEMFIRE_MAX_STATS_FILE_LIMIT; | 
 |   } | 
 |  | 
 |   if (m_isStatDiskSpaceEnabled) { | 
 |     m_archiveDiskSpaceLimit = statDiskSpaceLimit * 1024 * 1024;  // 10000000; | 
 |  | 
 |     if (m_archiveDiskSpaceLimit < | 
 |         0 /*|| m_archiveDiskSpaceLimit > GEMFIRE_MAX_STAT_DISK_LIMIT*/) { | 
 |       m_archiveDiskSpaceLimit = GEMFIRE_MAX_STAT_DISK_LIMIT; | 
 |     } | 
 |  | 
 |     // If FileSizelimit is greater than DiskSpaceLimit & diskspaceLimit is set, | 
 |     // then set DiskSpaceLimit to FileSizelimit | 
 |     if (m_archiveFileSizeLimit > m_archiveDiskSpaceLimit) { | 
 |       m_archiveFileSizeLimit = m_archiveDiskSpaceLimit; | 
 |     } | 
 |  | 
 |     // If only DiskSpaceLimit is specified and no FileSizeLimit specified, then | 
 |     // set DiskSpaceLimit to FileSizelimit. | 
 |     // This helps in getting the file handle that is exceeded the limit. | 
 |     if (m_archiveFileSizeLimit == 0) { | 
 |       m_archiveFileSizeLimit = m_archiveDiskSpaceLimit; | 
 |     } | 
 |  | 
 |     g_statFileWithExt = initStatFileWithExt(); | 
 |  | 
 | #ifdef _WIN32 | 
 |     // replace all '\' with '/' to make everything easier.. | 
 |     size_t len = g_statFile.length() + 1; | 
 |     char* slashtmp = new char[len]; | 
 |     ACE_OS::strncpy(slashtmp, g_statFile.c_str(), len); | 
 |     for (size_t i = 0; i < g_statFile.length(); i++) { | 
 |       if (slashtmp[i] == '/') { | 
 |         slashtmp[i] = '\\'; | 
 |       } | 
 |     } | 
 |     g_statFile = slashtmp; | 
 |     delete[] slashtmp; | 
 |     slashtmp = NULL; | 
 | #endif | 
 |  | 
 |     std::string dirname = ACE::dirname(g_statFile.c_str()); | 
 |     // struct dirent **resultArray; | 
 |     // int entries_count = ACE_OS::scandir(dirname.c_str(), &resultArray, | 
 |     // selector, comparator); | 
 |     ACE_Dirent_Selector sds; | 
 |     int status = sds.open(dirname.c_str(), selector, comparator); | 
 |     if (status != -1) { | 
 |       for (int i = 0; i < sds.length(); i++) { | 
 |         // std::string strname = ACE::basename(resultArray[i]->d_name); | 
 |         std::string strname = ACE::basename(sds[i]->d_name); | 
 |         size_t fileExtPos = strname.find_last_of('.', strname.length()); | 
 |         if (fileExtPos != std::string::npos) { | 
 |           std::string tempname = strname.substr(0, fileExtPos); | 
 |           size_t fileHyphenPos = tempname.find_last_of('-', tempname.length()); | 
 |           if (fileHyphenPos != std::string::npos) { | 
 |             std::string buff = | 
 |                 tempname.substr(fileHyphenPos + 1, tempname.length()); | 
 |             rollIndex = ACE_OS::atoi(buff.c_str()) + 1; | 
 |           } | 
 |         } | 
 |       } | 
 |       sds.close(); | 
 |     } | 
 |     /*for(int i = 0; i < entries_count; i++) { | 
 |       ACE_OS::free ( resultArray[i] ); | 
 |     } | 
 |     if (entries_count >= 0) { | 
 |       ACE_OS::free( resultArray ); | 
 |       resultArray = NULL; | 
 |     }*/ | 
 |  | 
 |     FILE* existingFile = fopen(g_statFileWithExt.c_str(), "r"); | 
 |     if (existingFile != NULL && statFileLimit > 0) { | 
 |       fclose(existingFile); | 
 |       /* adongre | 
 |        * CID 28820: Resource leak (RESOURCE_LEAK) | 
 |        */ | 
 |       existingFile = NULL; | 
 |       changeArchive(g_statFileWithExt); | 
 |     } else { | 
 |       writeGfs(); | 
 |     } | 
 |     /* adongre | 
 |      * CID 28820: Resource leak (RESOURCE_LEAK) | 
 |      */ | 
 |     if (existingFile != NULL) { | 
 |       fclose(existingFile); | 
 |       existingFile = NULL; | 
 |     } | 
 |   } | 
 | } | 
 |  | 
 | std::string HostStatSampler::initStatFileWithExt() { | 
 |   std::string archivefilename = createArchiveFileName(); | 
 |   archivefilename = chkForGFSExt(archivefilename); | 
 |   return archivefilename; | 
 | } | 
 |  | 
 | HostStatSampler::~HostStatSampler() { | 
 |   if (m_samplerStats != NULL) { | 
 |     delete m_samplerStats; | 
 |     m_samplerStats = NULL; | 
 |   } | 
 |   if (m_archiver != NULL) { | 
 |     delete m_archiver; | 
 |     m_archiver = NULL; | 
 |   } | 
 | } | 
 |  | 
 | std::string HostStatSampler::createArchiveFileName() { | 
 |   if (!m_isStatDiskSpaceEnabled) { | 
 |     char buff[1024] = {0}; | 
 |     int32 pid = ACE_OS::getpid(); | 
 |     int32 len = static_cast<int32>(m_archiveFileName.length()); | 
 |     size_t fileExtPos = m_archiveFileName.find_last_of('.', len); | 
 |     if (fileExtPos == std::string::npos) { | 
 |       ACE_OS::snprintf(buff, 1024, "%s-%d.gfs", m_archiveFileName.c_str(), pid); | 
 |     } else { | 
 |       std::string tmp; | 
 |       tmp = m_archiveFileName.substr(0, fileExtPos); | 
 |       ACE_OS::snprintf(buff, 1024, "%s-%d.gfs", tmp.c_str(), pid); | 
 |     } | 
 |     m_archiveFileName = buff; | 
 |     return m_archiveFileName; | 
 |   } else { | 
 |     return m_archiveFileName; | 
 |   } | 
 | } | 
 |  | 
 | std::string HostStatSampler::getArchiveFileName() { return m_archiveFileName; } | 
 |  | 
 | int64 HostStatSampler::getArchiveFileSizeLimit() { | 
 |   return m_archiveFileSizeLimit; | 
 | } | 
 |  | 
 | int64 HostStatSampler::getArchiveDiskSpaceLimit() { | 
 |   return m_archiveDiskSpaceLimit; | 
 | } | 
 |  | 
 | int64 HostStatSampler::getSampleRate() { return m_sampleRate; } | 
 |  | 
 | bool HostStatSampler::isSamplingEnabled() { return true; } | 
 |  | 
 | void HostStatSampler::accountForTimeSpentWorking(int64 nanosSpentWorking) { | 
 |   m_samplerStats->tookSample(nanosSpentWorking); | 
 | } | 
 |  | 
 | bool HostStatSampler::statisticsExists(const int64 id) { | 
 |   ACE_Guard<ACE_Recursive_Thread_Mutex> guard(m_statMngr->getListMutex()); | 
 |   std::vector<Statistics*>& statsList = m_statMngr->getStatsList(); | 
 |   std::vector<Statistics*>::iterator i; | 
 |   for (i = statsList.begin(); i != statsList.end(); ++i) { | 
 |     if ((*i)->getUniqueId() == id) { | 
 |       return true; | 
 |     } | 
 |   } | 
 |   return false; | 
 | } | 
 |  | 
 | Statistics* HostStatSampler::findStatistics(const int64 id) { | 
 |   ACE_Guard<ACE_Recursive_Thread_Mutex> guard(m_statMngr->getListMutex()); | 
 |   std::vector<Statistics*>& statsList = m_statMngr->getStatsList(); | 
 |   std::vector<Statistics*>::iterator i; | 
 |   for (i = statsList.begin(); i != statsList.end(); ++i) { | 
 |     if ((*i)->getUniqueId() == id) { | 
 |       return *i; | 
 |     } | 
 |   } | 
 |   return NULL; | 
 | } | 
 |  | 
 | ACE_Recursive_Thread_Mutex& HostStatSampler::getStatListMutex() { | 
 |   return m_statMngr->getListMutex(); | 
 | } | 
 |  | 
 | int32 HostStatSampler::getStatisticsModCount() { | 
 |   return m_statMngr->getStatListModCount(); | 
 | } | 
 |  | 
 | std::vector<Statistics*>& HostStatSampler::getStatistics() { | 
 |   return m_statMngr->getStatsList(); | 
 | } | 
 |  | 
 | std::vector<Statistics*>& HostStatSampler::getNewStatistics() { | 
 |   return m_statMngr->getNewlyAddedStatsList(); | 
 | } | 
 |  | 
 | int64 HostStatSampler::getSystemId() { return m_pid; } | 
 |  | 
 | int64 HostStatSampler::getSystemStartTime() { return m_startTime; } | 
 |  | 
 | std::string HostStatSampler::getSystemDirectoryPath() { | 
 |   ACE_utsname u; | 
 |   ACE_OS::uname(&u); | 
 |   std::string dirPath(u.nodename); | 
 |   return dirPath; | 
 | } | 
 |  | 
 | std::string HostStatSampler::getProductDescription() { | 
 |   return "Pivotal Geode Native Client "; | 
 | } | 
 |  | 
 | void HostStatSampler::changeArchive(std::string filename) { | 
 |   if (filename.length() == 0) { | 
 |     // terminate the sampling thread | 
 |     m_stopRequested = true; | 
 |     return; | 
 |   } | 
 |   filename = chkForGFSExt(filename); | 
 |   if (m_archiver != NULL) { | 
 |     g_previoussamplesize = m_archiver->getSampleSize(); | 
 |     m_archiver->closeFile(); | 
 |   } | 
 |   // create new file only when tis file has some data; otherwise reuse it | 
 |   if (rollArchive(filename) != 0) { | 
 |     delete m_archiver; | 
 |     m_archiver = NULL; | 
 |     // throw exception | 
 |     return; | 
 |   } else { | 
 |     /* | 
 |     if (m_archiver != NULL) { | 
 |       m_archiver->openFile(filename); | 
 |       m_archiver->close(); | 
 |     } | 
 |     */ | 
 |     delete m_archiver; | 
 |     m_archiver = NULL; | 
 |   } | 
 |  | 
 |   m_archiver = new StatArchiveWriter(filename, this); | 
 | } | 
 |  | 
 | std::string HostStatSampler::chkForGFSExt(std::string filename) { | 
 |   if (!m_isStatDiskSpaceEnabled) { | 
 |     int32 len = static_cast<int32>(filename.length()); | 
 |     size_t posOfExt = filename.find_last_of('.', len); | 
 |     if (posOfExt == std::string::npos) { | 
 |       std::string newFilename = filename + "." + "gfs"; | 
 |       return newFilename; | 
 |     } | 
 |     std::string extName = filename.substr(posOfExt + 1); | 
 |     if (extName != "gfs") { | 
 |       std::string newFilename = filename.substr(0, posOfExt) + "." + "gfs"; | 
 |       return newFilename; | 
 |     } | 
 |     return filename; | 
 |   } else { | 
 |     std::string filebasename = ACE::basename(filename.c_str()); | 
 |     int32 len = static_cast<int32>(filebasename.length()); | 
 |     size_t fileExtPos = filebasename.find_last_of('.', len); | 
 |     // if no extension then add .gfs extension | 
 |     if (fileExtPos == std::string::npos) { | 
 |       std::string newFilename = filename + "." + "gfs"; | 
 |       return newFilename; | 
 |     } else { | 
 |       std::string extName = filebasename.substr(fileExtPos + 1); | 
 |       // if extension other than .gfs change it to ext + .log | 
 |       if (extName != "gfs") { | 
 |         std::string newFilename = filename + "." + "gfs"; | 
 |         return newFilename; | 
 |       } | 
 |       // .gfs Extension already provided, no need to append any extension. | 
 |       else { | 
 |         return filename; | 
 |       } | 
 |     } | 
 |   } | 
 | } | 
 |  | 
 | int32 HostStatSampler::rollArchive(std::string filename) { | 
 |   FILE* fpExist = fopen(filename.c_str(), "r"); | 
 |   if (fpExist == NULL) { | 
 |     return 0;  // no need to roll | 
 |   } else { | 
 |     fclose(fpExist); | 
 |     ACE_stat statBuf = {0}; | 
 |     ACE_OS::stat(filename.c_str(), &statBuf); | 
 |     if (statBuf.st_size == 0) return 0;  // reuse this file | 
 |   } | 
 |  | 
 |   std::string statsdirname; | 
 |   std::string statsbasename; | 
 |   std::string fnameBeforeExt; | 
 |   std::string extName; | 
 |   std::string newfilestr; | 
 |   bool gotNewFileName = false; | 
 |   int32 len = static_cast<int32>(filename.length()); | 
 |   int32 lastPosOfSep = static_cast<int32>( | 
 |       filename.find_last_of(ACE_DIRECTORY_SEPARATOR_CHAR, len)); | 
 |   if (lastPosOfSep == -1) { | 
 |     statsdirname = "."; | 
 |   } else { | 
 |     statsdirname = filename.substr(0, lastPosOfSep); | 
 |   } | 
 |   statsbasename = filename.substr(lastPosOfSep + 1, len); | 
 |   char gfsFileExtAfter = '.'; | 
 |   int32 baselen = static_cast<int32>(statsbasename.length()); | 
 |   int32 posOfExt = static_cast<int32>( | 
 |       statsbasename.find_last_of(gfsFileExtAfter, static_cast<int32>(baselen))); | 
 |   if (posOfExt == -1) { | 
 |     // throw IllegalArgument; | 
 |   } else { | 
 |     fnameBeforeExt = statsbasename.substr(0, posOfExt); | 
 |     extName = statsbasename.substr(posOfExt + 1, baselen); | 
 |   } | 
 |  | 
 |   int32 i = this->rollIndex; | 
 |   // 1000 is a good enough val to hold even a very int64 filename. | 
 |   while (!gotNewFileName) { | 
 |     char newfilename[1000] = {0}; | 
 |     if (i < 10) { | 
 |       ACE_OS::snprintf(newfilename, 1000, "%s%c%s-%d.%s", statsdirname.c_str(), | 
 |                        ACE_DIRECTORY_SEPARATOR_CHAR, fnameBeforeExt.c_str(), i, | 
 |                        extName.c_str()); | 
 |     } else { | 
 |       ACE_OS::snprintf(newfilename, 1000, "%s%c%s-%d.%s", statsdirname.c_str(), | 
 |                        ACE_DIRECTORY_SEPARATOR_CHAR, fnameBeforeExt.c_str(), i, | 
 |                        extName.c_str()); | 
 |     } | 
 |     FILE* fp = fopen(newfilename, "r"); | 
 |  | 
 |     if (fp != NULL) { | 
 |       // file exists; increment i and try the next filename | 
 |       i++; | 
 |       fclose(fp); | 
 |     } else { | 
 |       newfilestr = newfilename; | 
 |       // In the next call it will start looking from rollIndex = i+1 | 
 |       if (rename(filename.c_str(), newfilestr.c_str()) < 0) { | 
 |         return -1; | 
 |       } else { | 
 |         this->rollIndex = i + 1; | 
 |         return 0; | 
 |       } | 
 |     } | 
 |   } | 
 |   // The control will come here in case of error only. | 
 |   // This return looks redundant but introduced to remove warnings | 
 |   // while compiling the code. | 
 |   return -1; | 
 | } | 
 |  | 
 | void HostStatSampler::initSpecialStats() { | 
 |   // After Special categories are decided initialize them here | 
 |   HostStatHelper::newProcessStats(m_pid, "ProcessStats"); | 
 | } | 
 |  | 
 | void HostStatSampler::sampleSpecialStats() { HostStatHelper::refresh(); } | 
 |  | 
 | void HostStatSampler::closeSpecialStats() { | 
 |   ACE_Guard<ACE_Recursive_Thread_Mutex> guard(m_statMngr->getListMutex()); | 
 |   HostStatHelper::close(); | 
 |   HostStatHelper::cleanup(); | 
 | } | 
 |  | 
 | void HostStatSampler::checkListeners() {} | 
 |  | 
 | void HostStatSampler::start() { | 
 |   if (!m_running) { | 
 |     m_running = true; | 
 |     this->activate(); | 
 |   } | 
 | } | 
 |  | 
 | void HostStatSampler::stop() { | 
 |   m_stopRequested = true; | 
 |   this->wait(); | 
 |   // while (m_running) { | 
 |   //  ACE_OS::sleep(100); | 
 |   //} | 
 | } | 
 |  | 
 | bool HostStatSampler::isRunning() { return m_running; } | 
 |  | 
 | void HostStatSampler::putStatsInAdminRegion() { | 
 |   try { | 
 |     // Get Values of gets, puts,misses,listCalls,numThreads | 
 |     static bool initDone = false; | 
 |     static std::string clientId = ""; | 
 |     AdminRegionPtr adminRgn = m_statMngr->getAdminRegion(); | 
 |     if (adminRgn == NULLPTR) return; | 
 |     TryReadGuard _guard(adminRgn->getRWLock(), adminRgn->isDestroyed()); | 
 |     if (!adminRgn->isDestroyed()) { | 
 |       TcrConnectionManager* m_conn_man = adminRgn->getConnectionManager(); | 
 |       if (m_conn_man->getNumEndPoints() > 0) { | 
 |         if (!initDone) { | 
 |           adminRgn->init(); | 
 |           initDone = true; | 
 |         } | 
 |         int puts = 0, gets = 0, misses = 0, numListeners = 0, numThreads = 0, | 
 |             creates = 0; | 
 |         int64 cpuTime = 0; | 
 |         GeodeStatisticsFactory* gf = | 
 |             GeodeStatisticsFactory::getExistingInstance(); | 
 |         if (gf) { | 
 |           StatisticsType* cacheStatType = gf->findType("CachePerfStats"); | 
 |           if (cacheStatType) { | 
 |             Statistics* cachePerfStats = | 
 |                 gf->findFirstStatisticsByType(cacheStatType); | 
 |             if (cachePerfStats) { | 
 |               puts = cachePerfStats->getInt((char*)"puts"); | 
 |               gets = cachePerfStats->getInt((char*)"gets"); | 
 |               misses = cachePerfStats->getInt((char*)"misses"); | 
 |               creates = cachePerfStats->getInt((char*)"creates"); | 
 |               numListeners = | 
 |                   cachePerfStats->getInt((char*)"cacheListenerCallsCompleted"); | 
 |               puts += creates; | 
 |             } | 
 |           } | 
 |           numThreads = HostStatHelper::getNumThreads(); | 
 |           cpuTime = HostStatHelper::getCpuTime(); | 
 |         } | 
 |         static int numCPU = ACE_OS::num_processors(); | 
 |         ClientHealthStatsPtr obj = ClientHealthStats::create( | 
 |             gets, puts, misses, numListeners, numThreads, cpuTime, numCPU); | 
 |         if (clientId.empty()) { | 
 |           ACE_TCHAR hostName[256]; | 
 |           ACE_OS::hostname(hostName, sizeof(hostName) - 1); | 
 |           ACE_INET_Addr driver("", hostName, "tcp"); | 
 |           uint32_t hostAddr = driver.get_ip_address(); | 
 |           uint16_t hostPort = 0; | 
 |           SystemProperties* sysProp = DistributedSystem::getSystemProperties(); | 
 |           const char* durableId = | 
 |               (sysProp != NULL) ? sysProp->durableClientId() : NULL; | 
 |           const uint32_t durableTimeOut = | 
 |               (sysProp != NULL) ? sysProp->durableTimeout() : 0; | 
 |  | 
 |           ClientProxyMembershipID memId(hostName, hostAddr, hostPort, durableId, | 
 |                                         durableTimeOut); | 
 |           clientId = memId.getDSMemberIdForThinClientUse(); | 
 |         } | 
 |  | 
 |         CacheableKeyPtr keyPtr = CacheableString::create(clientId.c_str()); | 
 |         adminRgn->put(keyPtr, obj); | 
 |       } | 
 |     } | 
 |   } catch (const Exception&) { | 
 |     m_adminError = true; | 
 |   } | 
 | } | 
 |  | 
 | void HostStatSampler::writeGfs() { | 
 |   std::string archivefilename = createArchiveFileName(); | 
 |   changeArchive(archivefilename); | 
 | } | 
 |  | 
 | void HostStatSampler::forceSample() { | 
 |   ACE_Guard<ACE_Recursive_Thread_Mutex> samplingGuard(m_samplingLock); | 
 |  | 
 |   if (m_archiver) { | 
 |     sampleSpecialStats(); | 
 |     m_archiver->sample(); | 
 |     m_archiver->flush(); | 
 |   } | 
 | } | 
 |  | 
 | void HostStatSampler::doSample(std::string& archivefilename) { | 
 |   ACE_Guard<ACE_Recursive_Thread_Mutex> samplingGuard(m_samplingLock); | 
 |  | 
 |   sampleSpecialStats(); | 
 |   checkListeners(); | 
 |  | 
 |   // Populate Admin Region for GFMon | 
 |   if (isSamplingEnabled() && !m_adminError && | 
 |       !TcrConnectionManager::isNetDown) { | 
 |     putStatsInAdminRegion(); | 
 |   } | 
 |  | 
 |   m_archiver->sample(); | 
 |  | 
 |   if (m_archiveFileSizeLimit != 0) { | 
 |     int64 size = m_archiver->getSampleSize(); | 
 |     int64 bytesWritten = m_archiver->bytesWritten();  // + g_previoussamplesize; | 
 |     if (bytesWritten > (m_archiveFileSizeLimit - size)) { | 
 |       // roll the archive | 
 |       changeArchive(archivefilename); | 
 |     } | 
 |   } | 
 |   g_spaceUsed += m_archiver->bytesWritten(); | 
 |   // delete older stat files if disk limit is about to be exceeded. | 
 |   if ((m_archiveDiskSpaceLimit != 0) && | 
 |       (g_spaceUsed >= | 
 |        (m_archiveDiskSpaceLimit - m_archiver->getSampleSize()))) { | 
 |     checkDiskLimit(); | 
 |   } | 
 |  | 
 |   // It will flush the contents to the archive file, in every | 
 |   // sample run. | 
 |  | 
 |   m_archiver->flush(); | 
 | } | 
 |  | 
 | void HostStatSampler::checkDiskLimit() { | 
 |   g_fileInfo fileInfo; | 
 |   g_spaceUsed = 0; | 
 |   char fullpath[512] = {0}; | 
 |   std::string dirname = ACE::dirname(g_statFile.c_str()); | 
 |   // struct dirent **resultArray; | 
 |   // int entries_count = ACE_OS::scandir(dirname.c_str(), &resultArray, | 
 |   // selector, comparator); | 
 |   ACE_stat statBuf = {0}; | 
 |   ACE_Dirent_Selector sds; | 
 |   int status = sds.open(dirname.c_str(), selector, comparator); | 
 |   if (status != -1) { | 
 |     for (int i = 1; i < sds.length(); i++) { | 
 |       ACE_OS::snprintf(fullpath, 512, "%s%c%s", dirname.c_str(), | 
 |                        ACE_DIRECTORY_SEPARATOR_CHAR, sds[i]->d_name); | 
 |       ACE_OS::stat(fullpath, &statBuf); | 
 |       g_fileInfoPair = std::make_pair(fullpath, statBuf.st_size); | 
 |       fileInfo.push_back(g_fileInfoPair); | 
 |       g_spaceUsed += fileInfo[i - 1].second; | 
 |     } | 
 |     g_spaceUsed += m_archiver->bytesWritten(); | 
 |     /*for(int i = 0; i < entries_count; i++) { | 
 |     ACE_OS::free ( resultArray[i] ); | 
 |     } | 
 |     if (entries_count >= 0) { | 
 |     ACE_OS::free( resultArray ); | 
 |     resultArray = NULL; | 
 |     }*/ | 
 |     sds.close(); | 
 |   } | 
 |   int fileIndex = 0; | 
 |   while ((g_spaceUsed > | 
 |           m_archiveDiskSpaceLimit) /*&& (fileIndex < entries_count)*/) { | 
 |     int64 fileSize = fileInfo[fileIndex].second; | 
 |     if (ACE_OS::unlink(fileInfo[fileIndex].first.c_str()) == 0) { | 
 |       g_spaceUsed -= fileSize; | 
 |     } else { | 
 |       LOGWARN("%s\t%s\n", "Could not delete", | 
 |               fileInfo[fileIndex].first.c_str()); | 
 |     } | 
 |     fileIndex++; | 
 |   } | 
 | } | 
 |  | 
 | int32 HostStatSampler::svc(void) { | 
 |   DistributedSystemImpl::setThreadName(NC_HSS_Thread); | 
 |   try { | 
 |     initSpecialStats(); | 
 |     // createArchiveFileName instead of getArchiveFileName here because | 
 |     // for the first time the sampler needs to add the pid to the filename | 
 |     // passed to it. | 
 |     std::string archivefilename = createArchiveFileName(); | 
 |     if (!m_isStatDiskSpaceEnabled) { | 
 |       changeArchive(archivefilename); | 
 |     } | 
 |     int32 msSpentWorking = 0; | 
 |     int32 msRate = static_cast<int32>(getSampleRate()); | 
 |     bool gotexception = false; | 
 |     int waitTime = 0; | 
 |     while (!m_stopRequested) { | 
 |       try { | 
 |         if (gotexception) { | 
 |           ACE_OS::sleep(1); | 
 |  | 
 |           waitTime++; | 
 |           if (waitTime < 60) {  // sleep for minute and then try to recreate | 
 |             continue; | 
 |           } | 
 |           waitTime = 0; | 
 |           gotexception = false; | 
 |           changeArchive(archivefilename); | 
 |         } | 
 |         int64 sampleStartNanos = NanoTimer::now(); | 
 |  | 
 |         doSample(archivefilename); | 
 |  | 
 |         int64 sampleEndNanos = NanoTimer::now(); | 
 |         int64 nanosSpentWorking = sampleEndNanos - sampleStartNanos; | 
 |         // updating the sampler statistics | 
 |         accountForTimeSpentWorking(nanosSpentWorking); | 
 |         msSpentWorking = static_cast<int32>(nanosSpentWorking / 1000000); | 
 |  | 
 |         // Continous check for m_stopRequested to sped up stop time. | 
 |         int32 msToWait = msRate - msSpentWorking; | 
 |         while (msToWait > 0) { | 
 |           ACE_Time_Value sleepTime; | 
 |           sleepTime.msec(msToWait > 100 ? 100 : msToWait); | 
 |           ACE_OS::sleep(sleepTime); | 
 |           msToWait -= 100; | 
 |           if (m_stopRequested) { | 
 |             break; | 
 |           } | 
 |         } | 
 |       } catch (Exception& e) { | 
 |         // log the exception and let the thread exit. | 
 |         LOGERROR("Exception in statistics sampler thread: %s: %s", e.getName(), | 
 |                  e.getMessage()); | 
 |         // now close current archiver and see if we can start new one | 
 |         gotexception = true; | 
 |       } catch (...) { | 
 |         LOGERROR("Unknown Exception in statistics sampler thread: "); | 
 |         gotexception = true; | 
 |       } | 
 |     } | 
 |     closeSpecialStats(); | 
 |     m_samplerStats->close(); | 
 |     if (m_archiver != NULL) { | 
 |       m_archiver->close(); | 
 |     } | 
 |   } catch (Exception& e) { | 
 |     // log the exception and let the thread exit. | 
 |     LOGERROR("Exception in statistics sampler thread: %s: %s", e.getName(), | 
 |              e.getMessage()); | 
 |     closeSpecialStats(); | 
 |   } /* catch (...) { | 
 |        // log the exception and let the thread exit. | 
 |        LOGERROR("Exception in sampler thread "); | 
 |        closeSpecialStats(); | 
 |    }*/ | 
 |   m_running = false; | 
 |   return 0; | 
 | } |