bwa_perf/util.cpp

165 lines
3.9 KiB
C++

#define FSYNC_ON_FLUSH
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <string.h>
#include <errno.h>
#ifdef FSYNC_ON_FLUSH
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#endif
#include <stdarg.h>
#include "util.h"
// base转成2bit值
int bval(char b)
{
if (b == 'A')
return 0;
if (b == 'C')
return 1;
if (b == 'G')
return 2;
if (b == 'T')
return 3;
return 4;
}
// 互补碱基值
int cbval(char b)
{
return 3 - bval(b);
}
double realtime(void)
{
struct timeval tp;
struct timezone tzp;
gettimeofday(&tp, &tzp);
return tp.tv_sec + tp.tv_usec * 1e-6;
}
// 打印故障信息,并终止程序
void _err_fatal_simple_core(const char *func, const char *msg)
{
fprintf(stderr, "[%s] %s Abort!\n", func, msg);
abort();
}
// 打印信息并停止运行
void _err_fatal_simple(const char *func, const char *msg)
{
fprintf(stderr, "[%s] %s\n", func, msg);
exit(EXIT_FAILURE);
}
void err_fatal(const char *header, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
fprintf(stderr, "[%s] ", header);
vfprintf(stderr, fmt, args);
fprintf(stderr, "\n");
va_end(args);
exit(EXIT_FAILURE);
}
void err_fatal_core(const char *header, const char *fmt, ...)
{
va_list args;
va_start(args, fmt);
fprintf(stderr, "[%s] ", header);
vfprintf(stderr, fmt, args);
fprintf(stderr, " Abort!\n");
va_end(args);
abort();
}
// 打开文件流
FILE *err_xopen_core(const char *func, const char *fn, const char *mode)
{
FILE *fp = 0;
if (strcmp(fn, "-") == 0)
return (strstr(mode, "r")) ? stdin : stdout;
if ((fp = fopen(fn, mode)) == 0)
{
err_fatal(func, "fail to open file '%s' : %s", fn, strerror(errno));
}
return fp;
}
// 读取数据
bwtint_t fread_fix(FILE *fp, bwtint_t size, void *a)
{ /* Mac/Darwin has a bug when reading data longer than 2GB. This function fixes this issue by reading data in small chunks */
const int bufsize = 0x1000000; // 16M block
bwtint_t offset = 0;
while (size)
{
int x = bufsize < size ? bufsize : size;
if ((x = fread((uint8_t *)a + offset, 1, x, fp)) == 0)
break;
size -= x;
offset += x;
}
return offset;
}
// 写二进制文件
size_t err_fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream)
{
size_t ret = fwrite(ptr, size, nmemb, stream);
if (ret != nmemb)
_err_fatal_simple("fwrite", strerror(errno));
return ret;
}
// 读取单个数据
size_t err_fread_noeof(void *ptr, size_t size, size_t nmemb, FILE *stream)
{
size_t ret = fread(ptr, size, nmemb, stream);
if (ret != nmemb)
{
_err_fatal_simple("fread", ferror(stream) ? strerror(errno) : "Unexpected end of file");
}
return ret;
}
// 刷新文件流
int err_fflush(FILE *stream)
{
int ret = fflush(stream);
if (ret != 0)
_err_fatal_simple("fflush", strerror(errno));
#ifdef FSYNC_ON_FLUSH
/* Calling fflush() ensures that all the data has made it to the
kernel buffers, but this may not be sufficient for remote filesystems
(e.g. NFS, lustre) as an error may still occur while the kernel
is copying the buffered data to the file server. To be sure of
catching these errors, we need to call fsync() on the file
descriptor, but only if it is a regular file. */
{
struct stat sbuf;
if (0 != fstat(fileno(stream), &sbuf))
_err_fatal_simple("fstat", strerror(errno));
if (S_ISREG(sbuf.st_mode))
{
if (0 != fsync(fileno(stream)))
_err_fatal_simple("fsync", strerror(errno));
}
}
#endif
return ret;
}
// 关闭文件流
int err_fclose(FILE *stream)
{
int ret = fclose(stream);
if (ret != 0)
_err_fatal_simple("fclose", strerror(errno));
return ret;
}