muduo异步日志

muduo异步日志实现

陈硕老师的muduo网络库的异步日志的实现,今晚有点晚了,我明晚再把这个异步日志抽出来,作为一个独立的日志库。

所在文件

  • AsyncLogging.cc

  • AsyncLogging.h

  • LogFile.h

  • LogFile.cc

  • CountDownLatch.h

  • CountDownLatch.cc

    这个CountDownLatch有点像信号量,但是又只有down操作,上网查了以下类似的,作用有点像屏障

class AsyncLogging : noncopyable
{public:AsyncLogging(const string& basename,off_t rollSize,int flushInterval = 3);~AsyncLogging(){if (running_){stop();}}void append(const char* logline, int len);void start(){running_ = true;thread_.start();	// 启动线程latch_.wait();		// 这里的wait调用其实并不会阻塞// 主线程}void stop() NO_THREAD_SAFETY_ANALYSIS{running_ = false;cond_.notify();thread_.join();}private:// 默认的守护进程执行的函数void threadFunc();/*Buffer的数据结构private:std::vector<char> buffer_;size_t readerIndex_;size_t writerIndex_;static const char kCRLF[];*/typedef muduo::detail::FixedBuffer<muduo::detail::kLargeBuffer> Buffer;typedef std::vector<std::unique_ptr<Buffer>> BufferVector;typedef BufferVector::value_type BufferPtr;	// 表示容器元素的类型const int flushInterval_;						// 刷盘的时间间隔std::atomic<bool> running_;					// 是否运行const string basename_;						// 文件名const off_t rollSize_;						// 日志回滚的大小muduo::Thread thread_;						// 日志类自带一个守护线程来写muduo::CountDownLatch latch_;					muduo::MutexLock mutex_;muduo::Condition cond_ GUARDED_BY(mutex_);BufferPtr currentBuffer_ GUARDED_BY(mutex_);	// 当前缓冲BufferPtr nextBuffer_ GUARDED_BY(mutex_);		// 预备缓冲BufferVector buffers_ GUARDED_BY(mutex_);		// 已经写满并等待落盘的缓冲
};
#include <stdio.h>using namespace muduo;AsyncLogging::AsyncLogging(const string& basename,off_t rollSize,int flushInterval): flushInterval_(flushInterval),running_(false),basename_(basename),rollSize_(rollSize),thread_(std::bind(&AsyncLogging::threadFunc, this), "Logging"),latch_(1),mutex_(),cond_(mutex_),currentBuffer_(new Buffer),nextBuffer_(new Buffer),buffers_()
{currentBuffer_->bzero();nextBuffer_->bzero();buffers_.reserve(16);
}void AsyncLogging::append(const char* logline, int len)
{muduo::MutexLockGuard lock(mutex_);if (currentBuffer_->avail() > len){currentBuffer_->append(logline, len);}else{buffers_.push_back(std::move(currentBuffer_));if (nextBuffer_){currentBuffer_ = std::move(nextBuffer_);}else{// 四个缓冲区都写满了currentBuffer_.reset(new Buffer); // Rarely happens}currentBuffer_->append(logline, len);// 这里的notify不一定什么时候都有效// 如果此时守护线程正在工作// 那么这个信后就会丢失,但是没有造成影响// 但是有可能守护线程正在条件变量上睡眠cond_.notify();}
}void AsyncLogging::threadFunc()
{assert(running_ == true);latch_.countDown();		// 计数器减一,latch_ == 0,并唤醒主线程LogFile output(basename_, rollSize_, false);	// 初始化一个输出流BufferPtr newBuffer1(new Buffer);BufferPtr newBuffer2(new Buffer);newBuffer1->bzero();newBuffer2->bzero();BufferVector buffersToWrite;	// 相当于一个前后端交互的单元// 将写满的buffer装到vector中// 在传输到后端buffersToWrite.reserve(16);while (running_){assert(newBuffer1 && newBuffer1->length() == 0);assert(newBuffer2 && newBuffer2->length() == 0);assert(buffersToWrite.empty());{muduo::MutexLockGuard lock(mutex_);// 使用条件变量完成定时任务if (buffers_.empty())  // unusual usage!{cond_.waitForSeconds(flushInterval_);}buffers_.push_back(std::move(currentBuffer_));currentBuffer_ = std::move(newBuffer1);buffersToWrite.swap(buffers_);	// buffers_变成一个空的buffers_if (!nextBuffer_){nextBuffer_ = std::move(newBuffer2);}}assert(!buffersToWrite.empty());// 如果日志太多了if (buffersToWrite.size() > 25){char buf[256];snprintf(buf, sizeof buf, "Dropped log messages at %s, %zd larger buffers\n",Timestamp::now().toFormattedString().c_str(),buffersToWrite.size()-2);fputs(buf, stderr);// 先输出一个报警的日志output.append(buf, static_cast<int>(strlen(buf)));// 清除多余的日志buffersToWrite.erase(buffersToWrite.begin()+2, buffersToWrite.end());}for (const auto& buffer : buffersToWrite){// FIXME: use unbuffered stdio FILE ? or use ::writev ?output.append(buffer->data(), buffer->length());}if (buffersToWrite.size() > 2){// drop non-bzero-ed buffers, avoid trashing// vector底层是智能指针不用担心内存泄露buffersToWrite.resize(2);}if (!newBuffer1){assert(!buffersToWrite.empty());newBuffer1 = std::move(buffersToWrite.back());buffersToWrite.pop_back();newBuffer1->reset();}if (!newBuffer2){assert(!buffersToWrite.empty());newBuffer2 = std::move(buffersToWrite.back());buffersToWrite.pop_back();newBuffer2->reset();}buffersToWrite.clear();output.flush();}output.flush();
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/763000.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

美团2023年财报:全年营收2767亿元,即时配送订单219亿笔

3月22日&#xff0c;美团(股票代码:3690.HK)发布2023年第四季度及全年业绩。公司各项业务继续取得稳健增长&#xff0c;全年营收2767亿元(人民币&#xff0c;下同)&#xff0c;同比增长26%&#xff0c;经营利润134亿元。 本年度&#xff0c;美团继续围绕“零售科技”战略&…

openlayers 入门教程(四):layers 篇

还是大剑师兰特&#xff1a;曾是美国某知名大学计算机专业研究生&#xff0c;现为航空航海领域高级前端工程师&#xff1b;CSDN知名博主&#xff0c;GIS领域优质创作者&#xff0c;深耕openlayers、leaflet、mapbox、cesium&#xff0c;canvas&#xff0c;webgl&#xff0c;ech…

广告增量实时索引构建实践

本期作者 1.前言 在广告检索系统中&#xff0c;增量索引&#xff08;实时索引&#xff09;是一类常见的技术&#xff0c;用于使广告信息的变更及时生效。其中一种主要的思路即由检索系统消费广告更新数据流&#xff0c;实时更新内存索引&#xff0c;对此行业中已有很多优秀方案…

OpenHarmony开发之图形UI组件解析

简介 图形UI组件实现了一套系统级的图形引擎。 该组件为应用开发提供UIKit接口&#xff0c;包括了动画、布局、图形转换、事件处理&#xff0c;以及丰富的UI组件。 组件内部直接调用HAL接口&#xff0c;或者使用WMS(Window Manager Service)提供的客户端与硬件交互&#xff…

数据结构之排序一

目录 1.排序 一.概念及其分类 二.排序的稳定性 2.插入排序 一.基本思想 二.插入排序的实现 复杂度 稳定性的分析 3.希尔排序 一.预排序代码的实现 二.希尔排序代码实现 复杂度分析 4.clock函数 1.排序 一.概念及其分类 说到排序&#xff0c;我们都不陌生&#x…

设计数据库之概念模式:E-R模型

Chapter3&#xff1a;设计数据库之概念模式&#xff1a;E-R模型 笔记来源&#xff1a;《漫画数据库》—科学出版社 设计数据库的步骤&#xff1a; 概念模式 概念模式(conceptual schema)是指将现实世界模型化的阶段进而&#xff0c;是确定数据库理论结构的阶段。 概念模式的设…

Ubuntu 安装 Carla仿真环境

1、系统要求 Ubuntu 16.04/18.04/20.04 CARLA 为 16.04 之前的 Ubuntu 版本提供支持。然而&#xff0c;Unreal Engine需要合适的编译器才能正常工作。 CARLA 服务器至少需要 6 GB GPU&#xff0c;但建议使用 8 GB。 2、安装NIVDIA驱动 BISO设置 开机F12&#xff0c;进入BIOS…

0x01_实验课leetcode

题目总结 lc1979 给你一个整数数组 nums &#xff0c;返回数组中最大数和最小数的 最大公约数 。 两个数的 最大公约数 是能够被两个数整除的最大正整数。 会求 gcd 就行 class Solution { public:int gcd(int a, int b){return b ? gcd(b, a % b) : a;}int findGCD(vector&…

29-中断管理

中断管理 什么是中断管理&#xff1f; 用户可以自定义配置系统可管理的最高中断优先级的宏定义configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY&#xff08;高四位有效&#xff09;&#xff0c;它是用于配置内核中的basepri 寄存器的&#xff0c;当 basepri 设置为某个值的时候…

【sql】初识 where EXISTS

文章目录 概述1. select 简单示例2. update和DELETE参考 相关文章&#xff1a; 【sql】深入理解 mysql的EXISTS 语法 【sql】初识 where EXISTS 概述 where EXISTS &#xff08;子查询&#xff09;多对多中通过中间表查对方列表 1. select 简单示例 用户表A&#xff0c;小组…

hive语法树分析,判断 sql语句中有没有select *

pom依赖参考以下博文java 通过 IMetaStoreClient 取 hive 元数据信息-CSDN博客1 节点处理器类 import lombok.Getter; import org.apache.hadoop.hive.ql.lib.Dispatcher; import org.apache.hadoop.hive.ql.lib.Node; import org.apache.hadoop.hive.ql.parse.ASTNode; impor…

org.springframework.boot:type=Admin,name=SpringApplication异常

javax.management.InstanceNotFoundException: org.springframework.boot:typeAdmin,nameSpringApplication 问题描述&#xff1a; IDEA 新建 SpringBoot 项目&#xff0c;启动时后台报错&#xff1a; javax.management.InstanceNotFoundException: org.springframework.boot…

windows搭建Elasticsearch环境

windows搭建Elasticsearch环境 本章搭建Elasticsearch ik分词器插件 kibana三个环境.三个版本都是7.8.0 1.安装Elasticsearch 安装网址: https://www.elastic.co/cn/downloads/past-releases#elasticsearch 下载解压后直接进入bin目录&#xff0c;双击运行elasticsearch.…

基于springboot的牙科就诊管理系统

技术&#xff1a;springbootmysqlvue 一、系统背景 当前社会各行业领域竞争压力非常大&#xff0c;随着当前时代的信息化&#xff0c;科学化发展&#xff0c;让社会各行业领域都争相使用新的信息技术&#xff0c;对行业内的各种相关数据进行科学化&#xff0c;规范化管理。这样…

粤嵌6818开发板如何理解Linux文件IO?

一、文件IO的概述 1、什么是文件&#xff1f; Linux下一切皆文件。普通文件、目录文件、管道文件、套接字文件、链接文件、字符设备文件、块设备文件。 2、什么是IO&#xff1f; input output&#xff1a;输入输出 3、什么是文件IO&#xff1f; 对文件的输入输出&#xff0c;把…

轻松找回丢失数据EasyRecovery数据恢复软件让你无后顾之忧

轻松找回丢失数据&#xff0c;EasyRecovery数据恢复软件让你无后顾之忧&#xff0c;电脑数码行业必备工具&#xff0c;让你的数据安全有保障 &#xff01; 一、EasyRecovery数据恢复软件简介 在我们的日常生活中&#xff0c;无论是工作还是学习&#xff0c;都离不开电脑和数据…

Terraform实战(四)-资源打标签

1 腾讯云 1.1 tf配置 标签&#xff08;Tag&#xff09;是腾讯云提供的云资源管理工具&#xff0c;以键值对 key:values 的形式存在&#xff0c;用于关联您的大多数云资源&#xff0c;对于资源的分类、搜索和聚合十分有用。 在 Terraform 中&#xff0c;通过 Map 来定义一个资…

Linux/Perfection

Enumeration nmap 用 nmap 扫描了常见的端口&#xff0c;发现对外开放了 22,80&#xff0c;扫描一下详细信息&#xff0c;如下所示 ┌──(kali㉿kali)-[~/vegetable/HTB/Perfection] └─$ nmap -sC -sV -p 22,80 10.10.11.253 -oA nmap Starting Nmap 7.93 ( https://nmap…

目标检测——DOTA航拍数据集

DOTA数据集是一个用于航空图像中目标检测的大规模数据集&#xff0c;旨在帮助研究人员开发和评估航空图像中的目标检测算法。该数据集具有广泛的应用价值&#xff0c;尤其在计算机视觉和遥感技术领域。 DOTA数据集的特点主要体现在以下几个方面&#xff1a;首先&#xff0c;其…

科研文献阅读方法

阅读科研文献是科研工作者的重要工作之一&#xff0c;以下是一些阅读科研文献的方法&#xff1a; 确定阅读目的&#xff1a;在阅读科研文献之前&#xff0c;确定你的阅读目的&#xff0c;是为了了解某一领域的最新进展&#xff0c;还是为了找到支持自己研究的理论和实证依据。…