host/common/HealthCollator.cpp (632 lines of code) (raw):

#include<iostream> #include<sstream> #include<fstream> #include<boost/filesystem.hpp> #include <boost/interprocess/sync/file_lock.hpp> #include <boost/interprocess/sync/scoped_lock.hpp> #include <boost/interprocess/sync/sharable_lock.hpp> #include<boost/date_time.hpp> #include <boost/date_time/posix_time/posix_time.hpp> #include <boost/date_time/posix_time/posix_time_io.hpp> #include "logger.h" #include "inmageex.h" #include "portablehelpers.h" #include "HealthCollator.h" #define HEALTH_COLLATOR_CATCH_EXCEPTION(errMsg,status) \ catch (const JSON::json_exception& jsone) \ { \ errMsg += std::string("JSON parser failed with exception: ") + jsone.what(); \ status = false; \ DebugPrintf(SV_LOG_ERROR,"%s: %s",FUNCTION_NAME,errMsg.c_str()); \ } \ catch (const std::exception &e) \ { \ errMsg += std::string("Standard Exception occurred:") + e.what(); \ status = false; \ DebugPrintf(SV_LOG_ERROR,"%s: %s",FUNCTION_NAME,errMsg.c_str()); \ } \ catch (...) \ { \ errMsg += std::string("Generic Exception occurred."); \ status = false; \ DebugPrintf(SV_LOG_ERROR,"%s: %s",FUNCTION_NAME,errMsg.c_str()); \ } // can change to SV_LOG_ALWAYS for debugging SV_LOG_LEVEL HealthCollator::s_logLevel = SV_LOG_DEBUG; HealthCollator::HealthCollator(const std::string& strHealthJsonFile) :m_HealthJsonFile(strHealthJsonFile), m_HealthJsonFileLock(strHealthJsonFile + std::string(".lck")) { DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME); Init(); DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME); } void HealthCollator::Init() { DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME); bool bStatus = true; std::string errMsg; boost::filesystem::path healthFilePath = m_HealthJsonFile; boost::system::error_code ec; // if the file is not found, there are no previous health issues if (!boost::filesystem::exists(healthFilePath.c_str(), ec)) { DebugPrintf(s_logLevel, "%s: no previous health file %s found.\n", FUNCTION_NAME, m_HealthJsonFile.c_str()); return; } //If already a health file is there with health issues then load them into memory ReadSerializedHealthIssuesFromJsonFile(); if (m_strHealthIssuesAsJsonContent.empty()) { DebugPrintf(s_logLevel, "%s: previous health file %s found is empty.\n", FUNCTION_NAME, m_HealthJsonFile.c_str()); DeleteHealthFile(); return; } // load any existing health issues try { m_allHealthIssuesMap = JSON::consumer<SourceAgentProtectionPairHealthIssuesMap>::convert(m_strHealthIssuesAsJsonContent); if (m_allHealthIssuesMap.VMLevelHIsMap.empty() && m_allHealthIssuesMap.DiskLevelHIsMap.empty()) { DebugPrintf(s_logLevel, "%s: previous health file %s found has no health issues.\n", FUNCTION_NAME, m_HealthJsonFile.c_str()); DeleteHealthFile(); } } HEALTH_COLLATOR_CATCH_EXCEPTION(errMsg, bStatus); if (!bStatus) { DebugPrintf(SV_LOG_ERROR,"%s: deleting file %s as failed to deserialize existing health issues from file.\n", FUNCTION_NAME, m_HealthJsonFile.c_str()); DeleteHealthFile(); } DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME); return; } void HealthCollator::ReadSerializedHealthIssuesFromJsonFile() { DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME); std::string strException; //Use file lock to read the content std::ofstream lckFile(m_HealthJsonFileLock.c_str(), std::ofstream::out); if (!lckFile.good()) { strException = "failed to create lock file."; throw INMAGE_EX(strException.c_str())(m_HealthJsonFileLock.c_str())(errno); } //Create a file lock object for the file boost::interprocess::file_lock flock(m_HealthJsonFileLock.c_str()); //Assign a scoped lock object for the above file lock object boost::interprocess::sharable_lock<boost::interprocess::file_lock> sharableFlock(flock); //Read the file content std::ifstream hlthJsonFile(m_HealthJsonFile.c_str(), std::ifstream::in); if (!hlthJsonFile.good()) { strException = "failed to read file."; throw INMAGE_EX(strException.c_str())(m_HealthJsonFileLock.c_str())(errno); } std::stringstream ssJsonContent; ssJsonContent << hlthJsonFile.rdbuf(); hlthJsonFile.close(); m_strHealthIssuesAsJsonContent = ssJsonContent.str(); DebugPrintf(s_logLevel, "%s: Read the following Health Issues from the file %s as JSON content:%s\n", FUNCTION_NAME, m_HealthJsonFile.c_str(), m_strHealthIssuesAsJsonContent.c_str()); DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME); return; } void HealthCollator::DeleteHealthFile() { DebugPrintf(s_logLevel, "ENTERED %s: %s\n", FUNCTION_NAME, m_HealthJsonFile.c_str()); int nRetryCounter = 0; // retry 3 times on any exception to delete the file while (nRetryCounter < 3) { try { if (boost::filesystem::exists(m_HealthJsonFile)) boost::filesystem::remove(m_HealthJsonFile); if (boost::filesystem::exists(m_HealthJsonFileLock)) boost::filesystem::remove(m_HealthJsonFileLock); break; } catch (const std::exception& ex) { DebugPrintf(SV_LOG_ERROR, "%s: caught excetpion %s\n", FUNCTION_NAME, ex.what()); nRetryCounter++; boost::this_thread::sleep(boost::posix_time::seconds(1)); } catch (...) { DebugPrintf(SV_LOG_ERROR, "%s: caught unknown excetpion\n", FUNCTION_NAME); nRetryCounter++; boost::this_thread::sleep(boost::posix_time::seconds(1)); } } DebugPrintf(s_logLevel, "EXITED %s\n", FUNCTION_NAME); } bool HealthCollator::GetAllHealthIssues(SourceAgentProtectionPairHealthIssues& healthIssues) { DebugPrintf(s_logLevel, "ENTERED %s\n", FUNCTION_NAME); boost::recursive_mutex::scoped_lock slock(m_hiMutex); bool bStatus = false; std::string errMsg; try { HealthIssueMap_t::const_iterator vmHIIter = m_allHealthIssuesMap.VMLevelHIsMap.begin(); for (; vmHIIter != m_allHealthIssuesMap.VMLevelHIsMap.end(); vmHIIter++) { HealthIssue hi = JSON::consumer<HealthIssue>::convert(vmHIIter->second); healthIssues.HealthIssues.push_back(hi); } HealthIssueMap_t::const_iterator diskHIIter = m_allHealthIssuesMap.DiskLevelHIsMap.begin(); for (; diskHIIter != m_allHealthIssuesMap.DiskLevelHIsMap.end(); diskHIIter++) { AgentDiskLevelHealthIssue diskHi = JSON::consumer<AgentDiskLevelHealthIssue>::convert(diskHIIter->second); healthIssues.DiskLevelHealthIssues.push_back(diskHi); } bStatus = true; } catch (const std::exception &ex) { DebugPrintf(SV_LOG_ERROR, "%s: failed with exception: %s.\n", FUNCTION_NAME, ex.what()); } catch (...) { DebugPrintf(SV_LOG_ERROR, "%s failed with an unknown exception.\n", FUNCTION_NAME); } DebugPrintf(s_logLevel, "EXITED %s\n", FUNCTION_NAME); return bStatus; } bool HealthCollator::SetVMHealthIssue(HealthIssue& vmHealthIssue) { DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME); if (vmHealthIssue.IssueCode.empty()) { DebugPrintf(SV_LOG_ERROR, "%s: the health issue code is empty.\n", FUNCTION_NAME); return false; } //mutex to synchronize the set and reset updates of health issues from across the process boost::recursive_mutex::scoped_lock slock(m_hiMutex); std::string errMsg; bool bPersisted = false; try { //Check if the same health issue code is already there, then don't overwrite the file //as we want to preserve observed time if (!IsHealthIssuePresent(vmHealthIssue.IssueCode, m_allHealthIssuesMap.VMLevelHIsMap)) { //else if a new health issue is observed, add this as a new health issue std::string strSerializedHealthIssue = JSON::producer<HealthIssue>::convert(vmHealthIssue); m_allHealthIssuesMap.VMLevelHIsMap[vmHealthIssue.IssueCode] = strSerializedHealthIssue; std::string strContent = JSON::producer<SourceAgentProtectionPairHealthIssuesMap>::convert(m_allHealthIssuesMap); //and persist to the .json health file RemoveChar(strContent, '\r'); RemoveChar(strContent, '\n'); bPersisted = WriteToJsonHealthFileWithRetry(strContent); if (bPersisted) { m_strHealthIssuesAsJsonContent = strContent; DebugPrintf(s_logLevel, "%s: A new VM Level Health Issue Code %s is added. file contents: %s\n", FUNCTION_NAME, vmHealthIssue.IssueCode.c_str(), m_strHealthIssuesAsJsonContent.c_str()); } } else { bPersisted = true; DebugPrintf(s_logLevel, "%s: existing VM Level Health Issue Code %s not added. file contents: %s\n", FUNCTION_NAME, vmHealthIssue.IssueCode.c_str(), m_strHealthIssuesAsJsonContent.c_str()); } } HEALTH_COLLATOR_CATCH_EXCEPTION(errMsg, bPersisted); if (!bPersisted) { DebugPrintf(SV_LOG_ERROR, "%s:Failed to write the Health Issue %s to the file. restoring to old state.\n", FUNCTION_NAME, vmHealthIssue.IssueCode.c_str()); RestoreOldState(); } DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME); return bPersisted; } void HealthCollator::RestoreOldState() { DebugPrintf(s_logLevel, "ENTERED %s: %s\n", FUNCTION_NAME, m_HealthJsonFile.c_str()); std::string errMsg; bool bStatus = false; try { if (!m_strHealthIssuesAsJsonContent.empty()) { m_allHealthIssuesMap = JSON::consumer< SourceAgentProtectionPairHealthIssuesMap>::convert(m_strHealthIssuesAsJsonContent); } DebugPrintf(s_logLevel, "%s: file %s, content %s.\n", FUNCTION_NAME, m_HealthJsonFile.c_str(), m_strHealthIssuesAsJsonContent.c_str()); } HEALTH_COLLATOR_CATCH_EXCEPTION(errMsg, bStatus); DebugPrintf(s_logLevel, "EXITED %s\n", FUNCTION_NAME); return; } bool HealthCollator::ResetVMHealthIssue(const std::string &vmHealthIssueCode) { DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME); if (vmHealthIssueCode.empty()) { DebugPrintf(SV_LOG_ERROR, "%s: HealthIssue Code is empty.\n", FUNCTION_NAME); return false; } std::vector<std::string>VMHealthIssues; VMHealthIssues.push_back(vmHealthIssueCode); DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME); return ResetVMHealthIssues(VMHealthIssues); } bool HealthCollator::ResetVMHealthIssues(const std::vector<std::string>&vHealthIssueCodes) { DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME); if (vHealthIssueCodes.empty()) { DebugPrintf(SV_LOG_ERROR, "%s: no HealthIssue Codes supplied.\n", FUNCTION_NAME); return false; } bool bFound = false; std::string errMsg; bool bPersisted = false; //synchronize with a scoped lock mutex boost::recursive_mutex::scoped_lock slock(m_hiMutex); try { std::map<std::string, std::string> tempVMHealthIssuesMap(m_allHealthIssuesMap.VMLevelHIsMap.begin(), m_allHealthIssuesMap.VMLevelHIsMap.end()); std::map<std::string, std::string >::iterator mapIter; std::vector<std::string>::const_iterator resetIter; for (resetIter=vHealthIssueCodes.begin(); resetIter != vHealthIssueCodes.end(); resetIter++) { mapIter = m_allHealthIssuesMap.VMLevelHIsMap.find(*resetIter); if (mapIter != m_allHealthIssuesMap.VMLevelHIsMap.end()) { bFound = true; m_allHealthIssuesMap.VMLevelHIsMap.erase(mapIter); } } if (!bFound) { DebugPrintf(s_logLevel, "EXITED %s as no health issue code found.\n", FUNCTION_NAME); return true; } if (m_allHealthIssuesMap.VMLevelHIsMap.empty() && m_allHealthIssuesMap.DiskLevelHIsMap.empty()) { DebugPrintf(s_logLevel, "%s: deleting health file as there are no other health issues.\n", FUNCTION_NAME); m_strHealthIssuesAsJsonContent.clear(); DeleteHealthFile(); DebugPrintf(s_logLevel, "EXITED %s as health file is deleted.\n", FUNCTION_NAME); return true; } //get the serialized health content std::string strContent = JSON::producer<SourceAgentProtectionPairHealthIssuesMap>::convert(m_allHealthIssuesMap); //Write to the .json health file RemoveChar(strContent, '\r'); RemoveChar(strContent, '\n'); //even if this below write fails, the health issue will be cleaned in memory so that next write is attempted later and it can succeed bPersisted = WriteToJsonHealthFileWithRetry(strContent); if (bPersisted) { m_strHealthIssuesAsJsonContent = strContent; } } HEALTH_COLLATOR_CATCH_EXCEPTION(errMsg, bPersisted); if (!bPersisted) { DebugPrintf(SV_LOG_ERROR, "%s: failed to persist to file, restoring to previous state.\n", FUNCTION_NAME); RestoreOldState(); } DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME); return bPersisted; } bool HealthCollator::SetDiskHealthIssue(AgentDiskLevelHealthIssue& diskHealthIssue) { DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME); if (diskHealthIssue.DiskContext.empty() || diskHealthIssue.IssueCode.empty()) { DebugPrintf(SV_LOG_ERROR, "%s: Either DiskContext = \"%s\" or Disk Health Issue code = \"%s\" is empty. Cannot set disk health issue.\n", FUNCTION_NAME, diskHealthIssue.DiskContext.c_str(), diskHealthIssue.IssueCode.c_str()); return false; } boost::recursive_mutex::scoped_lock slock(m_hiMutex); std::string errMsg; bool bPersisted = false; std::string strUniqDiskHlthIssue; COMBINE_DISKID_WITH_HEALTH_ISSUE_CODE(diskHealthIssue.DiskContext, diskHealthIssue.IssueCode, strUniqDiskHlthIssue); try { //Check if the same health issue code is already there, then don't overwrite the file as we want to preserve observed time if (!IsHealthIssuePresent(strUniqDiskHlthIssue, m_allHealthIssuesMap.DiskLevelHIsMap)) { std::string strSerializedDiskLevelHealthIssue = JSON::producer<AgentDiskLevelHealthIssue>::convert(diskHealthIssue); m_allHealthIssuesMap.DiskLevelHIsMap[strUniqDiskHlthIssue] = strSerializedDiskLevelHealthIssue; std::string strContent = JSON::producer<SourceAgentProtectionPairHealthIssuesMap>::convert(m_allHealthIssuesMap); //and persist to the .json health file RemoveChar(strContent, '\r'); RemoveChar(strContent, '\n'); bPersisted = WriteToJsonHealthFileWithRetry(strContent); if (bPersisted) { m_strHealthIssuesAsJsonContent = strContent; DebugPrintf(s_logLevel, "%s:A new Disk Level Health Issue Code %s for disk %s is added. %s\n", FUNCTION_NAME, diskHealthIssue.IssueCode.c_str(), diskHealthIssue.DiskContext.c_str(), strSerializedDiskLevelHealthIssue.c_str()); } } else { //same health issue occurred bPersisted = true; DebugPrintf(s_logLevel, "%s: Health Issue %s for %s - already exists.\n", FUNCTION_NAME, diskHealthIssue.IssueCode.c_str(), diskHealthIssue.DiskContext.c_str()); } } HEALTH_COLLATOR_CATCH_EXCEPTION(errMsg, bPersisted); if (!bPersisted) { //remove the disk health issue from the map which was added just above DebugPrintf(SV_LOG_ERROR, "%s: failed to persiste the disk health issue %s. restoring to old state.\n", FUNCTION_NAME, strUniqDiskHlthIssue.c_str()); RestoreOldState(); } DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME); return bPersisted; } bool HealthCollator::ResetDiskHealthIssue(const std::string &diskHealthIssueCode, const std::string& strDiskId) { DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME); std::vector<std::string>vDiskIssues; if (diskHealthIssueCode.empty() || strDiskId.empty()) { DebugPrintf(SV_LOG_ERROR, "%s:Either DiskId = %s or Disk Health Issue code = %s is empty.\n", FUNCTION_NAME,strDiskId.c_str(),diskHealthIssueCode.c_str()); return false; } vDiskIssues.push_back(diskHealthIssueCode); DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME); return ResetDiskHealthIssues(vDiskIssues, strDiskId); } bool HealthCollator::ResetDiskHealthIssues(const std::vector<std::string>&vdiskHealthIssueCodes, const std::string& strDiskId) { DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME); if (vdiskHealthIssueCodes.empty()||strDiskId.empty()) { DebugPrintf(SV_LOG_ERROR, "%s:Either the health issues list count = %d is zero or the diskid = %s is empty.\n", FUNCTION_NAME,vdiskHealthIssueCodes.size(),strDiskId.c_str()); return false; } boost::recursive_mutex::scoped_lock slock(m_hiMutex); bool bFound = false; std::string errMsg; bool bPersisted = false; try { const std::map < std::string, std::string>tempDiskLevelHealthIssuesMap(m_allHealthIssuesMap.DiskLevelHIsMap.begin(), m_allHealthIssuesMap.DiskLevelHIsMap.end()); std::map<const std::string, std::string>::iterator diskIssuesMapIter; std::vector<std::string>::const_iterator resetIter = vdiskHealthIssueCodes.begin(); std::string strUniqDiskHlthIssue; for (; resetIter != vdiskHealthIssueCodes.end(); resetIter++) { strUniqDiskHlthIssue = ""; COMBINE_DISKID_WITH_HEALTH_ISSUE_CODE(strDiskId, *resetIter, strUniqDiskHlthIssue); diskIssuesMapIter = m_allHealthIssuesMap.DiskLevelHIsMap.find(strUniqDiskHlthIssue); if (diskIssuesMapIter != m_allHealthIssuesMap.DiskLevelHIsMap.end()) { m_allHealthIssuesMap.DiskLevelHIsMap.erase(diskIssuesMapIter); bFound = true; } } if (!bFound) { DebugPrintf(s_logLevel, "EXITED %s as no health issue code found.\n", FUNCTION_NAME); return true; } if (m_allHealthIssuesMap.VMLevelHIsMap.empty() && m_allHealthIssuesMap.DiskLevelHIsMap.empty()) { DebugPrintf(s_logLevel, "%s: deleting health file as there are no other health issues.\n", FUNCTION_NAME); m_strHealthIssuesAsJsonContent.clear(); DeleteHealthFile(); DebugPrintf(s_logLevel, "EXITED %s as health file is deleted.\n", FUNCTION_NAME); return true; } //get the serialized health content std::string strContent = JSON::producer<SourceAgentProtectionPairHealthIssuesMap>::convert(m_allHealthIssuesMap); //Write to the .json health file RemoveChar(strContent, '\r'); RemoveChar(strContent, '\n'); bPersisted = WriteToJsonHealthFileWithRetry(strContent); if (bPersisted) { m_strHealthIssuesAsJsonContent = strContent; } } HEALTH_COLLATOR_CATCH_EXCEPTION(errMsg, bPersisted); if (!bPersisted) { DebugPrintf(SV_LOG_ERROR, "%s: failed to persist the Disk Health Issues to file, restoring the old state.\n", FUNCTION_NAME); RestoreOldState(); } DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME); return (bPersisted); } bool HealthCollator::WriteToJsonHealthFileWithRetry(const std::string& strContent) { DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME); int nRetryCounter = 0; bool bStatus = false; //Retrying for 3 times while (!bStatus && (nRetryCounter < 3)) { if (bStatus = WriteToJsonHealthFile(strContent)) { break; } else { nRetryCounter++; boost::this_thread::sleep(boost::posix_time::seconds(1)); } } DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME); return bStatus; } bool HealthCollator::WriteToJsonHealthFile(const std::string& strContent) { DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME); bool bStatus = false; try { boost::filesystem::path healthFilePath = m_HealthJsonFile; boost::system::error_code ec; //If the file is not found, then create the .json file if (!boost::filesystem::exists(healthFilePath.c_str(), ec)) { DebugPrintf(s_logLevel, "%s: creating new health file %s.\n", FUNCTION_NAME, m_HealthJsonFile.c_str()); if (!InitJsonFile()) { DebugPrintf(SV_LOG_ERROR, "%s: failed to initialize new file %s.\n", FUNCTION_NAME, m_HealthJsonFile.c_str()); return false; } } //Prepare to write the serialized content into a json health file std::ofstream lckFile(m_HealthJsonFileLock.c_str(), std::ofstream::out); if (!lckFile.good()) { DebugPrintf(SV_LOG_ERROR, "%s:Failed to create lock file %s with error 0x%x\n", FUNCTION_NAME, m_HealthJsonFileLock.c_str(), errno); return false; } //Create a file lock object for the file boost::interprocess::file_lock flock(m_HealthJsonFileLock.c_str()); //Assign a scoped lock object for the above file lock object boost::interprocess::scoped_lock<boost::interprocess::file_lock> slock(flock); //Now write the serialized content to the actual health json file std::ofstream healthJsonFile(m_HealthJsonFile.c_str(), std::ofstream::out); if (!healthJsonFile.good()) { DebugPrintf(SV_LOG_ERROR, "%s:Failed to create the file %s with error 0x%x\n", FUNCTION_NAME, m_HealthJsonFile.c_str(), errno); healthJsonFile.close(); return false; } //if file status is good, then dump the serialized content into the file healthJsonFile << strContent; if (healthJsonFile.good()) { bStatus = true; } else { bStatus = false; } healthJsonFile.close(); DebugPrintf(s_logLevel, "%s:Health Issues written to the file: %s :%s\n", FUNCTION_NAME, m_HealthJsonFile.c_str(), strContent.c_str()); } catch (const boost::interprocess::interprocess_exception &ipc_ex) { DebugPrintf(SV_LOG_ERROR, "%s: failed with boost::interprocess::interprocess_exception: %s.\n", FUNCTION_NAME, ipc_ex.what()); } catch (const std::exception &ex) { DebugPrintf(SV_LOG_ERROR, "%s: failed with exception: %s.\n", FUNCTION_NAME, ex.what()); } catch (...) { DebugPrintf(SV_LOG_ERROR, "%s failed with an unknown exception.\n", FUNCTION_NAME); } DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME); return bStatus; } bool HealthCollator::InitJsonFile() { DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME); bool bStatus = false; try { boost::filesystem::path healthFilePath = m_HealthJsonFile; boost::system::error_code ec; if (!boost::filesystem::exists(healthFilePath.parent_path().c_str(), ec)) { DebugPrintf(s_logLevel, "%s:Creating directory %s for AgentHealth.\n", FUNCTION_NAME, healthFilePath.parent_path().c_str()); if (!boost::filesystem::create_directories(healthFilePath.parent_path(), ec)) { DebugPrintf(SV_LOG_ERROR, "%s:Failed to create directory %s with error code 0x%x. error message : %s\n", FUNCTION_NAME, healthFilePath.parent_path().c_str(), ec.value(), ec.message().c_str()); return false; } DebugPrintf(SV_LOG_ALWAYS, "%s: created directory %s\n", FUNCTION_NAME, healthFilePath.parent_path().c_str()); } //Use file lock to create the file or read the content std::ofstream lckFile(m_HealthJsonFileLock.c_str(), std::ofstream::out); if (!lckFile.good()) { DebugPrintf(SV_LOG_ERROR, "%s:Failed to create lock file %s with error 0x%x\n", FUNCTION_NAME, m_HealthJsonFileLock.c_str(), errno); return false; } //Create a file lock object for the file boost::interprocess::file_lock flock(m_HealthJsonFileLock.c_str()); //Assign a scoped lock object for the above file lock object boost::interprocess::scoped_lock<boost::interprocess::file_lock> slock(flock); std::ofstream healthJsonFile(m_HealthJsonFile.c_str(), std::ofstream::out); if (!healthJsonFile.good()) { DebugPrintf(SV_LOG_ERROR, "%s:Failed to create the file %s with error 0x%x\n", FUNCTION_NAME, m_HealthJsonFile.c_str(), errno); healthJsonFile.close(); return false; } //fill the created file with the empty json content //{"VMLevelHIsMap":{},"DiskLevelHIsMap":{}} SourceAgentProtectionPairHealthIssuesMap sapphm; std::string strJsonContent = JSON::producer<SourceAgentProtectionPairHealthIssuesMap>::convert(sapphm); healthJsonFile << strJsonContent; healthJsonFile.flush(); healthJsonFile.close(); bStatus = true; DebugPrintf(s_logLevel, "%s: file %s persisted with content %s.\n", FUNCTION_NAME, m_HealthJsonFile.c_str(), strJsonContent.c_str()); } catch (const boost::interprocess::interprocess_exception &ipc_ex) { DebugPrintf(SV_LOG_ERROR, "%s: failed with boost::interprocess::interprocess_exception: %s.\n", FUNCTION_NAME, ipc_ex.what()); } catch (const std::exception &ex) { DebugPrintf(SV_LOG_ERROR, "%s: failed with exception: %s.\n", FUNCTION_NAME, ex.what()); } catch (...) { DebugPrintf(SV_LOG_ERROR, "%s failed with an unknown exception.\n", FUNCTION_NAME); } DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME); return bStatus; } std::string HealthCollator::GetCurrentObservationTime() { DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME); std::stringstream sstrLocalTime; boost::posix_time::ptime timeLocal = boost::posix_time::second_clock::universal_time(); sstrLocalTime << boost::posix_time::to_simple_string(timeLocal); sstrLocalTime << " UTC"; DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME); return sstrLocalTime.str(); } bool HealthCollator::IsHealthIssuePresent(const std::string& healthIssueCode, const HealthIssueMap_t& mapHealthIssues) const { DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME); bool retval = false; if (!mapHealthIssues.empty()) { retval = mapHealthIssues.find(healthIssueCode) != mapHealthIssues.end(); } DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME); return retval; } bool HealthCollator::IsVMHealthIssuePresent(const std::string& healthIssueCode) const { DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME); DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME); return IsHealthIssuePresent(healthIssueCode, m_allHealthIssuesMap.VMLevelHIsMap); } bool HealthCollator::IsDiskHealthIssuePresent(const std::string& healthIssueCode, const std::string& diskId) const { DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME); std::string strUniqueDiskHealthIssue; COMBINE_DISKID_WITH_HEALTH_ISSUE_CODE(diskId, healthIssueCode, strUniqueDiskHealthIssue); DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME); return IsHealthIssuePresent(strUniqueDiskHealthIssue, m_allHealthIssuesMap.DiskLevelHIsMap); } bool HealthCollator::IsThereAnyHealthIssue() const { DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME); boost::recursive_mutex::scoped_lock slock(m_hiMutex); DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME); return(!(m_allHealthIssuesMap.VMLevelHIsMap.empty()) || !(m_allHealthIssuesMap.DiskLevelHIsMap.empty())); } bool HealthCollator::IsThereAnyDiskLevelHealthIssue() const { DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME); boost::recursive_mutex::scoped_lock slock(m_hiMutex); DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME); return !m_allHealthIssuesMap.DiskLevelHIsMap.empty(); } bool HealthCollator::IsThisHealthIssueFound(const std::string& healthIssueCode) { DebugPrintf(SV_LOG_DEBUG, "ENTERED %s\n", FUNCTION_NAME); bool bFound = true; boost::recursive_mutex::scoped_lock slock(m_hiMutex); if (!IsHealthIssuePresent(healthIssueCode, m_allHealthIssuesMap.VMLevelHIsMap) && !IsHealthIssuePresent(healthIssueCode, m_allHealthIssuesMap.DiskLevelHIsMap)) { bFound = false; } DebugPrintf(SV_LOG_DEBUG, "EXITED %s\n", FUNCTION_NAME); return bFound; }