/*=============================================================================
函 数 名: 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函数是不会改变当前文件偏移量的(文件指针),而read和write函数会改变当前文件偏移量
pread pwrite 是可以用在多线程里的。每个线程都使用同一个文件描述符。
如果每个线程都打开了文件描述符,则不用考虑
glog 日志函数
最新推荐文章于 2022-05-05 23:51:29 发布