LogFile.h——与日志记录文件有关的

2017-08-17  本文已影响0人  Myth52125

该类进一步封装了FileUtil.h,在应该的时候 使用新的日志文件。

同时该类可以选择是否是线程安全的(在构造的时候,可选的进行互斥量的初始化,同时每个函数检测互斥量,如果有,那么加锁调用函数,否则,直接调用函数)。

这个类功能如下:

  1. 生成新的文件名
  2. 达到一定条件后,更换新的日志文件
  3. 想文件中添加数据

LogFile.h

成员变量

  1. string _basename
    日志文件文件名的头部分,后半部分随程序运行自动生成。
  2. size_t _rollSize
    单个日志文件的最大写入的字节数。
    超过该字节接换文件,与FileUtil总的_writtenBytes对比。
  3. int _flushInterval
    日志流写入到实际文件中的间隔。
  4. int _checkEveryN
    每个日志文件最大存储条数。
  5. boost::scoped_ptr<MutexLock> _mutex
    互斥量,使用的智能指针。
  6. time_t _startOfPeriod, _lastRoll, _lastFlush
    这三个变量对应着:当前日志文件创建时间(秒),当前日志的创建时间(毫秒),上次将缓冲区日志写到文件的时间(毫秒)。
  7. boost::scoped_ptr<FileUtil::AppendFile> _file
    存储这当前的日志指针。

构造函数

LogFile::LogFile(const string& basename,size_t rollSize,bool threadSafe,int flushInterval,int checkEveryN)
  : _basename(basename),
    _rollSize(rollSize),
    _flushInterval(flushInterval),
    _checkEveryN(checkEveryN),
    _count(0),
    _mutex(threadSafe ? new MutexLock : NULL),  //可选是否使用锁
    _startOfPeriod(0),
    _lastRoll(0),
    _lastFlush(0)
{
  assert(basename.find('/') == string::npos);
  rollFile();  //启动就要创建文件夹
}

getLogFileName()

该函数动态生成日志文件的文件名。

sstring getLogFileName(const string &basename, time_t *now)
{
    string filename;
    filename.reserve(basename.size() + 64); //文件名
    filename = basename;
    //格式化时间
    char timebuf[32];
    struct tm tm;                                              //居然可以同名
    *now = time(NULL);                                         //填充传入的时间
    gmtime_r(now, &tm);                                        //time_t填充tm
    strftime(timebuf, sizeof timebuf, ".%Y%m%d-%H%M%S.", &tm); //时间格式化为字符串

    filename += timebuf;
    filename += ProcessInfo::hostname();                        //添加信息

    char pidbuf[32];
    snprintf(pidbuf, sizeof pidbuf, ".%d", ProcessInfo::pid()); //添加线程心西
    filename += pidbuf;

    filename += ".log";

    return filename;
}

rollFile()

主要是创建文件,更换指针。

bool LogFile::rollFile()
{
  time_t now = 0;
  string filename = getLogFileName(basename_, &now);    //在这里面填充now为什么?
  time_t start = now / kRollPerSeconds_ * kRollPerSeconds_; //换成秒

  if (now > lastRoll_)  //记录这次创建时间。
  {
    lastRoll_ = now;
    lastFlush_ = now;
    startOfPeriod_ = start;
    file_.reset(new AppendFile(filename));  //更换文件
    return true;
  }
  return false;
}

void LogFile::append_unlocked(const char* logline, int len)
{
  _file->append(logline, len);                          //添加日志信息

  if (_file->writtenBytes() > _rollSize)                //如果达到日志文件最大大小,那么创建新日志
  {
    rollFile();
  }
  else
  {
    ++_count;
    if (_count >= _checkEveryN)                         //达到日志文件的最大记录条数,创建新日志
    {
      _count = 0;
      time_t now = ::time(NULL);
      time_t _thisPeriod = now / kRollPerSeconds_ * kRollPerSeconds_;
      if (_thisPeriod != _startOfPeriod)                //***
      {
        rollFile();
      }
      else if (now - _lastFlush > _flushInterval)       //****
      {
        _lastFlush = now;
        _file->flush();
      }
    }
  }
}

逻辑这样:

  1. 如果达到单个日志文件的大小上限,就创建新的日志文件
  2. 当达到单个日志文件最大记录条数,需要判断当前时间和上一个日志创建的时间是否相同
    如果不同:那么创建新的日志文件
    如果相同:那么判断是否上次的写入文件的时间到现在是否达到设置的间隔时间,如果达到那么讲数据写到文件中。下次回来的时候,count被置0。
    也就是说,在一个日志文件中可以存储超过设置的最大记录条数,是设置的n倍。

两个存数据的函数

通过判断互斥量,选择是否要上锁。

void LogFile::append(const char* logline, int len)
{
  if (_mutex)
  {
    MutexLockGuard lock(*_mutex);
    append_unlocked(logline, len);
  }
  else
  {
    append_unlocked(logline, len);
  }
}

void LogFile::flush()
{
  if (_mutex)
  {
    MutexLockGuard lock(*_mutex);
    _file->flush();
  }
  else
  {
    _file->flush();
  }
}
上一篇下一篇

猜你喜欢

热点阅读