This source file includes following definitions.
- WriteMessage
- Log
- Add
- AddStr
- AddNum
- printf
#include <config.h>
#include "internal_logging.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <gperftools/malloc_extension.h>
#include "base/logging.h"
#include "base/spinlock.h"
static const int kLogBufSize = 800;
static SpinLock crash_lock(base::LINKER_INITIALIZED);
static bool crashed = false;
static const int kStatsBufferSize = 16 << 10;
static char stats_buffer[kStatsBufferSize] = { 0 };
namespace tcmalloc {
static void WriteMessage(const char* msg, int length) {
write(STDERR_FILENO, msg, length);
}
void (*log_message_writer)(const char* msg, int length) = WriteMessage;
class Logger {
public:
bool Add(const LogItem& item);
bool AddStr(const char* str, int n);
bool AddNum(uint64_t num, int base);
static const int kBufSize = 200;
char* p_;
char* end_;
char buf_[kBufSize];
};
void Log(LogMode mode, const char* filename, int line,
LogItem a, LogItem b, LogItem c, LogItem d) {
Logger state;
state.p_ = state.buf_;
state.end_ = state.buf_ + sizeof(state.buf_);
state.AddStr(filename, strlen(filename))
&& state.AddStr(":", 1)
&& state.AddNum(line, 10)
&& state.AddStr("]", 1)
&& state.Add(a)
&& state.Add(b)
&& state.Add(c)
&& state.Add(d);
if (state.p_ >= state.end_) {
state.p_ = state.end_ - 1;
}
*state.p_ = '\n';
state.p_++;
int msglen = state.p_ - state.buf_;
if (mode == kLog) {
(*log_message_writer)(state.buf_, msglen);
return;
}
bool first_crash = false;
{
SpinLockHolder l(&crash_lock);
if (!crashed) {
crashed = true;
first_crash = true;
}
}
(*log_message_writer)(state.buf_, msglen);
if (first_crash && mode == kCrashWithStats) {
MallocExtension::instance()->GetStats(stats_buffer, kStatsBufferSize);
(*log_message_writer)(stats_buffer, strlen(stats_buffer));
}
abort();
}
bool Logger::Add(const LogItem& item) {
if (p_ < end_) {
*p_ = ' ';
p_++;
}
switch (item.tag_) {
case LogItem::kStr:
return AddStr(item.u_.str, strlen(item.u_.str));
case LogItem::kUnsigned:
return AddNum(item.u_.unum, 10);
case LogItem::kSigned:
if (item.u_.snum < 0) {
return AddStr("-", 1)
&& AddNum(- static_cast<uint64_t>(item.u_.snum), 10);
} else {
return AddNum(static_cast<uint64_t>(item.u_.snum), 10);
}
case LogItem::kPtr:
return AddStr("0x", 2)
&& AddNum(reinterpret_cast<uintptr_t>(item.u_.ptr), 16);
default:
return false;
}
}
bool Logger::AddStr(const char* str, int n) {
if (end_ - p_ < n) {
return false;
} else {
memcpy(p_, str, n);
p_ += n;
return true;
}
}
bool Logger::AddNum(uint64_t num, int base) {
static const char kDigits[] = "0123456789abcdef";
char space[22];
char* end = space + sizeof(space);
char* pos = end;
do {
pos--;
*pos = kDigits[num % base];
num /= base;
} while (num > 0 && pos > space);
return AddStr(pos, end - pos);
}
}
void TCMalloc_Printer::printf(const char* format, ...) {
if (left_ > 0) {
va_list ap;
va_start(ap, format);
const int r = perftools_vsnprintf(buf_, left_, format, ap);
va_end(ap);
if (r < 0) {
left_ = 0;
} else if (r > left_) {
left_ = 0;
} else {
left_ -= r;
buf_ += r;
}
}
}