blob: d56b886887215242de4e2f020ebd1865ccae4b8d [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 "util/Log.hpp"
#include <cctype>
#include <chrono>
#include <cinttypes>
#include <string>
#include <thread>
#include <utility>
#include <vector>
#include <ace/ACE.h>
#include <ace/Dirent.h>
#include <ace/Dirent_Selector.h>
#include <ace/Guard_T.h>
#include <ace/OS.h>
#include <ace/OS_NS_Thread.h>
#include <ace/OS_NS_sys_stat.h>
#include <ace/OS_NS_sys_time.h>
#include <ace/OS_NS_time.h>
#include <ace/OS_NS_unistd.h>
#include <ace/Thread_Mutex.h>
#include <geode/ExceptionTypes.hpp>
#include <geode/internal/geode_globals.hpp>
#include <geode/util/LogLevel.hpp>
#include "../internal/hacks/AceThreadId.h"
#include "Assert.hpp"
#include "geodeBanner.hpp"
#if defined(_WIN32)
#include <io.h>
#define GF_FILEEXISTS(x) _access_s(x, 00)
#else
#include <unistd.h>
#define GF_FILEEXISTS(x) access(x, F_OK)
#endif
/*****************************************************************************/
/**
* The implementation of the Log class
*
*
*/
/*****************************************************************************/
namespace apache {
namespace geode {
namespace log {
namespace globals {
std::string* g_logFile = nullptr;
std::string* g_logFileWithExt = nullptr;
size_t g_bytesWritten = 0;
bool g_isLogFileOpened = false;
size_t g_fileSizeLimit = GEODE_MAX_LOG_FILE_LIMIT;
size_t g_diskSpaceLimit = GEODE_MAX_LOG_DISK_LIMIT;
char g_logFileNameBuffer[2048] = {0};
ACE_Thread_Mutex* g_logMutex = new ACE_Thread_Mutex("Log::logMutex");
int g_rollIndex = 0;
size_t g_spaceUsed = 0;
// Make a pair for the filename & its size
std::pair<std::string, int64_t> g_fileInfoPair;
// Vector to hold the fileInformation
typedef std::vector<std::pair<std::string, int64_t> > g_fileInfo;
FILE* g_log = nullptr;
ACE_utsname g_uname;
pid_t g_pid = 0;
} // namespace globals
} // namespace log
} // namespace geode
} // namespace apache
extern "C" {
static int selector(const dirent* d) {
std::string inputname(d->d_name);
std::string filebasename =
ACE::basename(apache::geode::log::globals::g_logFileWithExt->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(), "log") != 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 (strstr(filebasename.c_str(), buff1.c_str()) == nullptr) {
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;
}
}
static 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;
}
}
}
namespace apache {
namespace geode {
namespace client {
LogLevel Log::s_logLevel = LogLevel::Default;
using apache::geode::log::globals::g_bytesWritten;
using apache::geode::log::globals::g_diskSpaceLimit;
using apache::geode::log::globals::g_fileInfo;
using apache::geode::log::globals::g_fileInfoPair;
using apache::geode::log::globals::g_fileSizeLimit;
using apache::geode::log::globals::g_isLogFileOpened;
using apache::geode::log::globals::g_log;
using apache::geode::log::globals::g_logFile;
using apache::geode::log::globals::g_logFileNameBuffer;
using apache::geode::log::globals::g_logFileWithExt;
using apache::geode::log::globals::g_logMutex;
using apache::geode::log::globals::g_pid;
using apache::geode::log::globals::g_rollIndex;
using apache::geode::log::globals::g_spaceUsed;
using apache::geode::log::globals::g_uname;
/*****************************************************************************/
const char* Log::logFileName() {
ACE_Guard<ACE_Thread_Mutex> guard(*g_logMutex);
if (!g_logFile) {
g_logFileNameBuffer[0] = '\0';
} else {
if (g_logFile->size() >= sizeof g_logFileNameBuffer) {
throw IllegalStateException(
("Log file name is too long: " + *g_logFile).c_str());
}
ACE_OS::strncpy(g_logFileNameBuffer, g_logFile->c_str(),
sizeof(g_logFileNameBuffer));
}
return g_logFileNameBuffer;
}
void Log::init(LogLevel level, const char* logFileName, int32_t logFileLimit,
int64_t logDiskSpaceLimit) {
if (g_log != nullptr) {
throw IllegalStateException(
"The Log has already been initialized. "
"Call Log::close() before calling Log::init again.");
}
s_logLevel = level;
if (g_logMutex == nullptr) g_logMutex = new ACE_Thread_Mutex("Log::logMutex");
if (logDiskSpaceLimit <
0 /*|| logDiskSpaceLimit > GEODE_MAX_LOG_DISK_LIMIT*/) {
logDiskSpaceLimit = GEODE_MAX_LOG_DISK_LIMIT;
}
if (logFileLimit < 0 || logFileLimit > GEODE_MAX_LOG_FILE_LIMIT) {
logFileLimit = GEODE_MAX_LOG_FILE_LIMIT;
}
ACE_Guard<ACE_Thread_Mutex> guard(*g_logMutex);
if (logFileName && logFileName[0]) {
std::string filename = logFileName;
if (filename.size() >= sizeof g_logFileNameBuffer) {
throw IllegalStateException(
("Log file name is too long: " + filename).c_str());
}
if (g_logFile) {
*g_logFile = filename;
} else {
g_logFile = new std::string(filename);
}
#ifdef _WIN32
// replace all '\' with '/' to make everything easier..
size_t length = g_logFile->length() + 1;
char* slashtmp = new char[length];
ACE_OS::strncpy(slashtmp, g_logFile->c_str(), length);
for (size_t i = 0; i < g_logFile->length(); i++) {
if (slashtmp[i] == '/') {
slashtmp[i] = '\\';
}
}
*g_logFile = slashtmp;
delete[] slashtmp;
slashtmp = nullptr;
#endif
// Appending a ".log" at the end if it does not exist or file has some other
// extension.
std::string filebasename = ACE::basename(g_logFile->c_str());
int32_t len = static_cast<int32_t>(filebasename.length());
size_t fileExtPos = filebasename.find_last_of('.', len);
// if no extension then add .log extension
if (fileExtPos == std::string::npos) {
g_logFileWithExt = new std::string(*g_logFile + ".log");
} else {
std::string extName = filebasename.substr(fileExtPos + 1);
// if extension other than .log change it to ext + .log
if (extName != "log") {
g_logFileWithExt = new std::string(*g_logFile + ".log");
}
// .log Extension already provided, no need to append any extension.
else {
g_logFileWithExt = new std::string(*g_logFile);
}
}
g_fileSizeLimit = logFileLimit * 1024 * 1024;
g_diskSpaceLimit = logDiskSpaceLimit * 1024ll * 1024ll;
// If FileSizelimit is greater than DiskSpaceLimit & diskspaceLimit is set,
// then set DiskSpaceLimit to FileSizelimit
if (g_fileSizeLimit > g_diskSpaceLimit && g_diskSpaceLimit != 0) {
g_fileSizeLimit = g_diskSpaceLimit;
}
// 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 (g_fileSizeLimit == 0 && g_diskSpaceLimit != 0) {
g_fileSizeLimit = g_diskSpaceLimit;
}
g_bytesWritten = 0;
g_spaceUsed = 0;
g_rollIndex = 0;
std::string dirname = ACE::dirname(g_logFile->c_str());
ACE_Dirent_Selector sds;
int status = sds.open(dirname.c_str(), selector, comparator);
if (status != -1) {
for (int index = 0; index < sds.length(); ++index) {
std::string strname = ACE::basename(sds[index]->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());
g_rollIndex = ACE_OS::atoi(buff.c_str()) + 1;
}
} // if loop
} // for loop
}
sds.close();
FILE* existingFile = fopen(g_logFileWithExt->c_str(), "r");
if (existingFile != nullptr && logFileLimit > 0) {
/* adongre
* Coverity - II
* CID 29205: 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
*/
char rollFile[1024] = {0};
std::string logsdirname;
std::string logsbasename;
std::string fnameBeforeExt;
std::string extName;
std::string newfilestr;
int32_t len = static_cast<int32_t>(g_logFileWithExt->length());
int32_t lastPosOfSep = static_cast<int32_t>(
g_logFileWithExt->find_last_of(ACE_DIRECTORY_SEPARATOR_CHAR, len));
if (lastPosOfSep == -1) {
logsdirname = ".";
} else {
logsdirname = g_logFileWithExt->substr(0, lastPosOfSep);
}
logsbasename = g_logFileWithExt->substr(lastPosOfSep + 1, len);
char logFileExtAfter = '.';
int32_t baselen = static_cast<int32_t>(logsbasename.length());
int32_t posOfExt = static_cast<int32_t>(
logsbasename.find_last_of(logFileExtAfter, baselen));
if (posOfExt == -1) {
// throw IllegalArgument;
} else {
fnameBeforeExt = logsbasename.substr(0, posOfExt);
extName = logsbasename.substr(posOfExt + 1, baselen);
}
ACE_OS::snprintf(rollFile, 1024, "%s%c%s-%d.%s", logsdirname.c_str(),
ACE_DIRECTORY_SEPARATOR_CHAR, fnameBeforeExt.c_str(),
g_rollIndex++, extName.c_str());
bool rollFileNameGot = false;
while (!rollFileNameGot) {
FILE* checkFile = fopen(rollFile, "r");
if (checkFile != nullptr) {
fclose(checkFile);
checkFile = nullptr;
ACE_OS::snprintf(rollFile, 1024, "%s%c%s-%d.%s", logsdirname.c_str(),
ACE_DIRECTORY_SEPARATOR_CHAR, fnameBeforeExt.c_str(),
g_rollIndex++, extName.c_str());
} else {
rollFileNameGot = true;
}
/* adongre
* CID 28999: Use after free (USE_AFTER_FREE)
*/
if (checkFile != nullptr) fclose(existingFile);
}
// retry some number of times before giving up when file is busy etc.
int renameResult = -1;
int maxTries = 10;
while (maxTries-- > 0) {
renameResult = ACE_OS::rename(g_logFileWithExt->c_str(), rollFile);
if (renameResult >= 0) {
break;
}
// continue after some sleep
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
/* (don't throw exception; try appending to existing file instead)
if (renameResult < 0) {
std::string msg = "Could not rename: " +
*g_logFileWithExt + " to: " + rollFile;
throw GeodeIOException(msg.c_str());
}
*/
}
if (existingFile != nullptr) {
fclose(existingFile);
existingFile = nullptr;
}
} else if (g_logFile) {
delete g_logFile;
g_logFile = nullptr;
g_logFileWithExt = nullptr;
}
writeBanner();
}
void Log::close() {
ACE_Guard<ACE_Thread_Mutex> guard(*g_logMutex);
std::string oldfile;
if (g_logFile) {
oldfile = *g_logFile;
delete g_logFile;
g_logFile = nullptr;
}
if (g_logFileWithExt) {
delete g_logFileWithExt;
g_logFileWithExt = nullptr;
}
if (g_log) {
fclose(g_log);
g_log = nullptr;
}
}
void Log::writeBanner() {
if (g_logFileWithExt == nullptr) {
return;
}
const char* dirname = ACE::dirname(g_logFileWithExt->c_str());
if (GF_FILEEXISTS(dirname) != 0 && ACE_OS::mkdir(dirname) != 0) {
std::string msg =
"Error in creating directories for: " + std::string(dirname);
throw GeodeIOException(msg.c_str());
}
// retry some number of times before giving up when file is busy etc.
int maxTries = 10;
while (maxTries-- > 0) {
g_log = fopen(g_logFileWithExt->c_str(), "a");
if (g_log != nullptr) {
break;
}
int lastError = ACE_OS::last_error();
if (lastError != EACCES && lastError != EINTR && lastError != EWOULDBLOCK) {
break;
}
// continue after some sleep
std::this_thread::sleep_for(std::chrono::milliseconds(200));
}
if (!g_log) {
g_isLogFileOpened = false;
return;
} else {
g_isLogFileOpened = true;
}
if (s_logLevel == LogLevel::None) {
return;
}
std::string bannertext = geodeBanner::getBanner();
if (g_logFile == nullptr) {
fprintf(stdout, "%s", bannertext.c_str());
fflush(stdout);
return;
} // else
GF_D_ASSERT(g_logFile && g_logMutex && g_logFileWithExt);
if (fprintf(g_log, "%s", bannertext.c_str()) == 0 || ferror(g_log)) {
// we should be continue,
return;
}
int numchars = 0;
const char* pch = nullptr;
pch = strchr(bannertext.c_str(), '\n');
while (pch != nullptr) {
pch = strchr(pch + 1, '\n');
numchars += 2;
}
g_bytesWritten += static_cast<int32_t>(bannertext.length() + numchars);
fflush(g_log);
}
const char* Log::levelToChars(LogLevel level) {
switch (level) {
case LogLevel::None:
return "none";
case LogLevel::Error:
return "error";
case LogLevel::Warning:
return "warning";
case LogLevel::Info:
return "info";
case LogLevel::Default:
return "default";
case LogLevel::Config:
return "config";
case LogLevel::Fine:
return "fine";
case LogLevel::Finer:
return "finer";
case LogLevel::Finest:
return "finest";
case LogLevel::Debug:
return "debug";
case LogLevel::All:
return "all";
default: {
char buf[64] = {0};
ACE_OS::snprintf(buf, 64, "Unexpected log level: %d",
static_cast<int>(level));
throw IllegalArgumentException(buf);
}
}
}
LogLevel Log::charsToLevel(const std::string& chars) {
std::string level = chars;
if (level.empty()) return LogLevel::None;
std::transform(level.begin(), level.end(), level.begin(), ::tolower);
if (level == "none") {
return LogLevel::None;
} else if (level == "error") {
return LogLevel::Error;
} else if (level == "warning") {
return LogLevel::Warning;
} else if (level == "info") {
return LogLevel::Info;
} else if (level == "default") {
return LogLevel::Default;
} else if (level == "config") {
return LogLevel::Config;
} else if (level == "fine") {
return LogLevel::Fine;
} else if (level == "finer") {
return LogLevel::Finer;
} else if (level == "finest") {
return LogLevel::Finest;
} else if (level == "debug") {
return LogLevel::Debug;
} else if (level == "all") {
return LogLevel::All;
} else {
throw IllegalArgumentException(("Unexpected log level: " + level).c_str());
}
}
char* Log::formatLogLine(char* buf, LogLevel level) {
if (g_pid == 0) {
g_pid = ACE_OS::getpid();
ACE_OS::uname(&g_uname);
}
const size_t MINBUFSIZE = 128;
ACE_Time_Value clock = ACE_OS::gettimeofday();
time_t secs = clock.sec();
struct tm* tm_val = ACE_OS::localtime(&secs);
char* pbuf = buf;
pbuf += ACE_OS::snprintf(pbuf, 15, "[%s ", Log::levelToChars(level));
pbuf += ACE_OS::strftime(pbuf, MINBUFSIZE, "%Y/%m/%d %H:%M:%S", tm_val);
pbuf += ACE_OS::snprintf(pbuf, 15, ".%06" PRId64 " ",
static_cast<int64_t>(clock.usec()));
pbuf += ACE_OS::strftime(pbuf, MINBUFSIZE, "%Z ", tm_val);
ACE_OS::snprintf(pbuf, 300, "%s:%d %" PRIu64 "] ", g_uname.nodename, g_pid,
hacks::aceThreadId(ACE_OS::thr_self()));
return buf;
}
void Log::put(LogLevel level, const std::string& msg) {
put(level, msg.c_str());
}
// int g_count = 0;
void Log::put(LogLevel level, const char* msg) {
ACE_Guard<ACE_Thread_Mutex> guard(*g_logMutex);
g_fileInfo fileInfo;
char buf[256] = {0};
char fullpath[512] = {0};
if (!g_logFile) {
fprintf(stdout, "%s%s\n", formatLogLine(buf, level), msg);
fflush(stdout);
// TODO: ignoring for now; probably store the log-lines for possible
// future logging if log-file gets initialized properly
} else {
if (!g_isLogFileOpened) {
g_log = fopen(g_logFileWithExt->c_str(), "a");
if (!g_log) {
g_isLogFileOpened = false;
return;
}
g_isLogFileOpened = true;
} else if (!g_log) {
g_log = fopen(g_logFileWithExt->c_str(), "a");
if (!g_log) {
return;
}
}
formatLogLine(buf, level);
size_t numChars =
static_cast<int>(ACE_OS::strlen(buf) + ACE_OS::strlen(msg));
g_bytesWritten +=
numChars + 2; // bcoz we have to count trailing new line (\n)
if ((g_fileSizeLimit != 0) && (g_bytesWritten >= g_fileSizeLimit)) {
char rollFile[1024] = {0};
std::string logsdirname;
std::string logsbasename;
std::string fnameBeforeExt;
std::string extName;
std::string newfilestr;
int32_t len = static_cast<int32_t>(g_logFileWithExt->length());
int32_t lastPosOfSep = static_cast<int32_t>(
g_logFileWithExt->find_last_of(ACE_DIRECTORY_SEPARATOR_CHAR, len));
if (lastPosOfSep == -1) {
logsdirname = ".";
} else {
logsdirname = g_logFileWithExt->substr(0, lastPosOfSep);
}
logsbasename = g_logFileWithExt->substr(lastPosOfSep + 1, len);
char logFileExtAfter = '.';
int32_t baselen = static_cast<int32_t>(logsbasename.length());
int32_t posOfExt = static_cast<int32_t>(
logsbasename.find_last_of(logFileExtAfter, baselen));
if (posOfExt == -1) {
// throw IllegalArgument;
} else {
fnameBeforeExt = logsbasename.substr(0, posOfExt);
extName = logsbasename.substr(posOfExt + 1, baselen);
}
ACE_OS::snprintf(rollFile, 1024, "%s%c%s-%d.%s", logsdirname.c_str(),
ACE_DIRECTORY_SEPARATOR_CHAR, fnameBeforeExt.c_str(),
g_rollIndex++, extName.c_str());
bool rollFileNameGot = false;
while (!rollFileNameGot) {
FILE* fp1 = fopen(rollFile, "r");
if (fp1 != nullptr) {
fclose(fp1);
ACE_OS::snprintf(rollFile, 1024, "%s%c%s-%d.%s", logsdirname.c_str(),
ACE_DIRECTORY_SEPARATOR_CHAR, fnameBeforeExt.c_str(),
g_rollIndex++, extName.c_str());
} else {
rollFileNameGot = true;
}
}
fclose(g_log);
g_log = nullptr;
if (ACE_OS::rename(g_logFileWithExt->c_str(), rollFile) < 0) {
return; // no need to throw exception try next time
}
g_bytesWritten =
numChars + 2; // bcoz we have to count trailing new line (\n)
writeBanner();
}
g_spaceUsed += g_bytesWritten;
if ((g_diskSpaceLimit > 0) && (g_spaceUsed >= g_diskSpaceLimit)) {
std::string dirname = ACE::dirname(g_logFile->c_str());
g_spaceUsed = 0;
ACE_stat statBuf = {};
ACE_Dirent_Selector sds;
int status = sds.open(dirname.c_str(), selector, comparator);
if (status != -1) {
for (int index = 1; index < sds.length(); ++index) {
ACE_OS::snprintf(fullpath, 512, "%s%c%s", dirname.c_str(),
ACE_DIRECTORY_SEPARATOR_CHAR, sds[index]->d_name);
ACE_OS::stat(fullpath, &statBuf);
g_fileInfoPair = std::make_pair(fullpath, statBuf.st_size);
fileInfo.push_back(g_fileInfoPair);
g_spaceUsed += fileInfo[index - 1].second;
} // for loop
g_spaceUsed += g_bytesWritten;
sds.close();
}
int fileIndex = 0;
while ((g_spaceUsed > (g_diskSpaceLimit /*- g_fileSizeLimit*/))) {
int64_t fileSize = fileInfo[fileIndex].second;
if (ACE_OS::unlink(fileInfo[fileIndex].first.c_str()) == 0) {
g_spaceUsed -= fileSize;
} else {
char printmsg[256];
ACE_OS::snprintf(printmsg, 256, "%s\t%s\n", "Could not delete",
fileInfo[fileIndex].first.c_str());
int numChars =
fprintf(g_log, "%s%s\n", formatLogLine(buf, level), printmsg);
g_bytesWritten +=
numChars + 2; // bcoz we have to count trailing new line (\n)
}
fileIndex++;
}
}
if ((numChars = fprintf(g_log, "%s%s\n", buf, msg)) == 0 || ferror(g_log)) {
if ((g_diskSpaceLimit > 0)) {
g_spaceUsed = g_spaceUsed - (numChars + 2);
}
if (g_fileSizeLimit > 0) {
g_bytesWritten = g_bytesWritten - (numChars + 2);
}
// lets continue wothout throwing the exception; it should not cause
// process to terminate
fclose(g_log);
g_log = nullptr;
} else {
fflush(g_log);
}
}
}
void Log::putThrow(LogLevel level, const char* msg, const Exception& ex) {
std::string message = "Geode exception " + ex.getName() +
" thrown: " + ex.getMessage() + "\n" + msg;
put(level, message);
}
void Log::putCatch(LogLevel level, const char* msg, const Exception& ex) {
std::string message = "Geode exception " + ex.getName() +
" caught: " + ex.getMessage() + "\n" + msg;
put(level, message);
}
void Log::enterFn(LogLevel level, const char* functionName) {
enum { MAX_NAME_LENGTH = 1024 };
std::string fn = functionName;
if (fn.size() > MAX_NAME_LENGTH) {
fn = fn.substr(fn.size() - MAX_NAME_LENGTH, MAX_NAME_LENGTH);
}
char buf[MAX_NAME_LENGTH + 512] = {0};
ACE_OS::snprintf(buf, 1536, "{{{===>>> Entering function %s", fn.c_str());
put(level, buf);
}
void Log::exitFn(LogLevel level, const char* functionName) {
enum { MAX_NAME_LENGTH = 1024 };
std::string fn = functionName;
if (fn.size() > MAX_NAME_LENGTH) {
fn = fn.substr(fn.size() - MAX_NAME_LENGTH, MAX_NAME_LENGTH);
}
char buf[MAX_NAME_LENGTH + 512] = {0};
ACE_OS::snprintf(buf, 1536, "<<<===}}} Exiting function %s", fn.c_str());
put(level, buf);
}
// var arg logging routines.
#ifdef _WIN32
#define vsnprintf _vsnprintf
#endif
void LogVarargs::debug(const char* fmt, ...) {
char msg[_GF_MSG_LIMIT] = {0};
va_list argp;
va_start(argp, fmt);
vsnprintf(msg, _GF_MSG_LIMIT, fmt, argp);
/* win doesn't guarantee termination */ msg[_GF_MSG_LIMIT - 1] = '\0';
Log::put(LogLevel::Debug, msg);
va_end(argp);
}
void LogVarargs::error(const char* fmt, ...) {
char msg[_GF_MSG_LIMIT] = {0};
va_list argp;
va_start(argp, fmt);
vsnprintf(msg, _GF_MSG_LIMIT, fmt, argp);
/* win doesn't guarantee termination */ msg[_GF_MSG_LIMIT - 1] = '\0';
Log::put(LogLevel::Error, msg);
va_end(argp);
}
void LogVarargs::warn(const char* fmt, ...) {
char msg[_GF_MSG_LIMIT] = {0};
va_list argp;
va_start(argp, fmt);
vsnprintf(msg, _GF_MSG_LIMIT, fmt, argp);
/* win doesn't guarantee termination */ msg[_GF_MSG_LIMIT - 1] = '\0';
Log::put(LogLevel::Warning, msg);
va_end(argp);
}
void LogVarargs::info(const char* fmt, ...) {
char msg[_GF_MSG_LIMIT] = {0};
va_list argp;
va_start(argp, fmt);
vsnprintf(msg, _GF_MSG_LIMIT, fmt, argp);
/* win doesn't guarantee termination */ msg[_GF_MSG_LIMIT - 1] = '\0';
Log::put(LogLevel::Info, msg);
va_end(argp);
}
void LogVarargs::config(const char* fmt, ...) {
char msg[_GF_MSG_LIMIT] = {0};
va_list argp;
va_start(argp, fmt);
vsnprintf(msg, _GF_MSG_LIMIT, fmt, argp);
/* win doesn't guarantee termination */ msg[_GF_MSG_LIMIT - 1] = '\0';
Log::put(LogLevel::Config, msg);
va_end(argp);
}
void LogVarargs::fine(const char* fmt, ...) {
char msg[_GF_MSG_LIMIT] = {0};
va_list argp;
va_start(argp, fmt);
vsnprintf(msg, _GF_MSG_LIMIT, fmt, argp);
/* win doesn't guarantee termination */ msg[_GF_MSG_LIMIT - 1] = '\0';
Log::put(LogLevel::Fine, msg);
va_end(argp);
}
void LogVarargs::finer(const char* fmt, ...) {
char msg[_GF_MSG_LIMIT] = {0};
va_list argp;
va_start(argp, fmt);
vsnprintf(msg, _GF_MSG_LIMIT, fmt, argp);
/* win doesn't guarantee termination */ msg[_GF_MSG_LIMIT - 1] = '\0';
Log::put(LogLevel::Finer, msg);
va_end(argp);
}
void LogVarargs::finest(const char* fmt, ...) {
char msg[_GF_MSG_LIMIT] = {0};
va_list argp;
va_start(argp, fmt);
vsnprintf(msg, _GF_MSG_LIMIT, fmt, argp);
/* win doesn't guarantee termination */ msg[_GF_MSG_LIMIT - 1] = '\0';
Log::put(LogLevel::Finest, msg);
va_end(argp);
}
} // namespace client
} // namespace geode
} // namespace apache