glog 日志函数

/*=============================================================================
  函 数 名: PuOsTruncateLogFile
  功    能: 隔一段时间缩短日志,使日志一直维持在最新的打印里
  算法实现: 
  全局变量: 
  输入参数: LPCSTR path   keep 
  返 回 值: 
=============================================================================*/
void PuOsTruncateLogFile(const char *path, u64 keep) {
  struct stat statbuf;
  const int kCopyBlockSize = 8 << 10;
  char copybuf[kCopyBlockSize];
  u64 read_offset, write_offset;
  int flags = O_RDWR;

  int fd = open(path, flags);
  if (fd == -1) {
    if (errno == EFBIG) {
      if (truncate(path, 0) == -1) {        
        PuOsPrintf(PU_LOGLEVEL_EXCEPTION, FALSE, PU_MODULE_OSAPI,"Unable to truncate %s\n",path);
        //printf("Unable to truncate %s\n",path);
      } else {
        PuOsPrintf(PU_LOGLEVEL_EXCEPTION, FALSE, PU_MODULE_OSAPI,"Truncated %s due to EFBIG error\n",path);
        //printf("Truncated %s due to EFBIG error\n",path);
      }
    } else {  
      PuOsPrintf(PU_LOGLEVEL_EXCEPTION, FALSE, PU_MODULE_OSAPI,"Unable to open %s\n",path);
      //printf("Unable to open %s\n",path);
    }
    return;
  }

  if (fstat(fd, &statbuf) == -1) {    
    PuOsPrintf(PU_LOGLEVEL_EXCEPTION, FALSE, PU_MODULE_OSAPI,"Unable to fstat()\n");
    //printf("Unable to fstat()\n");
    goto out_close_fd;
  }

  if (!S_ISREG(statbuf.st_mode)) goto out_close_fd;
  if (statbuf.st_size <= keep) goto out_close_fd;

  // This log file is too large - we need to truncate it  
  PuOsPrintf(PU_LOGLEVEL_EXCEPTION, FALSE, PU_MODULE_OSAPI,"Truncating %s to %llu bytes\n",path,keep);
  //printf("Truncating %s to %llu bytes\n",path,keep);


  // Copy the last "keep" bytes of the file to the beginning of the file
  read_offset = statbuf.st_size - keep;
  write_offset = 0;
  int bytesin, bytesout;
  while ((bytesin = pread(fd, copybuf, sizeof(copybuf), read_offset)) > 0) {
    bytesout = pwrite(fd, copybuf, bytesin, write_offset);
    if (bytesout == -1) {      
      PuOsPrintf(PU_LOGLEVEL_EXCEPTION, FALSE, PU_MODULE_OSAPI,"Unable to write to  %s\n",path);
      //printf("Unable to write to  %s\n",path);
      break;
    } else if (bytesout != bytesin) {
      PuOsPrintf(PU_LOGLEVEL_EXCEPTION, FALSE, PU_MODULE_OSAPI,"Expected to write %d , wrote %d\n",bytesin,bytesout);
      //printf("Expected to write %d , wrote %d\n",bytesin,bytesout);
    }
    read_offset += bytesin;
    write_offset += bytesout;
  }
  if (bytesin == -1)  PuOsPrintf(PU_LOGLEVEL_EXCEPTION, FALSE, PU_MODULE_OSAPI,"Unable to read from %s\n",path);

  // Truncate the remainder of the file. If someone else writes to the
  // end of the file after our last read() above, we lose their latest
  // data. Too bad ...
  //if (ftruncate(fd, write_offset) == -1) {
  //  PuOsPrintf(PU_LOGLEVEL_EXCEPTION, FALSE, PU_MODULE_OSAPI,"Unable to truncate %s\n",path);
  //}

 out_close_fd:
  close(fd);

}

pread函数相当于先后调用了lseek和read函数,但是还是有区别的,有以下两点区别:
pread函数是原子操作,而先后调用两个函数不是原子操作
pread函数是不会改变当前文件偏移量的(文件指针),而readwrite函数会改变当前文件偏移量

pread pwrite 是可以用在多线程里的。每个线程都使用同一个文件描述符。

 如果每个线程都打开了文件描述符,则不用考虑

你可能感兴趣的:(c)