support merge free trunk spaces
parent
8d2a04e435
commit
513894c5a2
3
HISTORY
3
HISTORY
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
Version 6.05 2019-12-20
|
||||
Version 6.05 2019-12-21
|
||||
* fdfs_trackerd and fdfs_storaged print the server version in usage.
|
||||
you can execute fdfs_trackerd or fdfs_storaged without parameters
|
||||
to show the server version
|
||||
|
|
@ -10,6 +10,7 @@ Version 6.05 2019-12-20
|
|||
* support backup binlog file when truncate trunk binlog,
|
||||
the config item in tracker.conf: trunk_binlog_max_backups
|
||||
* support alignment size for trunk space allocation
|
||||
* support merge free trunk spaces
|
||||
|
||||
Version 6.04 2019-12-05
|
||||
* storage_report_ip_changed ignore result EEXIST
|
||||
|
|
|
|||
|
|
@ -161,6 +161,11 @@ slot_max_size = 1MB
|
|||
# fragmentation, but the more space is wasted.
|
||||
trunk_alloc_alignment_size = 512
|
||||
|
||||
# if merge contiguous free spaces of trunk file
|
||||
# default value is false
|
||||
# since V6.05
|
||||
trunk_free_space_merge = true
|
||||
|
||||
# the trunk file size, should >= 4MB
|
||||
# default value is 64MB
|
||||
# since V3.00
|
||||
|
|
|
|||
|
|
@ -142,6 +142,8 @@ int storage_get_params_from_tracker()
|
|||
"trunk_init_check_occupying", &iniContext, false);
|
||||
g_trunk_init_reload_from_binlog = iniGetBoolValue(NULL,
|
||||
"trunk_init_reload_from_binlog", &iniContext, false);
|
||||
g_trunk_free_space_merge = iniGetBoolValue(NULL,
|
||||
"trunk_free_space_merge", &iniContext, false);
|
||||
g_trunk_compress_binlog_min_interval = iniGetIntValue(NULL,
|
||||
"trunk_compress_binlog_min_interval", &iniContext, 0);
|
||||
g_trunk_compress_binlog_interval = iniGetIntValue(NULL,
|
||||
|
|
@ -203,6 +205,7 @@ int storage_get_params_from_tracker()
|
|||
"trunk_create_file_space_threshold=%d GB, "
|
||||
"trunk_init_check_occupying=%d, "
|
||||
"trunk_init_reload_from_binlog=%d, "
|
||||
"trunk_free_space_merge=%d, "
|
||||
"trunk_compress_binlog_min_interval=%d, "
|
||||
"trunk_compress_binlog_interval=%d, "
|
||||
"trunk_compress_binlog_time_base=%02d:%02d, "
|
||||
|
|
@ -224,6 +227,7 @@ int storage_get_params_from_tracker()
|
|||
(int)(g_trunk_create_file_space_threshold /
|
||||
(FDFS_ONE_MB * 1024)), g_trunk_init_check_occupying,
|
||||
g_trunk_init_reload_from_binlog,
|
||||
g_trunk_free_space_merge,
|
||||
g_trunk_compress_binlog_min_interval,
|
||||
g_trunk_compress_binlog_interval,
|
||||
g_trunk_compress_binlog_time_base.hour,
|
||||
|
|
|
|||
|
|
@ -64,6 +64,7 @@ bool g_if_trunker_self = false;
|
|||
bool g_trunk_create_file_advance = false;
|
||||
bool g_trunk_init_check_occupying = false;
|
||||
bool g_trunk_init_reload_from_binlog = false;
|
||||
bool g_trunk_free_space_merge = false;
|
||||
int g_trunk_binlog_compress_stage = STORAGE_TRUNK_COMPRESS_STAGE_NONE;
|
||||
int64_t g_trunk_total_free_space = 0;
|
||||
int64_t g_trunk_create_file_space_threshold = 0;
|
||||
|
|
@ -349,54 +350,141 @@ static int64_t storage_trunk_get_binlog_size()
|
|||
return stat_buf.st_size;
|
||||
}
|
||||
|
||||
struct trunk_info_array {
|
||||
FDFSTrunkFullInfo **trunks;
|
||||
int count;
|
||||
int alloc;
|
||||
};
|
||||
|
||||
struct walk_callback_args {
|
||||
int fd;
|
||||
char buff[16 * 1024];
|
||||
char temp_trunk_filename[MAX_PATH_SIZE];
|
||||
char *pCurrent;
|
||||
|
||||
struct trunk_info_array trunk_array; //for space combine
|
||||
};
|
||||
|
||||
static int tree_walk_callback(void *data, void *args)
|
||||
static int trunk_alloc_trunk_array(
|
||||
struct trunk_info_array *trunk_array)
|
||||
{
|
||||
int bytes;
|
||||
FDFSTrunkFullInfo **trunks;
|
||||
int alloc;
|
||||
|
||||
if (trunk_array->alloc == 0)
|
||||
{
|
||||
alloc = 64 * 1024;
|
||||
}
|
||||
else
|
||||
{
|
||||
alloc = trunk_array->alloc * 2;
|
||||
}
|
||||
|
||||
bytes = sizeof(FDFSTrunkFullInfo *) * alloc;
|
||||
trunks = (FDFSTrunkFullInfo **)malloc(bytes);
|
||||
if (trunks == NULL)
|
||||
{
|
||||
logError("file: "__FILE__", line: %d, "
|
||||
"malloc %d bytes fail", __LINE__, bytes);
|
||||
return ENOMEM;
|
||||
}
|
||||
|
||||
if (trunk_array->count > 0)
|
||||
{
|
||||
memcpy(trunks, trunk_array->trunks,
|
||||
sizeof(FDFSTrunkFullInfo *) *
|
||||
trunk_array->count);
|
||||
}
|
||||
|
||||
if (trunk_array->trunks != NULL)
|
||||
{
|
||||
free(trunk_array->trunks);
|
||||
}
|
||||
|
||||
trunk_array->trunks = trunks;
|
||||
trunk_array->alloc = alloc;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int save_one_trunk(struct walk_callback_args *pCallbackArgs,
|
||||
FDFSTrunkFullInfo *pTrunkInfo)
|
||||
{
|
||||
int len;
|
||||
int result;
|
||||
|
||||
len = sprintf(pCallbackArgs->pCurrent,
|
||||
"%d %c %d %d %d %d %d %d\n",
|
||||
(int)g_current_time, TRUNK_OP_TYPE_ADD_SPACE,
|
||||
pTrunkInfo->path.store_path_index,
|
||||
pTrunkInfo->path.sub_path_high,
|
||||
pTrunkInfo->path.sub_path_low,
|
||||
pTrunkInfo->file.id,
|
||||
pTrunkInfo->file.offset,
|
||||
pTrunkInfo->file.size);
|
||||
pCallbackArgs->pCurrent += len;
|
||||
if (pCallbackArgs->pCurrent - pCallbackArgs->buff >
|
||||
sizeof(pCallbackArgs->buff) - 128)
|
||||
{
|
||||
if (fc_safe_write(pCallbackArgs->fd, pCallbackArgs->buff,
|
||||
pCallbackArgs->pCurrent - pCallbackArgs->buff)
|
||||
!= pCallbackArgs->pCurrent - pCallbackArgs->buff)
|
||||
{
|
||||
result = errno != 0 ? errno : EIO;
|
||||
logError("file: "__FILE__", line: %d, "
|
||||
"write to file %s fail, "
|
||||
"errno: %d, error info: %s", __LINE__,
|
||||
pCallbackArgs->temp_trunk_filename,
|
||||
result, STRERROR(result));
|
||||
return result;
|
||||
}
|
||||
|
||||
pCallbackArgs->pCurrent = pCallbackArgs->buff;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tree_walk_callback_to_file(void *data, void *args)
|
||||
{
|
||||
struct walk_callback_args *pCallbackArgs;
|
||||
FDFSTrunkFullInfo *pTrunkInfo;
|
||||
FDFSTrunkNode *pCurrent;
|
||||
int len;
|
||||
int result;
|
||||
|
||||
pCallbackArgs = (struct walk_callback_args *)args;
|
||||
pCurrent = ((FDFSTrunkSlot *)data)->head;
|
||||
while (pCurrent != NULL)
|
||||
{
|
||||
pTrunkInfo = &pCurrent->trunk;
|
||||
len = sprintf(pCallbackArgs->pCurrent,
|
||||
"%d %c %d %d %d %d %d %d\n",
|
||||
(int)g_current_time, TRUNK_OP_TYPE_ADD_SPACE,
|
||||
pTrunkInfo->path.store_path_index,
|
||||
pTrunkInfo->path.sub_path_high,
|
||||
pTrunkInfo->path.sub_path_low,
|
||||
pTrunkInfo->file.id,
|
||||
pTrunkInfo->file.offset,
|
||||
pTrunkInfo->file.size);
|
||||
pCallbackArgs->pCurrent += len;
|
||||
if (pCallbackArgs->pCurrent - pCallbackArgs->buff >
|
||||
sizeof(pCallbackArgs->buff) - 128)
|
||||
{
|
||||
if (fc_safe_write(pCallbackArgs->fd, pCallbackArgs->buff,
|
||||
pCallbackArgs->pCurrent - pCallbackArgs->buff)
|
||||
!= pCallbackArgs->pCurrent - pCallbackArgs->buff)
|
||||
{
|
||||
result = errno != 0 ? errno : EIO;
|
||||
logError("file: "__FILE__", line: %d, "
|
||||
"write to file %s fail, "
|
||||
"errno: %d, error info: %s", __LINE__,
|
||||
pCallbackArgs->temp_trunk_filename,
|
||||
result, STRERROR(result));
|
||||
return result;
|
||||
}
|
||||
if ((result=save_one_trunk(pCallbackArgs, &pCurrent->trunk)) != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
pCurrent = pCurrent->next;
|
||||
}
|
||||
|
||||
pCallbackArgs->pCurrent = pCallbackArgs->buff;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int tree_walk_callback_to_list(void *data, void *args)
|
||||
{
|
||||
struct walk_callback_args *pCallbackArgs;
|
||||
FDFSTrunkNode *pCurrent;
|
||||
int result;
|
||||
|
||||
pCallbackArgs = (struct walk_callback_args *)args;
|
||||
pCurrent = ((FDFSTrunkSlot *)data)->head;
|
||||
while (pCurrent != NULL)
|
||||
{
|
||||
if (pCallbackArgs->trunk_array.count >= pCallbackArgs->trunk_array.alloc)
|
||||
{
|
||||
if ((result=trunk_alloc_trunk_array(
|
||||
&pCallbackArgs->trunk_array)) != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
pCallbackArgs->trunk_array.trunks[pCallbackArgs->trunk_array.
|
||||
count++] = &pCurrent->trunk;
|
||||
|
||||
pCurrent = pCurrent->next;
|
||||
}
|
||||
|
|
@ -404,6 +492,145 @@ static int tree_walk_callback(void *data, void *args)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int trunk_compare_id_offset(const void *p1, const void *p2)
|
||||
{
|
||||
FDFSTrunkFullInfo *pTrunkInfo1;
|
||||
FDFSTrunkFullInfo *pTrunkInfo2;
|
||||
int result;
|
||||
|
||||
pTrunkInfo1 = *((FDFSTrunkFullInfo **)p1);
|
||||
pTrunkInfo2 = *((FDFSTrunkFullInfo **)p2);
|
||||
|
||||
result = memcmp(&(pTrunkInfo1->path), &(pTrunkInfo2->path),
|
||||
sizeof(FDFSTrunkPathInfo));
|
||||
if (result != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
result = pTrunkInfo1->file.id - pTrunkInfo2->file.id;
|
||||
if (result != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return pTrunkInfo1->file.offset - pTrunkInfo2->file.offset;
|
||||
}
|
||||
|
||||
static int trunk_compare_path_and_id(const FDFSTrunkFullInfo *pTrunkInfo1,
|
||||
const FDFSTrunkFullInfo *pTrunkInfo2)
|
||||
{
|
||||
int result;
|
||||
|
||||
result = memcmp(&(pTrunkInfo1->path), &(pTrunkInfo2->path),
|
||||
sizeof(FDFSTrunkPathInfo));
|
||||
if (result != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
return pTrunkInfo1->file.id - pTrunkInfo2->file.id;
|
||||
}
|
||||
|
||||
static int trunk_save_merged_spaces(struct walk_callback_args *pCallbackArgs)
|
||||
{
|
||||
FDFSTrunkFullInfo **ppTrunkInfo;
|
||||
FDFSTrunkFullInfo **ppEnd;
|
||||
FDFSTrunkFullInfo **previous;
|
||||
FDFSTrunkFullInfo **ppMergeFirst;
|
||||
FDFSTrunkFullInfo trunk_info;
|
||||
FDFSTrunkFullInfo *pTrunkInfo;
|
||||
int merge_count;
|
||||
int merged_trunk_count;
|
||||
int64_t total_size;
|
||||
int64_t merged_size;
|
||||
int result;
|
||||
|
||||
if (pCallbackArgs->trunk_array.count == 0)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
qsort(pCallbackArgs->trunk_array.trunks, pCallbackArgs->trunk_array.
|
||||
count, sizeof(FDFSTrunkFullInfo *), trunk_compare_id_offset);
|
||||
|
||||
merge_count = 0;
|
||||
merged_trunk_count = 0;
|
||||
merged_size = 0;
|
||||
ppEnd = pCallbackArgs->trunk_array.trunks +
|
||||
pCallbackArgs->trunk_array.count;
|
||||
ppTrunkInfo = pCallbackArgs->trunk_array.trunks;
|
||||
ppMergeFirst = ppTrunkInfo;
|
||||
total_size = (*ppTrunkInfo)->file.size;
|
||||
while (++ppTrunkInfo < ppEnd)
|
||||
{
|
||||
total_size += (*ppTrunkInfo)->file.size;
|
||||
previous = ppTrunkInfo - 1;
|
||||
if (trunk_compare_path_and_id(*previous, *ppTrunkInfo) == 0 &&
|
||||
(*previous)->file.offset + (*previous)->file.size ==
|
||||
(*ppTrunkInfo)->file.offset)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (ppTrunkInfo - ppMergeFirst == 1)
|
||||
{
|
||||
pTrunkInfo = *ppMergeFirst;
|
||||
}
|
||||
else
|
||||
{
|
||||
pTrunkInfo = &trunk_info;
|
||||
memcpy(pTrunkInfo, *ppMergeFirst, sizeof(FDFSTrunkFullInfo));
|
||||
pTrunkInfo->file.size = (*ppTrunkInfo)->file.offset -
|
||||
(*ppMergeFirst)->file.offset;
|
||||
|
||||
merge_count++;
|
||||
merged_size += pTrunkInfo->file.size;
|
||||
merged_trunk_count += ppTrunkInfo - ppMergeFirst;
|
||||
}
|
||||
|
||||
if ((result=save_one_trunk(pCallbackArgs, pTrunkInfo)) != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
ppMergeFirst = ppTrunkInfo;
|
||||
ppTrunkInfo++;
|
||||
}
|
||||
|
||||
if (ppEnd - ppMergeFirst == 1)
|
||||
{
|
||||
pTrunkInfo = *ppMergeFirst;
|
||||
}
|
||||
else
|
||||
{
|
||||
FDFSTrunkFullInfo **ppLast;
|
||||
|
||||
pTrunkInfo = &trunk_info;
|
||||
ppLast = ppEnd - 1;
|
||||
memcpy(pTrunkInfo, *ppMergeFirst, sizeof(FDFSTrunkFullInfo));
|
||||
pTrunkInfo->file.size = (*ppLast)->file.offset -
|
||||
(*ppMergeFirst)->file.offset + (*ppLast)->file.size;
|
||||
|
||||
merge_count++;
|
||||
merged_size += pTrunkInfo->file.size;
|
||||
merged_trunk_count += ppEnd - ppMergeFirst;
|
||||
}
|
||||
|
||||
if ((result=save_one_trunk(pCallbackArgs, pTrunkInfo)) != 0)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
|
||||
logInfo("file: "__FILE__", line: %d, "
|
||||
"trunk count: %d, total_size: %"PRId64", merge count: %d, "
|
||||
"merged trunk count: %d, merged size: %"PRId64, __LINE__,
|
||||
pCallbackArgs->trunk_array.count, total_size,
|
||||
merge_count, merged_trunk_count, merged_size);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int do_save_trunk_data()
|
||||
{
|
||||
int64_t trunk_binlog_size;
|
||||
|
|
@ -445,14 +672,32 @@ static int do_save_trunk_data()
|
|||
pthread_mutex_lock(&trunk_mem_lock);
|
||||
for (i=0; i<g_fdfs_store_paths.count; i++)
|
||||
{
|
||||
result = avl_tree_walk(tree_info_by_sizes + i,
|
||||
tree_walk_callback, &callback_args);
|
||||
if (g_trunk_free_space_merge)
|
||||
{
|
||||
result = avl_tree_walk(tree_info_by_sizes + i,
|
||||
tree_walk_callback_to_list, &callback_args);
|
||||
}
|
||||
else
|
||||
{
|
||||
result = avl_tree_walk(tree_info_by_sizes + i,
|
||||
tree_walk_callback_to_file, &callback_args);
|
||||
}
|
||||
|
||||
if (result != 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_trunk_free_space_merge)
|
||||
{
|
||||
result = trunk_save_merged_spaces(&callback_args);
|
||||
if (callback_args.trunk_array.trunks != NULL)
|
||||
{
|
||||
free(callback_args.trunk_array.trunks);
|
||||
}
|
||||
}
|
||||
|
||||
len = callback_args.pCurrent - callback_args.buff;
|
||||
if (len > 0 && result == 0)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ extern bool g_if_use_trunk_file; //if use trunk file
|
|||
extern bool g_trunk_create_file_advance;
|
||||
extern bool g_trunk_init_check_occupying;
|
||||
extern bool g_trunk_init_reload_from_binlog;
|
||||
extern bool g_trunk_free_space_merge;
|
||||
extern int g_trunk_binlog_compress_stage;
|
||||
extern bool g_if_trunker_self; //if am i trunk server
|
||||
extern int64_t g_trunk_create_file_space_threshold;
|
||||
|
|
|
|||
|
|
@ -598,6 +598,9 @@ int tracker_load_from_conf_file(const char *filename, \
|
|||
g_trunk_init_reload_from_binlog = iniGetBoolValue(NULL,
|
||||
"trunk_init_reload_from_binlog", &iniContext, false);
|
||||
|
||||
g_trunk_free_space_merge = iniGetBoolValue(NULL,
|
||||
"trunk_free_space_merge", &iniContext, false);
|
||||
|
||||
if ((result=tracker_load_storage_id_info(
|
||||
filename, &iniContext)) != 0)
|
||||
{
|
||||
|
|
@ -775,6 +778,7 @@ int tracker_load_from_conf_file(const char *filename, \
|
|||
"trunk_create_file_space_threshold=%d GB, "
|
||||
"trunk_init_check_occupying=%d, "
|
||||
"trunk_init_reload_from_binlog=%d, "
|
||||
"trunk_free_space_merge=%d, "
|
||||
"trunk_compress_binlog_min_interval=%d, "
|
||||
"trunk_compress_binlog_interval=%d, "
|
||||
"trunk_compress_binlog_time_base=%02d:%02d, "
|
||||
|
|
@ -818,6 +822,7 @@ int tracker_load_from_conf_file(const char *filename, \
|
|||
(int)(g_trunk_create_file_space_threshold /
|
||||
(FDFS_ONE_MB * 1024)), g_trunk_init_check_occupying,
|
||||
g_trunk_init_reload_from_binlog,
|
||||
g_trunk_free_space_merge,
|
||||
g_trunk_compress_binlog_min_interval,
|
||||
g_trunk_compress_binlog_interval,
|
||||
g_trunk_compress_binlog_time_base.hour,
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ bool g_if_use_trunk_file = false; //if use trunk file
|
|||
bool g_trunk_create_file_advance = false;
|
||||
bool g_trunk_init_check_occupying = false;
|
||||
bool g_trunk_init_reload_from_binlog = false;
|
||||
bool g_trunk_free_space_merge = false;
|
||||
int g_slot_min_size = 256; //slot min size, such as 256 bytes
|
||||
int g_slot_max_size = 16 * 1024 * 1024; //slot max size, such as 16MB
|
||||
int g_trunk_file_size = 64 * 1024 * 1024; //the trunk file size, such as 64MB
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ extern bool g_if_use_trunk_file; //if use trunk file
|
|||
extern bool g_trunk_create_file_advance;
|
||||
extern bool g_trunk_init_check_occupying;
|
||||
extern bool g_trunk_init_reload_from_binlog;
|
||||
extern bool g_trunk_free_space_merge;
|
||||
extern int g_slot_min_size; //slot min size, such as 256 bytes
|
||||
extern int g_slot_max_size; //slot max size, such as 16MB
|
||||
extern int g_trunk_file_size; //the trunk file size, such as 64MB
|
||||
|
|
|
|||
|
|
@ -695,6 +695,7 @@ static int tracker_deal_parameter_req(struct fast_task_info *pTask)
|
|||
"trunk_create_file_space_threshold=%"PRId64"\n"
|
||||
"trunk_init_check_occupying=%d\n"
|
||||
"trunk_init_reload_from_binlog=%d\n"
|
||||
"trunk_free_space_merge=%d\n"
|
||||
"trunk_compress_binlog_min_interval=%d\n"
|
||||
"trunk_compress_binlog_interval=%d\n"
|
||||
"trunk_compress_binlog_time_base=%02d:%02d\n"
|
||||
|
|
@ -716,6 +717,7 @@ static int tracker_deal_parameter_req(struct fast_task_info *pTask)
|
|||
g_trunk_create_file_space_threshold,
|
||||
g_trunk_init_check_occupying,
|
||||
g_trunk_init_reload_from_binlog,
|
||||
g_trunk_free_space_merge,
|
||||
g_trunk_compress_binlog_min_interval,
|
||||
g_trunk_compress_binlog_interval,
|
||||
g_trunk_compress_binlog_time_base.hour,
|
||||
|
|
|
|||
Loading…
Reference in New Issue