当前位置:首页 > 芯闻号 > 充电吧
[导读]首先要区分LOG文件和.log文件。LOG文件:用来记录数据库打印的运行日志信息,方便bug的查找。.log文件:在LevelDB中的主要作用是系统故障恢复时,能够保证不会丢失数据。因为在将记录写入内

首先要区分LOG文件和.log文件。

LOG文件:用来记录数据库打印的运行日志信息,方便bug的查找。

.log文件:在LevelDB中的主要作用是系统故障恢复时,能够保证不会丢失数据。因为在将记录写入内存的Memtable之前,会先写入.log文件,这样即使系统发生故障,Memtable中的数据没有来得及Dump到磁盘的SSTable文件,LevelDB也可以根据.log文件恢复内存的Memtable数据结构内容,不会造成系统丢失数据。

Env.h中定义了操作LOG文件的虚基类Logger,只提供了一个对外的接口Logv。Logger的Windows版本实现是WinLogger。

// win_logger.h
class WinLogger : public Logger {
 private:
  FILE* file_;
 public:
  explicit WinLogger(FILE* f) : file_(f) { assert(file_); }
  virtual ~WinLogger() {
    fclose(file_);
  }
  virtual void Logv(const char* format, va_list ap);
};
// win_logger.cc
void WinLogger::Logv(const char* format, va_list ap) {
  // 获取当前线程ID
  const uint64_t thread_id = static_cast(::GetCurrentThreadId());


  // We try twice: the first time with a fixed-size stack allocated buffer,
  // and the second time with a much larger dynamically allocated buffer.
  // 尝试两次内存分配:第一次分配固定大小的栈内存,如果不够,第二次分配更大的堆内存
  char buffer[500];


  for (int iter = 0; iter < 2; iter++) {
    char* base;
    int bufsize;
    if (iter == 0) {
      bufsize = sizeof(buffer);
      base = buffer;
    } else {
      bufsize = 30000;
      base = new char[bufsize];
    }


    char* p = base;
    char* limit = base + bufsize;


    SYSTEMTIME st;


    // GetSystemTime returns UTC time, we want local time!
    ::GetLocalTime(&st);


    p += _snprintf_s(p, limit - p, _TRUNCATE,
      "%04d/%02d/%02d-%02d:%02d:%02d.%03d %llx ",
      st.wYear,
      st.wMonth,
      st.wDay,
      st.wHour,
      st.wMinute,
      st.wSecond,
      st.wMilliseconds,
      static_cast(thread_id));


    // Print the message
    if (p < limit) {
      va_list backup_ap = ap;
	   // limit-p是p可接受的最大字符数
      p += vsnprintf(p, limit - p, format, backup_ap);
      va_end(backup_ap);
    }


    // Truncate to available space if necessary
    // 如果第一次分的栈内存不够,会第二次分配更大的堆内存。
    // 如果第二次分的内存还不够,只能对存放内容做截断处理了。
    // 为什么p==limit也算内存不够呢?因为最后要存放换行符,
    // 所以有效的内容最大长度只能是limit-p-1。
    if (p >= limit) {
      if (iter == 0) {
        continue; // Try again with larger buffer
      } else {
        p = limit - 1;
      }
    }


    // Add newline if necessary
    // 如果p==base或者有效内容的最后一个字符不是换行符
    // 则将换行符添加到最后
    if (p == base || p[-1] != 'n') {
      *p++ = 'n';
    }


    assert(p <= limit);
    fwrite(base, 1, p - base, file_);
    // fwrite只是将写入内容放入缓存中,真正输出到文件是通过fflush实现的。
    fflush(file_);
    // 如果分配了堆内存,需要手动释放。
    if (base != buffer) {
      delete[] base;
    }
    break;
  }
}

我用的是Windows版LevelDB,上面这段代码在Windows 7上用VS2013调试时是有bug的。当要打印的日志信息长度超过30000时,vsnsprintf会截断信息,但是vsnsprintf并不会返回被截断前的信息的长度,而是返回-1,这样一来,那一行日志信息只会打印出日期、时间和线程号,尽管一行日志超过30000字节的概率非常小。经查证,vsnsprintf的返回值和操作系统、编译器有关。

经测试,Windows10上用VS2015时vsnsprintf能返回期望结果——被截断前的信息的长度。


个人觉得这段代码非常值得学习。首先是考虑了内存分配的情况。通常看到的日志实现中,要么是在栈中设定一个定长缓冲区,然后设定一个日志最大长度,以此来避免内存分配;要么是直接分配一大块内存来放日志字符串。这里作者使用了两级“内存分配”,首先在栈中分配500个字节的缓冲区,这样长度小于500字节的日志就可以避免掉new的开销。如果发现放不下,再去new一个大块内存。当然如果单行日志太大,超过了30000字节,那么就直接做截断了。其次就是内存的防越界处理。

不过这里有个疑问,为何添加换行符的时候要判断p==base,知道的同学请指点下。

最后在Env.h中封装了一个全局的方法Log,方便调用接口Logv,如下所示。


void Log(Logger* info_log, const char* format, ...) {
  if (info_log != NULL) {
    va_list ap;
    va_start(ap, format);
    info_log->Logv(format, ap);
    va_end(ap);
  }
}


调用方法:Log(result.info_log, "Ignoring error %s","灿哥哥的博客");








本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

May 20, 2024 ---- 据TrendForce集邦咨询研究,三大原厂开始提高先进制程的投片,继存储器合约价翻扬后,公司资金投入开始增加,产能提升将集中在今年下半年,预期1alpha nm(含)以上投片至年底将...

关键字: 晶圆 HBM 存储器

2024年5月18日,强国机械制造有限公司正式宣布,全力支持国家提出的“中国制造2050”战略。公司将把智能制造作为未来发展的核心方向,致力于在这一领域实现重大突破,提升中国制造业的全球竞争力。

关键字: 智能制造 物联网

每次与老友见面时总是免不了谈论以前美好的回忆,但时间渐长,我们的记忆也渐渐模糊,还有电子设备帮助我们留下痕迹,只是翻找起来有些许麻烦。不过我们倒是没有这样的困扰,那是因为我有铁威马NAS,无论什么时间的照片都能放在nas...

关键字: 数据中心 数据存储

合肥2024年5月18日 /美通社/ -- 5月17日,以"致新世界"为主题,国轩高科第13届科技大会在包河总部隆重启幕,瞄准用户最为关切的高安全性、长续航、快速充电等核心需求和痛点问题,重磅发布三大...

关键字: 国轩高科 快充 电芯 能量密度

上海2024年5月19日 /美通社/ -- 5月18日,一年一度佳通商用车胎产品日如期而至。结合新市场、新机遇、新挑战,佳通轮胎召开"数智赋能 佳境无限"为主题的2024年度商用车胎技术暨产品发布会,...

关键字: 轮胎 数字化 零部件 TPMS

NRT14 于 2025 年底竣工后,园区容量将提高到104 兆瓦, 以满足日本对下一代基础设施和无缝接入互联数据社区日益增长的需求 北京2024年5月20日 /美通社/ -- 世界领先的...

关键字: DIGITAL 人工智能 数字化 数据中心

北京2024年5月20日 /美通社/ -- 过去五年里,支付和收款方式日新月异,其发展和变化比过去五十年都要迅猛。从嵌入式数字商务的出现,到"一拍即付"的...

关键字: VI BSP PAY COM

杭州2024年5月20日 /美通社/ -- 5月20日,百世供应链旗下百世云仓在2024年全国网络大会上,宣布了其全面出海战略。聚焦于东南亚市场的新机遇,并积极推动品牌走向国际市场。 百世供应链召开2024年百世云仓全...

关键字: 供应链 网络 触点 软件

上海2024年5月20日 /美通社/ -- 仲夏伊始,光芒新生,5月17日,由上海工业商务展览有限公司主办的、以"拥抱新质生产力,助力新型工业化"为主题的第九届广东国际机器人及智能装备博览会(以下简称...

关键字: IAR 机器人 自动化 RS

开幕在即!SEMI-e第六届深圳国际半导体展将在深圳国际会展中心(宝安)4/6/8号馆拉开精彩帷幕!

关键字: 半导体
关闭
关闭