#pragma once
#include <boost/noncopyable.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/thread.hpp>
#include <boost/thread/mutex.hpp> class CountDownLatch : boost::noncopyable
{
public: explicit CountDownLatch(int count); void wait(); void countDown(); int getCount(); private:
boost::mutex m_Mutex;
boost::condition_variable m_ConditionVar;
int count_;
};
#include "stdafx.h"
#include "CountDownLatch.h" CountDownLatch::CountDownLatch(int count)
: count_(count)
{
} void CountDownLatch::wait()
{
boost::mutex::scoped_lock lock(m_Mutex);
while (count_ > 0) {
m_ConditionVar.wait(lock);
}
} void CountDownLatch::countDown()
{
boost::mutex::scoped_lock lock(m_Mutex);
--count_;
if (count_ == 0) {
m_ConditionVar.notify_all();
}
} int CountDownLatch::getCount()
{
boost::mutex::scoped_lock lock(m_Mutex);
return count_;
}
#pragma once
#include <string>
#include <boost/noncopyable.hpp>
using namespace std;
const int kSmallBuffer = 4000;
const int kLargeBuffer = 4000*1000; template<int SIZE>
class FixedBuffer : boost::noncopyable
{
public:
FixedBuffer()
: cur_(data_)
{
setCookie(cookieStart);
} ~FixedBuffer()
{
setCookie(cookieEnd);
} void append(const char* buf, size_t len)
{
if (static_cast<size_t>(avail()) > len)
{
memcpy(cur_, buf, len);
cur_ += len;
}
} const char* data() const { return data_; }
int length() const { return static_cast<int>(cur_ - data_); } // write to data_ directly
char* current() { return cur_; }
int avail() const { return static_cast<int>(end() - cur_); }
void add(size_t len) { cur_ += len; } void reset() { cur_ = data_; }
void bzero() { memset(data_, 0, sizeof(data_)); }
void setCookie(void (*cookie)()) { cookie_ = cookie; }
string asString() const { return string(data_, length()); } private:
const char* end() const { return data_ + sizeof data_; }
// Must be outline function for cookies.
static void cookieStart();
static void cookieEnd(); void (*cookie_)();
char data_[SIZE];
char* cur_;
};
#pragma once
#include <boost/date_time/posix_time/posix_time.hpp>
#include "boost/date_time/gregorian/gregorian.hpp"
#include "boost/atomic/atomic.hpp"
#include <queue>
#include <string>
#include <boost/bind.hpp>
#include <boost/noncopyable.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/thread.hpp>
#include <boost/thread/mutex.hpp>
#include "FixedBuffer.h"
#include "CountDownLatch.h" enum LoggingEnum{
LOG_INFO,
LOG_DBBUG,
LOG_ERROR,
LOG_WARNNING,
LOG_END
}; enum GLogColor {
COLOR_DEFAULT,
COLOR_RED,
COLOR_GREEN,
COLOR_YELLOW
}; class Logging
{
public:
Logging();
~Logging();
void WriteWithFunLine(LoggingEnum eLoggingEnum, char* fun, int line, char* msg, ...);
void WriteMsg(LoggingEnum eLoggingEnum, char* fun, int line, char* msg); private:
int CreateLogFile(LoggingEnum aLoggingEnum);
void Write(LoggingEnum eLoggingEnum, char* msg, int msgLen);
void threadFunc();
private:
bool running_;
FILE* m_File[LOG_END];
typedef boost::posix_time::ptime PTIME;
std::string m_AppPreStr;
typedef FixedBuffer<kLargeBuffer> Buffer;
typedef boost::ptr_vector<Buffer> BufferVector;
typedef BufferVector::auto_type BufferPtr;
BufferPtr currentBuffer_;
BufferPtr nextBuffer_;
BufferVector buffers_;
boost::thread m_Thread;
boost::mutex m_Mutex;
boost::condition_variable m_ConditionVar;
CountDownLatch latch_;
};
#include "Logging.h"
#include <iomanip>
#include <sstream>
#include <fcntl.h>
#include <io.h>
#include <Windows.h>
#include "SSActive.h" Logging g_Logging;
string LOGPreStr[LOG_END] = {"LOG_INFO", "LOG_DBBUG", "LOG_ERROR", "LOG_WARNNING"}; #ifdef _WINDOWS
// Returns the character attribute for the given color.
WORD GetColorAttribute(GLogColor color) {
switch (color) {
case COLOR_RED: return FOREGROUND_RED;
case COLOR_GREEN: return FOREGROUND_GREEN;
case COLOR_YELLOW: return FOREGROUND_RED | FOREGROUND_GREEN;
default: return 0;
}
}
#else
// Returns the ANSI color code for the given color.
const char* GetAnsiColorCode(GLogColor color) {
switch (color) {
case COLOR_RED: return "1";
case COLOR_GREEN: return "2";
case COLOR_YELLOW: return "3";
case COLOR_DEFAULT: return "";
};
return NULL; // stop warning about return type.
} #endif // OS_WINDOWS GLogColor GLogColorVec[LOG_END] = {COLOR_GREEN, COLOR_DEFAULT, COLOR_RED, COLOR_YELLOW}; Logging::Logging():latch_(1){
currentBuffer_.reset(new Buffer);
currentBuffer_->bzero(); nextBuffer_.reset(new Buffer);
nextBuffer_->bzero(); buffers_.reserve(16); boost::mutex::scoped_lock lock(m_Mutex);
char szAppPath[256] = "";
::GetModuleFileNameA(0, szAppPath, 256);
m_AppPreStr = szAppPath;
m_AppPreStr = m_AppPreStr.substr(m_AppPreStr.rfind("\\") + 1);
m_AppPreStr = m_AppPreStr.substr(0, m_AppPreStr.size()-4); int n32Res = 0;
for (int i = LOG_INFO; i < LOG_END; ++i){
m_File[i] = NULL;
} n32Res = CreateLogFile(LOG_INFO);
if (n32Res != 0){
printf("Createfile(i) failed", 0);
} lock.unlock(); running_ = true;
m_Thread = boost::thread(&Logging::threadFunc, this);
latch_.wait();
} void Logging::WriteWithFunLine(LoggingEnum eLoggingEnum, char* fun, int line, char* msg, ...){
if (eLoggingEnum < LOG_INFO || eLoggingEnum > LOG_WARNNING){
eLoggingEnum = eLoggingEnum;
} char tmp[1024] = {0};
PTIME nowTime = boost::posix_time::microsec_clock::local_time();
sprintf(tmp, "%s.%d %s:%d ", boost::posix_time::to_iso_string(nowTime).c_str(), boost::this_thread::get_id(), fun, line);
int curPos = strlen(tmp); va_list pArg = NULL;
va_start(pArg, msg);
vsprintf(tmp+curPos, msg, pArg);
va_end(pArg); curPos = strlen(tmp);
char end[] = "\n";
sprintf(tmp + curPos, "%s", end); int totlen = curPos + 1;
boost::mutex::scoped_lock lock(m_Mutex);
if (currentBuffer_->avail() > totlen)
{
currentBuffer_->append(tmp, totlen);
}
else
{
buffers_.push_back(currentBuffer_.release()); if (nextBuffer_)
{
currentBuffer_ = boost::ptr_container::move(nextBuffer_);
}
else
{
currentBuffer_.reset(new Buffer); // Rarely happens
}
currentBuffer_->append(tmp, totlen);
m_ConditionVar.notify_all();
}
} Logging::~Logging(){
running_ = false;
m_ConditionVar.notify_all();
m_Thread.join(); for (INT32 i = 0; i < 4; ++i){
if (NULL != m_File[i]){
fclose(m_File[i]);
}
}
} int Logging::CreateLogFile(LoggingEnum aLoggingEnum){
string strPre;
switch (aLoggingEnum){
case LOG_DBBUG:
strPre = "DBBUG";
break;
case LOG_INFO:
strPre = "INFO";
break;
case LOG_WARNNING:
strPre = "WARNNING";
break;
case LOG_ERROR:
strPre = "ERROR";
break;
}
char str[128];
sprintf(str, "./Log/%s-%s-%d-%s", m_AppPreStr.c_str(), strPre.c_str() ,boost::this_thread::get_id(), boost::posix_time::to_iso_string(boost::posix_time::microsec_clock::local_time()).c_str());
string fileName(str);
fileName += ".log";
int fd = open(fileName.c_str(), O_WRONLY | O_CREAT | O_EXCL, 0664);
if (fd == -1){
printf("%s create(%d) file error\n", __FUNCTION__, aLoggingEnum);
return -1;
} m_File[aLoggingEnum] = fdopen(fd, "a");
if (NULL == m_File[aLoggingEnum]){
printf("%s open file(%d) failed\n", __FUNCTION__, aLoggingEnum);
return -1;
} return 0;
} void Logging::threadFunc()
{
assert(running_ == true);
latch_.countDown();
BufferPtr newBuffer1(new Buffer);
BufferPtr newBuffer2(new Buffer);
newBuffer1->bzero();
newBuffer2->bzero();
BufferVector buffersToWrite;
buffersToWrite.reserve(16); while (running_)
{
assert(newBuffer1 && newBuffer1->length() == 0);
assert(newBuffer2 && newBuffer2->length() == 0);
assert(buffersToWrite.empty()); {
boost::mutex::scoped_lock lock(m_Mutex);
if (buffers_.empty()) // unusual usage!
{
m_ConditionVar.wait(lock);
} buffers_.push_back(currentBuffer_.release());
currentBuffer_ = boost::ptr_container::move(newBuffer1);
buffersToWrite.swap(buffers_);
if (!nextBuffer_)
{
nextBuffer_ = boost::ptr_container::move(newBuffer2);
}
} assert(!buffersToWrite.empty()); if (buffersToWrite.size() > 25)
{
buffersToWrite.erase(buffersToWrite.begin()+2, buffersToWrite.end());
} for (size_t i = 0; i < buffersToWrite.size(); ++i)
{
fwrite(buffersToWrite[i].data(), buffersToWrite[i].length(), 1, stderr);
fflush(stderr); fwrite(buffersToWrite[i].data(), 1, buffersToWrite[i].length(), m_File[0]);
fflush(m_File[0]);
} if (buffersToWrite.size() > 2)
{
// drop non-bzero-ed buffers, avoid trashing
buffersToWrite.resize(2);
} if (!newBuffer1)
{
assert(!buffersToWrite.empty());
newBuffer1 = buffersToWrite.pop_back();
newBuffer1->reset();
} if (!newBuffer2)
{
assert(!buffersToWrite.empty());
newBuffer2 = buffersToWrite.pop_back();
newBuffer2->reset();
} buffersToWrite.clear();
}
}

临时还没想清楚,假设写多个日志等级,logging的锁 应该怎样加。

參考mudo logging写的win下logging的更多相关文章

  1. win下写任务提交给集群

    一,复制和删除hdfs中的文件 import org.apache.hadoop.fs.{FileSystem, Path} import org.apache.spark.{SparkConf, S ...

  2. WPS2012交叉引用技巧,word比wps这点强更新參考文献

                WPS2012交叉引用技巧,word比wps这点强更新參考文献 到时生成仅仅有有一条线,好像WPS不能够,word能够,假设谁知道能够补充.^_^ 1.写论文,參考文献的改动非 ...

  3. ANTLR4权威參考手冊(一)

    写在前面的话: 此文档是对伟大的Terence Parr的著作<the definitive antlr4 reference>的翻译本.致敬!欢迎转载,请注明原地址,请尊重劳动成果.翻译 ...

  4. SQLIO 磁盘測试工具參考

    SQLIO 下载地址:id=20163">SQLIO Disk Subsystem Benchmark Tool 默认文件夹:C:\Program Files\SQLIO 以命令行执行 ...

  5. 计算机网络11--OSI參考模型

    本页内容 1.OSI參考模型简单介绍 2.OSI參考模型通信过程 3.OSI參考模型的数据封装 4.数据封装的意义 5.物理层 6.数据链路层 7.网络层 8.传输层 9.会话层 10.表示层 11. ...

  6. Unity开发规范(个人习惯,仅供參考)

    近期整理了一下unity里的文件夹使用和脚本上的一些规范,这个看个人习惯,仅供參考 1.unity中的Project文件夹      总体文件夹大致例如以下:            按资源种类分目录. ...

  7. [Java] 实验6參考代码

    1. 大家的.java程序都须要在一个"缺省包"(default package)下编写\执行\提交,不要去命名新的package     - 系统不支持package contr ...

  8. 基于TI Davinci架构的多核/双核开发高速扫盲(以OMAP L138为例),dm8168多核开发參考以及达芬奇系列资料user guide整理

    基于TI Davinci架构的双核嵌入式应用处理器OMAPL138开发入门 原文转自http://blog.csdn.net/wangpengqi/article/details/8115614 感谢 ...

  9. Win下最爱效率利器:AutoHotKey

    AutoHotkey是一个windows下的开源.免费.自动化软件工具.它由最初旨在提供键盘快捷键的脚本语言驱动(称为:热键),随着时间的推移演变成一个完整的脚本语言.但你不需要把它想得太深,你只需要 ...

随机推荐

  1. angularjs 指令2

    <!DOCTYPE HTML> <html ng-app="myApp"> <head> <meta http-equiv="C ...

  2. bzoj1934: [Shoi2007]Vote 善意的投票(显然最小割)

    1934: [Shoi2007]Vote 善意的投票 题目:传送门 题解: 明显的不能再明显的最小割... st连同意的,不同意的连ed 朋友之间两两连边(即双向边) 流量都为1... 为啥: 一个人 ...

  3. 使用iOS原生sqlite3框架对sqlite数据库进行操作

    摘要: iOS中sqlite3框架可以很好的对sqlite数据库进行支持,通过面向对象的封装,可以更易于开发者使用. 使用iOS原生sqlite3框架对sqlite数据库进行操作 一.引言 sqlit ...

  4. java9新特性-21-java的动态编译器

    1. 官方Feature 243: Java-Level JVM Compiler Interface 295: Ahead-of-Time Compilation 2. 产生背景 Oracle 一直 ...

  5. iOS——扬声器与听筒的切换

    1.扬声器模式:  NSError *error; [[AVAudioSession sharedInstance] overrideOutputAudioPort:AVAudioSessionPor ...

  6. ES6学习笔记(十二)异步解决方案Promise

    1.Promise 的含义 Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大.它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了P ...

  7. notepad++调用python3中文乱码

    使用notepad++,配置好快捷键调用python3,一切就绪,仿佛就差代码了,结果一使用, 中文乱码,一直没有好的解决办法. 最后只能在代码中增加一行重写向输出解决,示例如下: #!/usr/bi ...

  8. 解决zabbix容器中文无法选择的问题

    1.查看zabbiz-web运行的容器 2.进入容器 3.安装语言包(针对centos7) yum install -y kde-l10n-chinese 4.更新gitbc包(因为镜像阉割了该包的部 ...

  9. Lenovo k860i 移植Android 4.4 cm11进度记录【下篇--实时更新中】

    2014.8.24 k860i的cm11的移植在中断了近两三个月之后又开始继续了,进度记录的日志上一篇已经没什么写的了,就完结掉它吧,重新开一篇日志做下篇好了.最近的战况是,在scue同学的努力之下, ...

  10. 百度地图API的使用示例

    刚刚工作的时候写过百度地图API文档,那时候没有记录到技术博客里面,今天在群里看见有个姑娘在问这个问题,重温了一遍,这个API还算好用.百度地图API,集成简单好用,全面,兼容问题,文档全面: 官方文 ...