165 lines
3.9 KiB
C++
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;
|
|
} |