add buffered_file_writer.[hc] files
parent
2992bfc4be
commit
ad57015174
|
|
@ -0,0 +1,214 @@
|
|||
/**
|
||||
* Copyright (C) 2008 Happy Fish / YuQing
|
||||
*
|
||||
* FastDFS may be copied only under the terms of the GNU General
|
||||
* Public License V3, which may be found in the FastDFS source kit.
|
||||
* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail.
|
||||
**/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdarg.h>
|
||||
#include "shared_func.h"
|
||||
#include "logger.h"
|
||||
#include "buffered_file_writer.h"
|
||||
|
||||
int buffered_file_writer_open_ex(BufferedFileWriter *writer,
|
||||
const char *filename, const int buffer_size,
|
||||
const int max_written_once, const int mode)
|
||||
{
|
||||
int result;
|
||||
int written_once;
|
||||
|
||||
writer->buffer_size = (buffer_size > 0) ? buffer_size : 64 * 1024;
|
||||
written_once = (max_written_once > 0) ? max_written_once : 256;
|
||||
if (written_once > writer->buffer_size)
|
||||
{
|
||||
logError("file: "__FILE__", line: %d, "
|
||||
"max_written_once: %d > buffer_size: %d",
|
||||
__LINE__, written_once, writer->buffer_size);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
writer->buff = (char *)malloc(writer->buffer_size);
|
||||
if (writer->buff == NULL)
|
||||
{
|
||||
logError("file: "__FILE__", line: %d, "
|
||||
"malloc %d bytes fail",
|
||||
__LINE__, writer->buffer_size);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
snprintf(writer->filename, sizeof(writer->filename), "%s", filename);
|
||||
writer->fd = open(writer->filename, O_WRONLY | O_CREAT | O_TRUNC, mode);
|
||||
if (writer->fd < 0)
|
||||
{
|
||||
result = errno != 0 ? errno : EIO;
|
||||
logError("file: "__FILE__", line: %d, "
|
||||
"open file %s fail, "
|
||||
"errno: %d, error info: %s",
|
||||
__LINE__, writer->filename,
|
||||
result, STRERROR(result));
|
||||
|
||||
free(writer->buff);
|
||||
writer->buff = NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
writer->current = writer->buff;
|
||||
writer->buff_end = writer->buff + writer->buffer_size;
|
||||
writer->water_mark = writer->buff_end - written_once;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int buffered_file_writer_close(BufferedFileWriter *writer)
|
||||
{
|
||||
int result;
|
||||
|
||||
if (writer->buff == NULL)
|
||||
{
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
result = buffered_file_writer_flush(writer);
|
||||
if (result == 0 && fsync(writer->fd) != 0)
|
||||
{
|
||||
result = errno != 0 ? errno : EIO;
|
||||
logError("file: "__FILE__", line: %d, "
|
||||
"fsync file %s fail, "
|
||||
"errno: %d, error info: %s",
|
||||
__LINE__, writer->filename,
|
||||
result, STRERROR(result));
|
||||
}
|
||||
|
||||
if (close(writer->fd) != 0)
|
||||
{
|
||||
if (result == 0)
|
||||
{
|
||||
result = errno != 0 ? errno : EIO;
|
||||
}
|
||||
logError("file: "__FILE__", line: %d, "
|
||||
"close file %s fail, "
|
||||
"errno: %d, error info: %s",
|
||||
__LINE__, writer->filename,
|
||||
errno, STRERROR(errno));
|
||||
}
|
||||
|
||||
free(writer->buff);
|
||||
writer->buff = NULL;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int buffered_file_writer_flush(BufferedFileWriter *writer)
|
||||
{
|
||||
int result;
|
||||
int len;
|
||||
|
||||
len = writer->current - writer->buff;
|
||||
if (len == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (fc_safe_write(writer->fd, writer->buff, len) != len)
|
||||
{
|
||||
result = errno != 0 ? errno : EIO;
|
||||
logError("file: "__FILE__", line: %d, "
|
||||
"write to file %s fail, "
|
||||
"errno: %d, error info: %s", __LINE__,
|
||||
writer->filename, result, STRERROR(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
writer->current = writer->buff;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int buffered_file_writer_append(BufferedFileWriter *writer,
|
||||
const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int result;
|
||||
int remain_size;
|
||||
int len;
|
||||
int i;
|
||||
|
||||
result = 0;
|
||||
for (i=0; i<2; i++)
|
||||
{
|
||||
remain_size = writer->buff_end - writer->current;
|
||||
va_start(ap, format);
|
||||
len = vsnprintf(writer->current, remain_size, format, ap);
|
||||
va_end(ap);
|
||||
|
||||
if (len < remain_size)
|
||||
{
|
||||
writer->current += len;
|
||||
if (writer->current > writer->water_mark)
|
||||
{
|
||||
result = buffered_file_writer_flush(writer);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (len > writer->buffer_size)
|
||||
{
|
||||
result = ENOSPC;
|
||||
logError("file: "__FILE__", line: %d, "
|
||||
"too large output buffer, %d > %d!",
|
||||
__LINE__, len, writer->buffer_size);
|
||||
break;
|
||||
}
|
||||
|
||||
//maybe full, try again
|
||||
if ((result=buffered_file_writer_flush(writer)) != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int buffered_file_writer_append_buff(BufferedFileWriter *writer,
|
||||
const char *buff, const int len)
|
||||
{
|
||||
int result;
|
||||
|
||||
if (len >= writer->water_mark - writer->current)
|
||||
{
|
||||
if ((result=buffered_file_writer_flush(writer)) != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
if (fc_safe_write(writer->fd, buff, len) != len)
|
||||
{
|
||||
result = errno != 0 ? errno : EIO;
|
||||
logError("file: "__FILE__", line: %d, "
|
||||
"write to file %s fail, "
|
||||
"errno: %d, error info: %s", __LINE__,
|
||||
writer->filename, result, STRERROR(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
memcpy(writer->current, buff, len);
|
||||
writer->current += len;
|
||||
if (writer->current > writer->water_mark)
|
||||
{
|
||||
return buffered_file_writer_flush(writer);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/**
|
||||
* Copyright (C) 2008 Happy Fish / YuQing
|
||||
*
|
||||
* FastDFS may be copied only under the terms of the GNU General
|
||||
* Public License V3, which may be found in the FastDFS source kit.
|
||||
* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail.
|
||||
**/
|
||||
|
||||
#ifndef BUFFERED_FILE_WRITER_H
|
||||
#define BUFFERED_FILE_WRITER_H
|
||||
|
||||
#include "common_define.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int fd;
|
||||
int buffer_size;
|
||||
char filename[MAX_PATH_SIZE];
|
||||
char *buff;
|
||||
char *current;
|
||||
char *buff_end;
|
||||
char *water_mark;
|
||||
} BufferedFileWriter;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** open buffered file writer
|
||||
* parameters:
|
||||
* writer: the writer
|
||||
* filename: the filename to write
|
||||
* buffer_size: the buffer size, <= 0 for recommend 64KB
|
||||
* max_written_once: max written bytes per call, <= 0 for 256
|
||||
* mode: the file privilege such as 0644
|
||||
* return: error code, 0 for success, != 0 for errno
|
||||
*/
|
||||
int buffered_file_writer_open_ex(BufferedFileWriter *writer,
|
||||
const char *filename, const int buffer_size,
|
||||
const int max_written_once, const int mode);
|
||||
|
||||
static inline int buffered_file_writer_open(BufferedFileWriter *writer,
|
||||
const char *filename)
|
||||
{
|
||||
const int buffer_size = 0;
|
||||
const int max_written_once = 0;
|
||||
const int mode = 0644;
|
||||
return buffered_file_writer_open_ex(writer, filename,
|
||||
buffer_size, max_written_once, mode);
|
||||
}
|
||||
|
||||
/** close buffered file writer
|
||||
* parameters:
|
||||
* writer: the writer
|
||||
* return: error code, 0 for success, != 0 for errno
|
||||
*/
|
||||
int buffered_file_writer_close(BufferedFileWriter *writer);
|
||||
|
||||
int buffered_file_writer_append(BufferedFileWriter *writer,
|
||||
const char *format, ...);
|
||||
|
||||
int buffered_file_writer_append_buff(BufferedFileWriter *writer,
|
||||
const char *buff, const int len);
|
||||
|
||||
int buffered_file_writer_flush(BufferedFileWriter *writer);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
Loading…
Reference in New Issue