STTNet 0.7.0

第 14 章:文件与异步日志

本章说明路径工具、线程安全文件对象、有界异步日志及其生命周期关系。

1. 三层能力

职责关键契约
FileTool创建目录/文件、二进制复制、获取大小copy() 不创建目标父目录;任一文件打开或写入失败返回 false
File线程安全文本/二进制读写和内存事务文件操作从 openFile() 开始;内存事务由加锁线程解锁
LogFile有界队列和独立消费者线程队列满时丢弃并计数,不阻塞业务线程

2. 文件复制保留原始字节

if(!stt::file::FileTool::copy(
       "runtime/source.bin",
       "runtime/backup/source.bin"))
{
    // 目标父目录不存在、文件打不开或写入失败。
}

copy() 按二进制复制,NUL、换行和不可打印字节都会保留。目标父目录需在调用前存在。

3. File 与内存事务

stt::file::File config;
if(!config.openFile("runtime/app.conf"))
    return 1;

config.deleteAll();
config.appendLine("port=8080");
config.appendLine("workers=4");
config.closeFile();

普通方法自行完成锁定、修改和保存。lockMemory() 与带 C 后缀的方法表示同一把锁内的多步事务;每条退出路径都与一次 unlockMemory() 对应。

4. 异步日志的生命周期

{
    // 容量采用 MPSCQueue 要求的 2 的幂。
    stt::file::LogFile log(16384);
    if(!log.openFile("logs/server.log", ISO8086B, "  "))
        return 1;

    log.writeLog("server started");
    std::cout << log.getDroppedLogCount() << '
';

    // 所有生产者停止后,作用域结束时由析构流程排空队列。
    // 析构函数会停止消费者并排空已经进入队列的日志。
}
  • 固定时长的 sleep(50ms) 不能作为日志刷盘完成的判断依据。
  • LogFile 的生命周期需要覆盖所有调用 writeLog() 的线程。
  • 队列满时写入会被丢弃;通过 getDroppedLogCount() 监控。
  • deleteLogByTime(start,end) 使用 [start,end) 区间。
  • 日志内容应排除密码、私钥、完整 Token/Cookie 和敏感请求体。

完整文件与日志 Demo →