324 lines
9.9 KiB
C
324 lines
9.9 KiB
C
/*
|
|
* Copyright (c) 2020 YuQing <384681@qq.com>
|
|
*
|
|
* This program is free software: you can use, redistribute, and/or modify
|
|
* it under the terms of the GNU Affero General Public License, version 3
|
|
* or later ("AGPL"), as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE.
|
|
*
|
|
* You should have received a copy of the GNU Affero General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
//sf_file_writer.h
|
|
|
|
#ifndef _SF_FILE_WRITER_H_
|
|
#define _SF_FILE_WRITER_H_
|
|
|
|
#include "fastcommon/fc_queue.h"
|
|
#include "sf_types.h"
|
|
|
|
#define SF_FILE_WRITER_FLAGS_WANT_DONE_VERSION 1
|
|
|
|
#define SF_BINLOG_SUBDIR_NAME_SIZE 128
|
|
#define SF_BINLOG_FILE_PREFIX_STR_SIZE 64
|
|
#define SF_BINLOG_DEFAULT_ROTATE_SIZE (1024 * 1024 * 1024)
|
|
#define SF_BINLOG_NEVER_ROTATE_FILE 0
|
|
#define SF_BINLOG_FILE_PREFIX_STR "binlog"
|
|
#define SF_BINLOG_FILE_PREFIX_LEN (sizeof(SF_BINLOG_FILE_PREFIX_STR) - 1)
|
|
#define SF_BINLOG_FILE_EXT_LEN 6
|
|
#define SF_BINLOG_FILE_EXT_FMT ".%0"FC_MACRO_TOSTRING(SF_BINLOG_FILE_EXT_LEN)"d"
|
|
|
|
struct sf_file_writer_info;
|
|
|
|
typedef void (*sf_file_write_done_callback)(
|
|
struct sf_file_writer_info *writer, void *args);
|
|
|
|
typedef struct sf_file_writer_info {
|
|
struct {
|
|
const char *data_path;
|
|
char subdir_name[SF_BINLOG_SUBDIR_NAME_SIZE];
|
|
char file_prefix[SF_BINLOG_FILE_PREFIX_STR_SIZE];
|
|
int64_t file_rotate_size;
|
|
int max_record_size;
|
|
bool call_fsync;
|
|
} cfg;
|
|
|
|
struct {
|
|
int start_index; //for read only
|
|
int last_index; //for write
|
|
int compress_index;
|
|
} binlog;
|
|
|
|
struct {
|
|
int fd;
|
|
int64_t size; //file size
|
|
struct {
|
|
char *str;
|
|
int size;
|
|
} name;
|
|
} file;
|
|
|
|
int64_t total_count;
|
|
SFBinlogBuffer binlog_buffer;
|
|
|
|
short flags;
|
|
struct {
|
|
int64_t pending;
|
|
volatile int64_t done;
|
|
} last_versions;
|
|
|
|
struct {
|
|
sf_file_write_done_callback func;
|
|
void *args;
|
|
} write_done_callback;
|
|
|
|
} SFFileWriterInfo;
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
int sf_file_writer_init(SFFileWriterInfo *writer, const char *data_path,
|
|
const char *subdir_name, const char *file_prefix,
|
|
const int max_record_size, const int buffer_size,
|
|
const int64_t file_rotate_size, const bool call_fsync);
|
|
|
|
void sf_file_writer_destroy(SFFileWriterInfo *writer);
|
|
|
|
int sf_file_writer_direct_write(SFFileWriterInfo *writer,
|
|
char *buff, const int len);
|
|
|
|
int sf_file_writer_deal_versioned_buffer(SFFileWriterInfo *writer,
|
|
BufferInfo *buffer, const int64_t version);
|
|
|
|
#define sf_file_writer_deal_buffer(writer, buffer) \
|
|
sf_file_writer_deal_versioned_buffer(writer, buffer, 0)
|
|
|
|
int sf_file_writer_flush(SFFileWriterInfo *writer);
|
|
|
|
int sf_file_writer_fsync(SFFileWriterInfo *writer);
|
|
|
|
#define SF_FILE_WRITER_DATA_END_BUFF(writer) (writer)->binlog_buffer.data_end
|
|
#define SF_FILE_WRITER_CURRENT_DATA_VERSION(writer) \
|
|
(writer)->last_versions.pending
|
|
#define SF_FILE_WRITER_NEXT_DATA_VERSION(writer) \
|
|
++((writer)->last_versions.pending)
|
|
|
|
int sf_file_writer_save_buffer_ex(SFFileWriterInfo *writer,
|
|
const int length, const bool flush);
|
|
|
|
static inline int sf_file_writer_save_buffer(
|
|
SFFileWriterInfo *writer, const int length)
|
|
{
|
|
const bool flush = false;
|
|
return sf_file_writer_save_buffer_ex(writer, length, flush);
|
|
}
|
|
|
|
static inline int sf_file_writer_flush_buffer(
|
|
SFFileWriterInfo *writer, const int length)
|
|
{
|
|
const bool flush = true;
|
|
return sf_file_writer_save_buffer_ex(writer, length, flush);
|
|
}
|
|
|
|
static inline void sf_file_writer_set_flags(
|
|
SFFileWriterInfo *writer, const short flags)
|
|
{
|
|
writer->flags = flags;
|
|
}
|
|
|
|
static inline void sf_file_writer_set_call_fsync(
|
|
SFFileWriterInfo *writer, const bool call_fsync)
|
|
{
|
|
writer->cfg.call_fsync = call_fsync;
|
|
}
|
|
|
|
static inline void sf_file_writer_set_write_done_callback (
|
|
SFFileWriterInfo *writer, sf_file_write_done_callback callback,
|
|
void *args)
|
|
{
|
|
writer->write_done_callback.func = callback;
|
|
writer->write_done_callback.args = args;
|
|
}
|
|
|
|
static inline int64_t sf_file_writer_get_last_version_ex(
|
|
SFFileWriterInfo *writer, const int log_level)
|
|
{
|
|
if (writer->flags & SF_FILE_WRITER_FLAGS_WANT_DONE_VERSION) {
|
|
return writer->last_versions.done;
|
|
} else {
|
|
if (FC_LOG_BY_LEVEL(log_level)) {
|
|
log_it_ex(&g_log_context, log_level, "file: %s, line: %d, "
|
|
"writer: %s, should set writer flags to %d!",
|
|
__FILE__, __LINE__, writer->cfg.subdir_name,
|
|
SF_FILE_WRITER_FLAGS_WANT_DONE_VERSION);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
#define sf_file_writer_get_last_version(writer) \
|
|
sf_file_writer_get_last_version_ex(writer, LOG_ERR)
|
|
|
|
#define sf_file_writer_get_last_version_silence(writer) \
|
|
sf_file_writer_get_last_version_ex(writer, LOG_NOTHING)
|
|
|
|
int sf_file_writer_get_binlog_indexes(const char *data_path,
|
|
const char *subdir_name, int *start_index, int *last_index);
|
|
|
|
static inline int sf_file_writer_get_binlog_start_index(
|
|
const char *data_path, const char *subdir_name,
|
|
int *start_index)
|
|
{
|
|
int last_index;
|
|
return sf_file_writer_get_binlog_indexes(data_path,
|
|
subdir_name, start_index, &last_index);
|
|
}
|
|
|
|
static inline int sf_file_writer_get_binlog_last_index(
|
|
const char *data_path, const char *subdir_name,
|
|
int *last_index)
|
|
{
|
|
int start_index;
|
|
return sf_file_writer_get_binlog_indexes(data_path,
|
|
subdir_name, &start_index, last_index);
|
|
}
|
|
|
|
int sf_file_writer_set_indexes(SFFileWriterInfo *writer,
|
|
const int start_index, const int last_index);
|
|
|
|
int sf_file_writer_get_indexes(SFFileWriterInfo *writer,
|
|
int *start_index, int *last_index);
|
|
|
|
static inline int sf_file_writer_get_start_index(SFFileWriterInfo *writer)
|
|
{
|
|
int start_index;
|
|
int last_index;
|
|
|
|
sf_file_writer_get_indexes(writer, &start_index, &last_index);
|
|
return start_index;
|
|
}
|
|
|
|
static inline int sf_file_writer_get_last_index(SFFileWriterInfo *writer)
|
|
{
|
|
int start_index;
|
|
int last_index;
|
|
|
|
sf_file_writer_get_indexes(writer, &start_index, &last_index);
|
|
return last_index;
|
|
}
|
|
|
|
#define sf_file_writer_get_current_write_index(writer) \
|
|
sf_file_writer_get_last_index(writer)
|
|
|
|
static inline void sf_file_writer_get_current_position(
|
|
SFFileWriterInfo *writer, SFBinlogFilePosition *position)
|
|
{
|
|
position->index = writer->binlog.last_index;
|
|
position->offset = writer->file.size;
|
|
}
|
|
|
|
static inline const char *sf_file_writer_get_filepath(
|
|
const char *data_path, const char *subdir_name,
|
|
char *filepath, const int size)
|
|
{
|
|
fc_get_full_filepath_ex(data_path, strlen(data_path),
|
|
subdir_name, strlen(subdir_name), filepath, size);
|
|
return filepath;
|
|
}
|
|
|
|
static inline const char *sf_file_writer_get_filename_ex(
|
|
const char *data_path, const char *subdir_name,
|
|
const char *file_prefix, const int binlog_index,
|
|
char *filename, const int size)
|
|
{
|
|
char *p;
|
|
int data_path_len;
|
|
int subdir_name_len;
|
|
int file_prefix_len;
|
|
|
|
data_path_len = strlen(data_path);
|
|
subdir_name_len = strlen(subdir_name);
|
|
file_prefix_len = strlen(file_prefix);
|
|
if (data_path_len + subdir_name_len + file_prefix_len +
|
|
4 + SF_BINLOG_FILE_EXT_LEN >= size)
|
|
{
|
|
snprintf(filename, size, "%s/%s/%s"SF_BINLOG_FILE_EXT_FMT,
|
|
data_path, subdir_name, file_prefix, binlog_index);
|
|
return filename;
|
|
}
|
|
|
|
p = filename;
|
|
memcpy(p, data_path, data_path_len);
|
|
p += data_path_len;
|
|
*p++ = '/';
|
|
memcpy(p, subdir_name, subdir_name_len);
|
|
p += subdir_name_len;
|
|
*p++ = '/';
|
|
memcpy(p, file_prefix, file_prefix_len);
|
|
p += file_prefix_len;
|
|
*p++ = '.';
|
|
fc_ltostr_ex(binlog_index, p, SF_BINLOG_FILE_EXT_LEN);
|
|
|
|
return filename;
|
|
}
|
|
|
|
#define sf_file_writer_get_filename(data_path, subdir_name, \
|
|
binlog_index, filename, size) \
|
|
sf_file_writer_get_filename_ex(data_path, subdir_name, \
|
|
SF_BINLOG_FILE_PREFIX_STR, binlog_index, filename, size)
|
|
|
|
const char *sf_file_writer_get_index_filename(const char *data_path,
|
|
const char *subdir_name, char *filename, const int size);
|
|
|
|
int sf_file_writer_set_binlog_start_index(SFFileWriterInfo *writer,
|
|
const int start_index);
|
|
|
|
int sf_file_writer_set_binlog_write_index(SFFileWriterInfo *writer,
|
|
const int last_index);
|
|
|
|
static inline int sf_file_writer_rotate_file(SFFileWriterInfo *writer)
|
|
{
|
|
int last_index;
|
|
last_index = sf_file_writer_get_current_write_index(writer);
|
|
return sf_file_writer_set_binlog_write_index(writer, last_index + 1);
|
|
}
|
|
|
|
int sf_file_writer_get_last_lines(const char *data_path,
|
|
const char *subdir_name, const int current_write_index,
|
|
char *buff, const int buff_size, int *count, int *length);
|
|
|
|
static inline int sf_file_writer_get_last_line_ex(const char *data_path,
|
|
const char *subdir_name, const int current_write_index,
|
|
char *buff, const int buff_size, int *length)
|
|
{
|
|
int count = 1;
|
|
return sf_file_writer_get_last_lines(data_path, subdir_name,
|
|
current_write_index, buff, buff_size, &count, length);
|
|
}
|
|
|
|
int sf_file_writer_get_last_line(const char *data_path,
|
|
const char *subdir_name, char *buff,
|
|
const int buff_size, int *length);
|
|
|
|
int sf_file_writer_write_to_binlog_index_file_ex(const char *data_path,
|
|
const char *subdir_name, const char *file_prefix,
|
|
const int start_index, const int last_index,
|
|
const int compress_index);
|
|
|
|
#define sf_file_writer_write_to_binlog_index_file(data_path, \
|
|
subdir_name, start_index, last_index) \
|
|
sf_file_writer_write_to_binlog_index_file_ex(data_path, subdir_name, \
|
|
SF_BINLOG_FILE_PREFIX_STR, start_index, last_index, 0)
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#endif
|