diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..458784e --- /dev/null +++ b/.gitignore @@ -0,0 +1,106 @@ +# Makefile.in +storage/Makefile +tracker/Makefile +client/test/Makefile +client/Makefile + +# client/fdfs_link_library.sh.in +client/fdfs_link_library.sh + +# Prerequisites +*.d + +# Compiled Object files +*.slo +*.lo +*.o +*.obj + +# Precompiled Headers +*.gch +*.pch + +# Compiled Dynamic libraries +*.so +*.dylib +*.dSYM +*.dll + +# Fortran module files +*.mod +*.smod + +# Compiled Static libraries +*.lai +*.la +*.a +*.lib + +# Executables +*.exe +*.out +*.app +client/fdfs_append_file +client/fdfs_appender_test +client/fdfs_appender_test1 +client/fdfs_crc32 +client/fdfs_delete_file +client/fdfs_download_file +client/fdfs_file_info +client/fdfs_monitor +client/fdfs_test +client/fdfs_test1 +client/fdfs_upload_appender +client/fdfs_upload_file +client/fdfs_regenerate_filename +client/test/fdfs_monitor +client/test/fdfs_test +client/test/fdfs_test1 +storage/fdfs_storaged +tracker/fdfs_trackerd +test/combine_result +test/100M +test/10M +test/1M +test/200K +test/50K +test/5K +test/gen_files +test/test_delete +test/test_download +test/test_upload +test/upload/ +test/download/ +test/delete/ + +# other +php_client/.deps +php_client/.libs/ + +php_client/Makefile +php_client/Makefile.fragments +php_client/Makefile.global +php_client/Makefile.objects +php_client/acinclude.m4 +php_client/aclocal.m4 +php_client/autom4te.cache/ +php_client/build/ +php_client/config.guess +php_client/config.h +php_client/config.h.in +php_client/config.log +php_client/config.nice +php_client/config.status +php_client/config.sub +php_client/configure +php_client/configure.ac +php_client/install-sh +php_client/libtool +php_client/ltmain.sh +php_client/missing +php_client/mkinstalldirs +php_client/run-tests.php + +# fastdfs runtime paths +data/ +logs/ diff --git a/HISTORY b/HISTORY index b03e0e2..a51c7d4 100644 --- a/HISTORY +++ b/HISTORY @@ -1,7 +1,88 @@ +Version 6.07 2020-09-30 + * use libfastcommon V1.44 + NOTE: you MUST upgrade libfastcommon to V1.44 or later + * correct spell iovent to ioevent follows libfastcommon + +Version 6.06 2019-12-30 + * bugfixed: fdfs_storaged can't quit normally + * bugfixed: init/memset return ip address to ascii 0 for Java SDK + +Version 6.05 2019-12-25 + * 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 + + * trunk server support compress the trunk binlog periodically, + the config items in tracker.conf: trunk_compress_binlog_interval + and trunk_compress_binlog_time_base + + * trunk binlog compression support transaction + + * 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 + the config item in tracker.conf: trunk_alloc_alignment_size + + * support merge free trunk spaces + the config item in tracker.conf: trunk_free_space_merge + + * support delete unused trunk files + the config item in tracker.conf: delete_unused_trunk_files + + * fdfs_monitor.c: do NOT call getHostnameByIp + + NOTE: you MUST upgrade libfastcommon to V1.43 or later + + +Version 6.04 2019-12-05 + * storage_report_ip_changed ignore result EEXIST + * use get_gzip_command_filename from libfastcommon v1.42 + * support compress error log and access log + * disk recovery support multi-threads to speed up + * bugfix: should use memset to init pReader in function + storage_reader_init, this bug is caused by v6.01 + + NOTE: you MUST upgrade libfastcommon to V1.42 or later + + +Version 6.03 2019-11-20 + * dual IPs support two different types of inner (intranet) IPs + * storage server request tracker server to change it's status + to that of tracker leader when the storage server found + it's status inconsistence + * bugfix: fdfs_monitor fix get index of the specified tracker server + * storage server write to data_init_flag and mark file safely + (write to temp file then rename) + * code refine: combine g_fdfs_store_paths and g_path_space_list, + and extent struct FDFSStorePathInfo + * check store path's mark file to prevent confusion + * new selected tracker leader do NOT notify self by network + * larger network_timeout for fetching one-store-path binlog + when disk recovery + + NOTE: the tracker and storage server must upgrade together + + +Version 6.02 2019-11-12 + * get_file_info calculate CRC32 for appender file type + * disk recovery download file to local temp file then rename it + when the local file exists + * support regenerate filename for appender file + NOTE: the regenerated file will be a normal file! + + +Version 6.01 2019-10-25 + * compress and uncompress binlog file by gzip when need, + config items in storage.conf: compress_binlog and compress_binlog_time + * bugfix: must check and create data path before write_to_pid_file + in fdfs_storaged.c + + Version 6.00 2019-10-16 * tracker and storage server support dual IPs - 1. you can config dual trackr IPs in storage.conf and client.conf, + 1. you can config dual tracker IPs in storage.conf and client.conf, the configuration item name is "tracker_server" 2. you can config dual storage IPs in storage_ids.conf more detail please see the config files. @@ -14,6 +95,7 @@ Version 6.00 2019-10-16 * tracker server check tracker list when storage server join * use socketCreateExAuto and socketClientExAuto exported by libfastcommon + Version 5.12 2018-06-07 * code refine for rare case * replace print format OFF_PRINTF_FORMAT to PRId64 diff --git a/INSTALL b/INSTALL index 36e452f..3ebb522 100644 --- a/INSTALL +++ b/INSTALL @@ -3,50 +3,68 @@ Copy right 2009 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 for more detail. -English language: http://english.csource.org/ -Chinese language: http://www.csource.org/ +Chinese language: http://www.fastken.com/ -#step 1. download libfastcommon source package from github and install it, - the github address: - https://github.com/happyfish100/libfastcommon.git +# step 1. download libfastcommon source codes and install it, +# github address: https://github.com/happyfish100/libfastcommon.git +# gitee address: https://gitee.com/fastdfs100/libfastcommon.git +# command lines as: -#step 2. download FastDFS source package and unpack it, -tar xzf FastDFS_v5.x.tar.gz -#for example: -tar xzf FastDFS_v5.08.tar.gz + git clone https://github.com/happyfish100/libfastcommon.git + cd libfastcommon; git checkout V1.0.43 + ./make.sh clean && ./make.sh && ./make.sh install -#step 3. enter the FastDFS dir -cd FastDFS -#step 4. execute: -./make.sh +# step 2. download fastdfs source codes and install it, +# github address: https://github.com/happyfish100/fastdfs.git +# gitee address: https://gitee.com/fastdfs100/fastdfs.git +# command lines as: -#step 5. make install -./make.sh install + git clone https://github.com/happyfish100/fastdfs.git + cd fastdfs; git checkout V6.06 + ./make.sh clean && ./make.sh && ./make.sh install -#step 6. edit/modify the config file of tracker and storage -#step 7. run server programs -#start the tracker server: +# step 3. setup the config files +# the setup script does NOT overwrite existing config files, +# please feel free to execute this script (take easy :) + +./setup.sh /etc/fdfs + + +# step 4. edit or modify the config files of tracker, storage and client +such as: + vi /etc/fdfs/tracker.conf + vi /etc/fdfs/storage.conf + vi /etc/fdfs/client.conf + + and so on ... + + +# step 5. run the server programs +# start the tracker server: /usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf restart -#in Linux, you can start fdfs_trackerd as a service: -/sbin/service fdfs_trackerd start -#start the storage server: +# start the storage server: /usr/bin/fdfs_storaged /etc/fdfs/storage.conf restart -#in Linux, you can start fdfs_storaged as a service: -/sbin/service fdfs_storaged start -#step 8. run test program -#run the client test program: +# (optional) in Linux, you can start fdfs_trackerd and fdfs_storaged as a service: +/sbin/service fdfs_trackerd restart +/sbin/service fdfs_storaged restart + + +# step 6. (optional) run monitor program +# such as: +/usr/bin/fdfs_monitor /etc/fdfs/client.conf + + +# step 7. (optional) run the test program +# such as: /usr/bin/fdfs_test /usr/bin/fdfs_test1 -#for example, upload a file: -/usr/bin/fdfs_test conf/client.conf upload /usr/include/stdlib.h -#step 9. run monitor program -#run the monitor program: -/usr/bin/fdfs_monitor +# for example, upload a file for test: +/usr/bin/fdfs_test /etc/fdfs/client.conf upload /usr/include/stdlib.h tracker server config file sample please see conf/tracker.conf @@ -55,7 +73,6 @@ storage server config file sample please see conf/storage.conf client config file sample please see conf/client.conf - Item detail 1. server common items --------------------------------------------------- diff --git a/README.md b/README.md index 5aa4cee..63db25f 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,7 @@ 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 for more detail. -English language: http://english.csource.org/ -Chinese language: http://www.csource.org/ +Chinese language: http://www.fastken.com/ FastDFS is an open source high performance distributed file system. It's major @@ -42,3 +41,6 @@ The identification of a file is composed of two parts: the volume name and the file name. Client test code use client library please refer to the directory: client/test. + +For more FastDFS related articles, please subscribe the Wechat/Weixin public account +(Chinese Language): fastdfs diff --git a/README_zh.md b/README_zh.md new file mode 100644 index 0000000..95a434f --- /dev/null +++ b/README_zh.md @@ -0,0 +1,20 @@ + FastDFS是一款开源的分布式文件系统,功能主要包括:文件存储、文件同步、文件访问(文件上传、文件下载)等,解决了文件大容量存储和高性能访问的问题。FastDFS特别适合以文件为载体的在线服务,如图片、视频、文档等等。 + + FastDFS作为一款轻量级分布式文件系统,版本V6.01代码量6.3万行。FastDFS用C语言实现,支持Linux、FreeBSD、MacOS等类UNIX系统。FastDFS类似google FS,属于应用级文件系统,不是通用的文件系统,只能通过专有API访问,目前提供了C和Java SDK,以及PHP扩展SDK。 + + FastDFS为互联网应用量身定做,解决大容量文件存储问题,追求高性能和高扩展性。FastDFS可以看做是基于文件的key value存储系统,key为文件ID,value为文件内容,因此称作分布式文件存储服务更为合适。 + + FastDFS的架构比较简单,如下图所示: + ![architect](images/architect.png) + + FastDFS特点如下: + 1)分组存储,简单灵活; + 2)对等结构,不存在单点; + 3)文件ID由FastDFS生成,作为文件访问凭证。FastDFS不需要传统的name server或meta server; + 4)大、中、小文件均可以很好支持,可以存储海量小文件; + 5)一台storage支持多块磁盘,支持单盘数据恢复; + 6)提供了nginx扩展模块,可以和nginx无缝衔接; + 7)支持多线程方式上传和下载文件,支持断点续传; + 8)存储服务器上可以保存文件附加属性。 + + FastDFS更多更详细的功能和特性介绍,请参阅FastDFS微信公众号的其他文章,搜索公众号:fastdfs。 diff --git a/client/Makefile.in b/client/Makefile.in index 859b8b8..91d3da3 100644 --- a/client/Makefile.in +++ b/client/Makefile.in @@ -6,7 +6,7 @@ ENABLE_SHARED_LIB = $(ENABLE_SHARED_LIB) INC_PATH = -I../common -I../tracker -I/usr/include/fastcommon LIB_PATH = $(LIBS) -lfastcommon TARGET_PATH = $(TARGET_PREFIX)/bin -TARGET_LIB = $(TARGET_PREFIX)/lib64 +TARGET_LIB = $(TARGET_PREFIX)/$(LIB_VERSION) TARGET_INC = $(TARGET_PREFIX)/include CONFIG_PATH = $(TARGET_CONF_PATH) @@ -39,7 +39,7 @@ ALL_OBJS = $(STATIC_OBJS) $(FDFS_SHARED_OBJS) ALL_PRGS = fdfs_monitor fdfs_test fdfs_test1 fdfs_crc32 fdfs_upload_file \ fdfs_download_file fdfs_delete_file fdfs_file_info \ fdfs_appender_test fdfs_appender_test1 fdfs_append_file \ - fdfs_upload_appender + fdfs_upload_appender fdfs_regenerate_filename STATIC_LIBS = libfdfsclient.a diff --git a/client/client_func.c b/client/client_func.c index 1b8fe05..610abf2 100644 --- a/client/client_func.c +++ b/client/client_func.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //client_func.c diff --git a/client/client_func.h b/client/client_func.h index 01c338c..e0f317e 100644 --- a/client/client_func.h +++ b/client/client_func.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //client_func.h @@ -16,6 +16,8 @@ #define _CLIENT_FUNC_H_ typedef struct { + short file_type; + bool get_from_server; time_t create_timestamp; int crc32; int source_id; //source storage id diff --git a/client/client_global.c b/client/client_global.c index 19964b4..fa2553c 100644 --- a/client/client_global.c +++ b/client/client_global.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include diff --git a/client/client_global.h b/client/client_global.h index 35f5818..5c72442 100644 --- a/client/client_global.h +++ b/client/client_global.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //client_global.h diff --git a/client/fdfs_append_file.c b/client/fdfs_append_file.c index 39f9b73..1b1e451 100644 --- a/client/fdfs_append_file.c +++ b/client/fdfs_append_file.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include diff --git a/client/fdfs_appender_test.c b/client/fdfs_appender_test.c index 13821fb..f49e0be 100644 --- a/client/fdfs_appender_test.c +++ b/client/fdfs_appender_test.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include @@ -83,7 +83,7 @@ int main(int argc, char *argv[]) "\nCopyright (C) 2008, Happy Fish / YuQing\n" \ "\nFastDFS may be copied only under the terms of the GNU General\n" \ "Public License V3, which may be found in the FastDFS source kit.\n" \ -"Please visit the FastDFS Home Page http://www.csource.org/ \n" \ +"Please visit the FastDFS Home Page http://www.fastken.com/ \n" \ "for more detail.\n\n" \ , g_fdfs_version.major, g_fdfs_version.minor); diff --git a/client/fdfs_appender_test1.c b/client/fdfs_appender_test1.c index e713053..7fb0f22 100644 --- a/client/fdfs_appender_test1.c +++ b/client/fdfs_appender_test1.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include @@ -82,7 +82,7 @@ int main(int argc, char *argv[]) "\nCopyright (C) 2008, Happy Fish / YuQing\n" \ "\nFastDFS may be copied only under the terms of the GNU General\n" \ "Public License V3, which may be found in the FastDFS source kit.\n" \ -"Please visit the FastDFS Home Page http://www.csource.org/ \n" \ +"Please visit the FastDFS Home Page http://www.fastken.com/ \n" \ "for more detail.\n\n" \ , g_fdfs_version.major, g_fdfs_version.minor); diff --git a/client/fdfs_client.h b/client/fdfs_client.h index aaf9a39..d77b165 100644 --- a/client/fdfs_client.h +++ b/client/fdfs_client.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #ifndef FDFS_CLIENT_H diff --git a/client/fdfs_crc32.c b/client/fdfs_crc32.c index 7de0e9e..94b1d9f 100644 --- a/client/fdfs_crc32.c +++ b/client/fdfs_crc32.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include diff --git a/client/fdfs_delete_file.c b/client/fdfs_delete_file.c index 83636ab..7d9369c 100644 --- a/client/fdfs_delete_file.c +++ b/client/fdfs_delete_file.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include diff --git a/client/fdfs_download_file.c b/client/fdfs_download_file.c index 331ed2d..7cf5f93 100644 --- a/client/fdfs_download_file.c +++ b/client/fdfs_download_file.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include diff --git a/client/fdfs_file_info.c b/client/fdfs_file_info.c index 2e153ad..0d2a49d 100644 --- a/client/fdfs_file_info.c +++ b/client/fdfs_file_info.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include @@ -19,6 +19,7 @@ int main(int argc, char *argv[]) { char *conf_filename; + const char *file_type_str; char file_id[128]; int result; FDFSFileInfo file_info; @@ -44,7 +45,7 @@ int main(int argc, char *argv[]) result = fdfs_get_file_info_ex1(file_id, true, &file_info); if (result != 0) { - printf("query file info fail, " \ + fprintf(stderr, "query file info fail, " \ "error no: %d, error info: %s\n", \ result, STRERROR(result)); } @@ -52,6 +53,25 @@ int main(int argc, char *argv[]) { char szDatetime[32]; + switch (file_info.file_type) + { + case FDFS_FILE_TYPE_NORMAL: + file_type_str = "normal"; + break; + case FDFS_FILE_TYPE_SLAVE: + file_type_str = "slave"; + break; + case FDFS_FILE_TYPE_APPENDER: + file_type_str = "appender"; + break; + default: + file_type_str = "unkown"; + break; + } + + printf("GET FROM SERVER: %s\n\n", + file_info.get_from_server ? "true" : "false"); + printf("file type: %s\n", file_type_str); printf("source storage id: %d\n", file_info.source_id); printf("source ip address: %s\n", file_info.source_ip_addr); printf("file create timestamp: %s\n", formatDatetime( @@ -59,7 +79,7 @@ int main(int argc, char *argv[]) szDatetime, sizeof(szDatetime))); printf("file size: %"PRId64"\n", \ file_info.file_size); - printf("file crc32: %u (0x%08X)\n", \ + printf("file crc32: %d (0x%08x)\n", \ file_info.crc32, file_info.crc32); } diff --git a/client/fdfs_monitor.c b/client/fdfs_monitor.c index 67afd9f..f97b484 100644 --- a/client/fdfs_monitor.c +++ b/client/fdfs_monitor.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include @@ -131,9 +131,9 @@ int main(int argc, char *argv[]) for (i=0; igroup_name, \ - pGroupStat->total_mb, \ - pGroupStat->free_mb, \ - pGroupStat->trunk_free_mb, \ - pGroupStat->count, \ - pGroupStat->active_count, \ - pGroupStat->storage_port, \ - pGroupStat->storage_http_port, \ - pGroupStat->store_path_count, \ - pGroupStat->subdir_count_per_path, \ - pGroupStat->current_write_server, \ + printf( "group name = %s\n" + "disk total space = %s MB\n" + "disk free space = %s MB\n" + "trunk free space = %s MB\n" + "storage server count = %d\n" + "active server count = %d\n" + "storage server port = %d\n" + "storage HTTP port = %d\n" + "store path count = %d\n" + "subdir count per path = %d\n" + "current write server index = %d\n" + "current trunk file id = %d\n\n", + pGroupStat->group_name, + long_to_comma_str(pGroupStat->total_mb, szDiskTotalSpace), + long_to_comma_str(pGroupStat->free_mb, szDiskFreeSpace), + long_to_comma_str(pGroupStat->trunk_free_mb, szTrunkSpace), + pGroupStat->count, + pGroupStat->active_count, + pGroupStat->storage_port, + pGroupStat->storage_http_port, + pGroupStat->store_path_count, + pGroupStat->subdir_count_per_path, + pGroupStat->current_write_server, pGroupStat->current_trunk_file_id ); @@ -352,8 +355,12 @@ static int list_storages(FDFSGroupStat *pGroupStat) int second; char szDelayTime[64]; - delay_seconds = (int)(max_last_source_update - \ + delay_seconds = (int)(max_last_source_update - pStorageStat->last_synced_timestamp); + if (delay_seconds < 0) + { + delay_seconds = 0; + } day = delay_seconds / (24 * 3600); remain_seconds = delay_seconds % (24 * 3600); hour = remain_seconds / 3600; @@ -385,7 +392,8 @@ static int list_storages(FDFSGroupStat *pGroupStat) } } - getHostnameByIp(pStorage->ip_addr, szHostname, sizeof(szHostname)); + //getHostnameByIp(pStorage->ip_addr, szHostname, sizeof(szHostname)); + *szHostname = '\0'; if (*szHostname != '\0') { sprintf(szHostnamePrompt, " (%s)", szHostname); @@ -406,138 +414,138 @@ static int list_storages(FDFSGroupStat *pGroupStat) *szUpTime = '\0'; } - printf( "\tStorage %d:\n" \ - "\t\tid = %s\n" \ - "\t\tip_addr = %s%s %s\n" \ - "\t\thttp domain = %s\n" \ - "\t\tversion = %s\n" \ - "\t\tjoin time = %s\n" \ - "\t\tup time = %s\n" \ - "\t\ttotal storage = %d MB\n" \ - "\t\tfree storage = %d MB\n" \ - "\t\tupload priority = %d\n" \ - "\t\tstore_path_count = %d\n" \ - "\t\tsubdir_count_per_path = %d\n" \ - "\t\tstorage_port = %d\n" \ - "\t\tstorage_http_port = %d\n" \ - "\t\tcurrent_write_path = %d\n" \ - "\t\tsource storage id = %s\n" \ - "\t\tif_trunk_server = %d\n" \ - "\t\tconnection.alloc_count = %d\n" \ - "\t\tconnection.current_count = %d\n" \ - "\t\tconnection.max_count = %d\n" \ - "\t\ttotal_upload_count = %"PRId64"\n" \ - "\t\tsuccess_upload_count = %"PRId64"\n" \ - "\t\ttotal_append_count = %"PRId64"\n" \ - "\t\tsuccess_append_count = %"PRId64"\n" \ - "\t\ttotal_modify_count = %"PRId64"\n" \ - "\t\tsuccess_modify_count = %"PRId64"\n" \ - "\t\ttotal_truncate_count = %"PRId64"\n" \ - "\t\tsuccess_truncate_count = %"PRId64"\n" \ - "\t\ttotal_set_meta_count = %"PRId64"\n" \ - "\t\tsuccess_set_meta_count = %"PRId64"\n" \ - "\t\ttotal_delete_count = %"PRId64"\n" \ - "\t\tsuccess_delete_count = %"PRId64"\n" \ - "\t\ttotal_download_count = %"PRId64"\n" \ - "\t\tsuccess_download_count = %"PRId64"\n" \ - "\t\ttotal_get_meta_count = %"PRId64"\n" \ - "\t\tsuccess_get_meta_count = %"PRId64"\n" \ - "\t\ttotal_create_link_count = %"PRId64"\n" \ - "\t\tsuccess_create_link_count = %"PRId64"\n"\ - "\t\ttotal_delete_link_count = %"PRId64"\n" \ - "\t\tsuccess_delete_link_count = %"PRId64"\n" \ - "\t\ttotal_upload_bytes = %"PRId64"\n" \ - "\t\tsuccess_upload_bytes = %"PRId64"\n" \ - "\t\ttotal_append_bytes = %"PRId64"\n" \ - "\t\tsuccess_append_bytes = %"PRId64"\n" \ - "\t\ttotal_modify_bytes = %"PRId64"\n" \ - "\t\tsuccess_modify_bytes = %"PRId64"\n" \ - "\t\tstotal_download_bytes = %"PRId64"\n" \ - "\t\tsuccess_download_bytes = %"PRId64"\n" \ - "\t\ttotal_sync_in_bytes = %"PRId64"\n" \ - "\t\tsuccess_sync_in_bytes = %"PRId64"\n" \ - "\t\ttotal_sync_out_bytes = %"PRId64"\n" \ - "\t\tsuccess_sync_out_bytes = %"PRId64"\n" \ - "\t\ttotal_file_open_count = %"PRId64"\n" \ - "\t\tsuccess_file_open_count = %"PRId64"\n" \ - "\t\ttotal_file_read_count = %"PRId64"\n" \ - "\t\tsuccess_file_read_count = %"PRId64"\n" \ - "\t\ttotal_file_write_count = %"PRId64"\n" \ - "\t\tsuccess_file_write_count = %"PRId64"\n" \ - "\t\tlast_heart_beat_time = %s\n" \ - "\t\tlast_source_update = %s\n" \ - "\t\tlast_sync_update = %s\n" \ - "\t\tlast_synced_timestamp = %s %s\n", \ - ++k, pStorage->id, pStorage->ip_addr, \ - szHostnamePrompt, get_storage_status_caption( \ - pStorage->status), pStorage->domain_name, \ - pStorage->version, \ - formatDatetime(pStorage->join_time, \ - "%Y-%m-%d %H:%M:%S", \ - szJoinTime, sizeof(szJoinTime)), \ - szUpTime, pStorage->total_mb, \ - pStorage->free_mb, \ - pStorage->upload_priority, \ - pStorage->store_path_count, \ - pStorage->subdir_count_per_path, \ - pStorage->storage_port, \ - pStorage->storage_http_port, \ - pStorage->current_write_path, \ - pStorage->src_id, \ - pStorage->if_trunk_server, \ - pStorageStat->connection.alloc_count, \ - pStorageStat->connection.current_count, \ - pStorageStat->connection.max_count, \ - pStorageStat->total_upload_count, \ - pStorageStat->success_upload_count, \ - pStorageStat->total_append_count, \ - pStorageStat->success_append_count, \ - pStorageStat->total_modify_count, \ - pStorageStat->success_modify_count, \ - pStorageStat->total_truncate_count, \ - pStorageStat->success_truncate_count, \ - pStorageStat->total_set_meta_count, \ - pStorageStat->success_set_meta_count, \ - pStorageStat->total_delete_count, \ - pStorageStat->success_delete_count, \ - pStorageStat->total_download_count, \ - pStorageStat->success_download_count, \ - pStorageStat->total_get_meta_count, \ - pStorageStat->success_get_meta_count, \ - pStorageStat->total_create_link_count, \ - pStorageStat->success_create_link_count, \ - pStorageStat->total_delete_link_count, \ - pStorageStat->success_delete_link_count, \ - pStorageStat->total_upload_bytes, \ - pStorageStat->success_upload_bytes, \ - pStorageStat->total_append_bytes, \ - pStorageStat->success_append_bytes, \ - pStorageStat->total_modify_bytes, \ - pStorageStat->success_modify_bytes, \ - pStorageStat->total_download_bytes, \ - pStorageStat->success_download_bytes, \ - pStorageStat->total_sync_in_bytes, \ - pStorageStat->success_sync_in_bytes, \ - pStorageStat->total_sync_out_bytes, \ - pStorageStat->success_sync_out_bytes, \ - pStorageStat->total_file_open_count, \ - pStorageStat->success_file_open_count, \ - pStorageStat->total_file_read_count, \ - pStorageStat->success_file_read_count, \ - pStorageStat->total_file_write_count, \ - pStorageStat->success_file_write_count, \ - formatDatetime(pStorageStat->last_heart_beat_time, \ - "%Y-%m-%d %H:%M:%S", \ - szLastHeartBeatTime, sizeof(szLastHeartBeatTime)), \ - formatDatetime(pStorageStat->last_source_update, \ - "%Y-%m-%d %H:%M:%S", \ - szSrcUpdTime, sizeof(szSrcUpdTime)), \ - formatDatetime(pStorageStat->last_sync_update, \ - "%Y-%m-%d %H:%M:%S", \ - szSyncUpdTime, sizeof(szSyncUpdTime)), \ - formatDatetime(pStorageStat->last_synced_timestamp, \ - "%Y-%m-%d %H:%M:%S", \ - szSyncedTimestamp, sizeof(szSyncedTimestamp)),\ + printf( "\tStorage %d:\n" + "\t\tid = %s\n" + "\t\tip_addr = %s%s %s\n" + "\t\thttp domain = %s\n" + "\t\tversion = %s\n" + "\t\tjoin time = %s\n" + "\t\tup time = %s\n" + "\t\ttotal storage = %s MB\n" + "\t\tfree storage = %s MB\n" + "\t\tupload priority = %d\n" + "\t\tstore_path_count = %d\n" + "\t\tsubdir_count_per_path = %d\n" + "\t\tstorage_port = %d\n" + "\t\tstorage_http_port = %d\n" + "\t\tcurrent_write_path = %d\n" + "\t\tsource storage id = %s\n" + "\t\tif_trunk_server = %d\n" + "\t\tconnection.alloc_count = %d\n" + "\t\tconnection.current_count = %d\n" + "\t\tconnection.max_count = %d\n" + "\t\ttotal_upload_count = %"PRId64"\n" + "\t\tsuccess_upload_count = %"PRId64"\n" + "\t\ttotal_append_count = %"PRId64"\n" + "\t\tsuccess_append_count = %"PRId64"\n" + "\t\ttotal_modify_count = %"PRId64"\n" + "\t\tsuccess_modify_count = %"PRId64"\n" + "\t\ttotal_truncate_count = %"PRId64"\n" + "\t\tsuccess_truncate_count = %"PRId64"\n" + "\t\ttotal_set_meta_count = %"PRId64"\n" + "\t\tsuccess_set_meta_count = %"PRId64"\n" + "\t\ttotal_delete_count = %"PRId64"\n" + "\t\tsuccess_delete_count = %"PRId64"\n" + "\t\ttotal_download_count = %"PRId64"\n" + "\t\tsuccess_download_count = %"PRId64"\n" + "\t\ttotal_get_meta_count = %"PRId64"\n" + "\t\tsuccess_get_meta_count = %"PRId64"\n" + "\t\ttotal_create_link_count = %"PRId64"\n" + "\t\tsuccess_create_link_count = %"PRId64"\n" + "\t\ttotal_delete_link_count = %"PRId64"\n" + "\t\tsuccess_delete_link_count = %"PRId64"\n" + "\t\ttotal_upload_bytes = %"PRId64"\n" + "\t\tsuccess_upload_bytes = %"PRId64"\n" + "\t\ttotal_append_bytes = %"PRId64"\n" + "\t\tsuccess_append_bytes = %"PRId64"\n" + "\t\ttotal_modify_bytes = %"PRId64"\n" + "\t\tsuccess_modify_bytes = %"PRId64"\n" + "\t\tstotal_download_bytes = %"PRId64"\n" + "\t\tsuccess_download_bytes = %"PRId64"\n" + "\t\ttotal_sync_in_bytes = %"PRId64"\n" + "\t\tsuccess_sync_in_bytes = %"PRId64"\n" + "\t\ttotal_sync_out_bytes = %"PRId64"\n" + "\t\tsuccess_sync_out_bytes = %"PRId64"\n" + "\t\ttotal_file_open_count = %"PRId64"\n" + "\t\tsuccess_file_open_count = %"PRId64"\n" + "\t\ttotal_file_read_count = %"PRId64"\n" + "\t\tsuccess_file_read_count = %"PRId64"\n" + "\t\ttotal_file_write_count = %"PRId64"\n" + "\t\tsuccess_file_write_count = %"PRId64"\n" + "\t\tlast_heart_beat_time = %s\n" + "\t\tlast_source_update = %s\n" + "\t\tlast_sync_update = %s\n" + "\t\tlast_synced_timestamp = %s %s\n", + ++k, pStorage->id, pStorage->ip_addr, + szHostnamePrompt, get_storage_status_caption( + pStorage->status), pStorage->domain_name, + pStorage->version, + formatDatetime(pStorage->join_time, + "%Y-%m-%d %H:%M:%S", + szJoinTime, sizeof(szJoinTime)), szUpTime, + long_to_comma_str(pStorage->total_mb, szDiskTotalSpace), + long_to_comma_str(pStorage->free_mb, szDiskFreeSpace), + pStorage->upload_priority, + pStorage->store_path_count, + pStorage->subdir_count_per_path, + pStorage->storage_port, + pStorage->storage_http_port, + pStorage->current_write_path, + pStorage->src_id, + pStorage->if_trunk_server, + pStorageStat->connection.alloc_count, + pStorageStat->connection.current_count, + pStorageStat->connection.max_count, + pStorageStat->total_upload_count, + pStorageStat->success_upload_count, + pStorageStat->total_append_count, + pStorageStat->success_append_count, + pStorageStat->total_modify_count, + pStorageStat->success_modify_count, + pStorageStat->total_truncate_count, + pStorageStat->success_truncate_count, + pStorageStat->total_set_meta_count, + pStorageStat->success_set_meta_count, + pStorageStat->total_delete_count, + pStorageStat->success_delete_count, + pStorageStat->total_download_count, + pStorageStat->success_download_count, + pStorageStat->total_get_meta_count, + pStorageStat->success_get_meta_count, + pStorageStat->total_create_link_count, + pStorageStat->success_create_link_count, + pStorageStat->total_delete_link_count, + pStorageStat->success_delete_link_count, + pStorageStat->total_upload_bytes, + pStorageStat->success_upload_bytes, + pStorageStat->total_append_bytes, + pStorageStat->success_append_bytes, + pStorageStat->total_modify_bytes, + pStorageStat->success_modify_bytes, + pStorageStat->total_download_bytes, + pStorageStat->success_download_bytes, + pStorageStat->total_sync_in_bytes, + pStorageStat->success_sync_in_bytes, + pStorageStat->total_sync_out_bytes, + pStorageStat->success_sync_out_bytes, + pStorageStat->total_file_open_count, + pStorageStat->success_file_open_count, + pStorageStat->total_file_read_count, + pStorageStat->success_file_read_count, + pStorageStat->total_file_write_count, + pStorageStat->success_file_write_count, + formatDatetime(pStorageStat->last_heart_beat_time, + "%Y-%m-%d %H:%M:%S", + szLastHeartBeatTime, sizeof(szLastHeartBeatTime)), + formatDatetime(pStorageStat->last_source_update, + "%Y-%m-%d %H:%M:%S", + szSrcUpdTime, sizeof(szSrcUpdTime)), + formatDatetime(pStorageStat->last_sync_update, + "%Y-%m-%d %H:%M:%S", + szSyncUpdTime, sizeof(szSyncUpdTime)), + formatDatetime(pStorageStat->last_synced_timestamp, + "%Y-%m-%d %H:%M:%S", + szSyncedTimestamp, sizeof(szSyncedTimestamp)), szSyncedDelaySeconds); } diff --git a/client/fdfs_regenerate_filename.c b/client/fdfs_regenerate_filename.c new file mode 100644 index 0000000..e3a19d7 --- /dev/null +++ b/client/fdfs_regenerate_filename.c @@ -0,0 +1,68 @@ +/** +* 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 +#include +#include +#include +#include +#include +#include +#include "fdfs_client.h" +#include "fastcommon/logger.h" + +int main(int argc, char *argv[]) +{ + char *conf_filename; + ConnectionInfo *pTrackerServer; + int result; + char appender_file_id[128]; + char new_file_id[128]; + + if (argc < 3) + { + fprintf(stderr, "regenerate filename for the appender file.\n" + "NOTE: the regenerated file will be a normal file!\n" + "Usage: %s \n", + argv[0]); + return 1; + } + + log_init(); + g_log_context.log_level = LOG_ERR; + + conf_filename = argv[1]; + if ((result=fdfs_client_init(conf_filename)) != 0) + { + return result; + } + + pTrackerServer = tracker_get_connection(); + if (pTrackerServer == NULL) + { + fdfs_client_destroy(); + return errno != 0 ? errno : ECONNREFUSED; + } + + snprintf(appender_file_id, sizeof(appender_file_id), "%s", argv[2]); + if ((result=storage_regenerate_appender_filename1(pTrackerServer, + NULL, appender_file_id, new_file_id)) != 0) + { + fprintf(stderr, "regenerate file %s fail, " + "error no: %d, error info: %s\n", + appender_file_id, result, STRERROR(result)); + return result; + } + + printf("%s\n", new_file_id); + + tracker_close_connection_ex(pTrackerServer, true); + fdfs_client_destroy(); + + return result; +} diff --git a/client/fdfs_test.c b/client/fdfs_test.c index 639bac8..16850b9 100644 --- a/client/fdfs_test.c +++ b/client/fdfs_test.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include @@ -84,7 +84,7 @@ int main(int argc, char *argv[]) "\nCopyright (C) 2008, Happy Fish / YuQing\n" \ "\nFastDFS may be copied only under the terms of the GNU General\n" \ "Public License V3, which may be found in the FastDFS source kit.\n" \ -"Please visit the FastDFS Home Page http://www.csource.org/ \n" \ +"Please visit the FastDFS Home Page http://www.fastken.com/ \n" \ "for more detail.\n\n" \ , g_fdfs_version.major, g_fdfs_version.minor); diff --git a/client/fdfs_test1.c b/client/fdfs_test1.c index 124fc49..9b015a8 100644 --- a/client/fdfs_test1.c +++ b/client/fdfs_test1.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include @@ -82,7 +82,7 @@ int main(int argc, char *argv[]) "\nCopyright (C) 2008, Happy Fish / YuQing\n" \ "\nFastDFS may be copied only under the terms of the GNU General\n" \ "Public License V3, which may be found in the FastDFS source kit.\n" \ -"Please visit the FastDFS Home Page http://www.csource.org/ \n" \ +"Please visit the FastDFS Home Page http://www.fastken.com/ \n" \ "for more detail.\n\n" \ , g_fdfs_version.major, g_fdfs_version.minor); diff --git a/client/fdfs_upload_appender.c b/client/fdfs_upload_appender.c index 81ea98d..a195553 100644 --- a/client/fdfs_upload_appender.c +++ b/client/fdfs_upload_appender.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include diff --git a/client/fdfs_upload_file.c b/client/fdfs_upload_file.c index f121203..4bac235 100644 --- a/client/fdfs_upload_file.c +++ b/client/fdfs_upload_file.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include diff --git a/client/storage_client.c b/client/storage_client.c index ce7912a..2e7adb4 100644 --- a/client/storage_client.c +++ b/client/storage_client.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ @@ -35,20 +35,20 @@ static struct base64_context the_base64_context; static int the_base64_context_inited = 0; #define FDFS_SPLIT_GROUP_NAME_AND_FILENAME(file_id) \ - char new_file_id[FDFS_GROUP_NAME_MAX_LEN + 128]; \ + char in_file_id[FDFS_GROUP_NAME_MAX_LEN + 128]; \ char *group_name; \ char *filename; \ char *pSeperator; \ \ - snprintf(new_file_id, sizeof(new_file_id), "%s", file_id); \ - pSeperator = strchr(new_file_id, FDFS_FILE_ID_SEPERATOR); \ + snprintf(in_file_id, sizeof(in_file_id), "%s", file_id); \ + pSeperator = strchr(in_file_id, FDFS_FILE_ID_SEPERATOR); \ if (pSeperator == NULL) \ { \ return EINVAL; \ } \ \ *pSeperator = '\0'; \ - group_name = new_file_id; \ + group_name = in_file_id; \ filename = pSeperator + 1; \ #define storage_get_read_connection(pTrackerServer, \ @@ -794,22 +794,16 @@ int storage_do_upload_file1(ConnectionInfo *pTrackerServer, \ STORAGE_PROTO_CMD_UPLOAD_FILE and STORAGE_PROTO_CMD_UPLOAD_APPENDER_FILE: 1 byte: store path index -8 bytes: meta data bytes 8 bytes: file size FDFS_FILE_EXT_NAME_MAX_LEN bytes: file ext name -meta data bytes: each meta data seperated by \x01, - name and value seperated by \x02 file size bytes: file content STORAGE_PROTO_CMD_UPLOAD_SLAVE_FILE: 8 bytes: master filename length -8 bytes: meta data bytes 8 bytes: file size FDFS_FILE_PREFIX_MAX_LEN bytes : filename prefix FDFS_FILE_EXT_NAME_MAX_LEN bytes: file ext name, do not include dot (.) master filename bytes: master filename -meta data bytes: each meta data seperated by \x01, - name and value seperated by \x02 file size bytes: file content **/ int storage_do_upload_file(ConnectionInfo *pTrackerServer, \ @@ -1808,7 +1802,7 @@ int storage_do_append_file(ConnectionInfo *pTrackerServer, \ } /** -STORAGE_PROTO_CMD_APPEND_FILE: +STORAGE_PROTO_CMD_MODIFY_FILE: 8 bytes: appender filename length 8 bytes: file offset 8 bytes: file size @@ -2181,7 +2175,7 @@ int fdfs_get_file_info_ex(const char *group_name, const char *remote_filename, \ if (pStorageId != NULL) { strcpy(pFileInfo->source_ip_addr, - pStorageId->ip_addrs.ips[0]); + pStorageId->ip_addrs.ips[0].address); } else { @@ -2203,8 +2197,21 @@ int fdfs_get_file_info_ex(const char *group_name, const char *remote_filename, \ pFileInfo->create_timestamp = buff2int(buff + sizeof(int)); pFileInfo->file_size = buff2long(buff + sizeof(int) * 2); - if (IS_SLAVE_FILE(filename_len, pFileInfo->file_size) || \ - IS_APPENDER_FILE(pFileInfo->file_size) || \ + if (IS_APPENDER_FILE(pFileInfo->file_size)) + { + pFileInfo->file_type = FDFS_FILE_TYPE_APPENDER; + } + else if (IS_SLAVE_FILE(filename_len, pFileInfo->file_size)) + { + pFileInfo->file_type = FDFS_FILE_TYPE_SLAVE; + } + else + { + pFileInfo->file_type = FDFS_FILE_TYPE_NORMAL; + } + + if (pFileInfo->file_type == FDFS_FILE_TYPE_SLAVE || + pFileInfo->file_type == FDFS_FILE_TYPE_APPENDER || (*(pFileInfo->source_ip_addr) == '\0' && get_from_server)) { //slave file or appender file if (get_from_server) @@ -2218,21 +2225,24 @@ int fdfs_get_file_info_ex(const char *group_name, const char *remote_filename, \ return result; } - result = storage_query_file_info(conn, \ + result = storage_query_file_info(conn, NULL, group_name, remote_filename, pFileInfo); - tracker_close_connection_ex(conn, result != 0 && \ + tracker_close_connection_ex(conn, result != 0 && result != ENOENT); + pFileInfo->get_from_server = true; return result; } else { + pFileInfo->get_from_server = false; pFileInfo->file_size = -1; return 0; } } else //master file (normal file) { + pFileInfo->get_from_server = false; if ((pFileInfo->file_size >> 63) != 0) { pFileInfo->file_size &= 0xFFFFFFFF; //low 32 bits is file size @@ -2352,3 +2362,115 @@ int storage_truncate_file(ConnectionInfo *pTrackerServer, \ return result; } +int storage_regenerate_appender_filename(ConnectionInfo *pTrackerServer, + ConnectionInfo *pStorageServer, const char *group_name, + const char *appender_filename, char *new_group_name, + char *new_remote_filename) +{ + TrackerHeader *pHeader; + int result; + char out_buff[512]; + char in_buff[256]; + char *p; + char *pInBuff; + int64_t in_bytes; + ConnectionInfo storageServer; + bool new_connection; + int appender_filename_len; + + appender_filename_len = strlen(appender_filename); + if ((result=storage_get_update_connection(pTrackerServer, + &pStorageServer, group_name, appender_filename, + &storageServer, &new_connection)) != 0) + { + return result; + } + + do + { + pHeader = (TrackerHeader *)out_buff; + p = out_buff + sizeof(TrackerHeader); + + memcpy(p, appender_filename, appender_filename_len); + p += appender_filename_len; + + long2buff((p - out_buff) - sizeof(TrackerHeader), + pHeader->pkg_len); + pHeader->cmd = STORAGE_PROTO_CMD_REGENERATE_APPENDER_FILENAME; + pHeader->status = 0; + + if ((result=tcpsenddata_nb(pStorageServer->sock, out_buff, + p - out_buff, g_fdfs_network_timeout)) != 0) + { + logError("file: "__FILE__", line: %d, " + "send data to storage server %s:%d fail, " + "errno: %d, error info: %s", __LINE__, + pStorageServer->ip_addr, pStorageServer->port, + result, STRERROR(result)); + break; + } + + pInBuff = in_buff; + if ((result=fdfs_recv_response(pStorageServer, + &pInBuff, sizeof(in_buff), &in_bytes)) != 0) + { + logError("file: "__FILE__", line: %d, " + "fdfs_recv_response fail, result: %d", + __LINE__, result); + break; + } + + if (in_bytes <= FDFS_GROUP_NAME_MAX_LEN) + { + logError("file: "__FILE__", line: %d, " + "storage server %s:%d response data " + "length: %"PRId64" is invalid, " + "should > %d", __LINE__, + pStorageServer->ip_addr, pStorageServer->port, + in_bytes, FDFS_GROUP_NAME_MAX_LEN); + result = EINVAL; + break; + } + + in_buff[in_bytes] = '\0'; + memcpy(new_group_name, in_buff, FDFS_GROUP_NAME_MAX_LEN); + new_group_name[FDFS_GROUP_NAME_MAX_LEN] = '\0'; + + memcpy(new_remote_filename, in_buff + FDFS_GROUP_NAME_MAX_LEN, + in_bytes - FDFS_GROUP_NAME_MAX_LEN + 1); + + } while (0); + + if (new_connection) + { + tracker_close_connection_ex(pStorageServer, result != 0); + } + + return result; +} + +int storage_regenerate_appender_filename1(ConnectionInfo *pTrackerServer, + ConnectionInfo *pStorageServer, const char *appender_file_id, + char *new_file_id) +{ + int result; + char new_group_name[FDFS_GROUP_NAME_MAX_LEN + 1]; + char new_remote_filename[128]; + + FDFS_SPLIT_GROUP_NAME_AND_FILENAME(appender_file_id) + + result = storage_regenerate_appender_filename(pTrackerServer, + pStorageServer, group_name, filename, + new_group_name, new_remote_filename); + if (result == 0) + { + sprintf(new_file_id, "%s%c%s", new_group_name, + FDFS_FILE_ID_SEPERATOR, new_remote_filename); + } + else + { + new_file_id[0] = '\0'; + } + + return result; +} diff --git a/client/storage_client.h b/client/storage_client.h index 12489a9..11e2e47 100644 --- a/client/storage_client.h +++ b/client/storage_client.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #ifndef STORAGE_CLIENT_H @@ -563,6 +563,23 @@ int fdfs_get_file_info_ex(const char *group_name, const char *remote_filename, \ const bool get_from_server, FDFSFileInfo *pFileInfo); +/** +* regenerate normal filename for appender file +* Note: the appender file will change to normal file +* params: +* pTrackerServer: the tracker server +* pStorageServer: the storage server +* group_name: the group name +* appender_filename: the appender filename +* new_group_name: return the new group name +* new_remote_filename: return the new filename +* return: 0 success, !=0 fail, return the error code +**/ +int storage_regenerate_appender_filename(ConnectionInfo *pTrackerServer, + ConnectionInfo *pStorageServer, const char *group_name, + const char *appender_filename, char *new_group_name, + char *new_remote_filename); + #ifdef __cplusplus } #endif diff --git a/client/storage_client1.h b/client/storage_client1.h index 63b5e4c..a0358f2 100644 --- a/client/storage_client1.h +++ b/client/storage_client1.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #ifndef STORAGE_CLIENT1_H @@ -524,6 +524,22 @@ int fdfs_get_file_info_ex1(const char *file_id, const bool get_from_server, \ int storage_file_exist1(ConnectionInfo *pTrackerServer, \ ConnectionInfo *pStorageServer, \ const char *file_id); + +/** +* regenerate normal filename for appender file +* Note: the appender file will change to normal file +* params: +* pTrackerServer: the tracker server +* pStorageServer: the storage server +* group_name: the group name +* appender_file_id: the appender file id +* file_id: regenerated file id return by storage server +* return: 0 success, !=0 fail, return the error code +**/ +int storage_regenerate_appender_filename1(ConnectionInfo *pTrackerServer, + ConnectionInfo *pStorageServer, const char *appender_file_id, + char *new_file_id); + #ifdef __cplusplus } #endif diff --git a/client/test/Makefile.in b/client/test/Makefile.in index 3910089..4a5a55e 100644 --- a/client/test/Makefile.in +++ b/client/test/Makefile.in @@ -1,7 +1,8 @@ .SUFFIXES: .c .o COMPILE = $(CC) $(CFLAGS) -INC_PATH = -I/usr/include/fastcommon -I/usr/include/fastdfs +INC_PATH = -I/usr/include/fastcommon -I/usr/include/fastdfs \ + -I/usr/local/include/fastcommon -I/usr/local/include/fastdfs LIB_PATH = -L/usr/local/lib -lfastcommon -lfdfsclient $(LIBS) TARGET_PATH = $(TARGET_PATH) diff --git a/client/test/fdfs_monitor.c b/client/test/fdfs_monitor.c index 7978b29..742cf56 100644 --- a/client/test/fdfs_monitor.c +++ b/client/test/fdfs_monitor.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include @@ -12,6 +12,7 @@ #include #include #include +#include #include #include "fastcommon/sockopt.h" #include "fastcommon/logger.h" @@ -25,8 +26,11 @@ static int list_all_groups(const char *group_name); static void usage(char *argv[]) { - printf("Usage: %s [-h ] [list|delete|set_trunk_server " \ - "[storage_id]]\n", argv[0]); + printf("Usage: %s [-h ] " + "[list|delete|set_trunk_server [storage_id]]\n" + "\tthe tracker server format: host[:port], " + "the tracker default port is %d\n\n", + argv[0], FDFS_TRACKER_SERVER_DEF_PORT); } int main(int argc, char *argv[]) @@ -115,21 +119,19 @@ int main(int argc, char *argv[]) else { int i; - char ip_addr[IP_ADDRESS_SIZE]; + ConnectionInfo conn; - *ip_addr = '\0'; - if (getIpaddrByName(tracker_server, ip_addr, sizeof(ip_addr)) \ - == INADDR_NONE) + if ((result=conn_pool_parse_server_info(tracker_server, &conn, + FDFS_TRACKER_SERVER_DEF_PORT)) != 0) { - printf("resolve ip address of tracker server: %s " \ - "fail!\n", tracker_server); - return 2; + printf("resolve ip address of tracker server: %s " + "fail!, error info: %s\n", tracker_server, hstrerror(h_errno)); + return result; } for (i=0; ilast_synced_timestamp); + if (delay_seconds < 0) + { + delay_seconds = 0; + } day = delay_seconds / (24 * 3600); remain_seconds = delay_seconds % (24 * 3600); hour = remain_seconds / 3600; diff --git a/client/test/fdfs_test.c b/client/test/fdfs_test.c index 468275f..16850b9 100644 --- a/client/test/fdfs_test.c +++ b/client/test/fdfs_test.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include @@ -84,7 +84,7 @@ int main(int argc, char *argv[]) "\nCopyright (C) 2008, Happy Fish / YuQing\n" \ "\nFastDFS may be copied only under the terms of the GNU General\n" \ "Public License V3, which may be found in the FastDFS source kit.\n" \ -"Please visit the FastDFS Home Page http://www.csource.org/ \n" \ +"Please visit the FastDFS Home Page http://www.fastken.com/ \n" \ "for more detail.\n\n" \ , g_fdfs_version.major, g_fdfs_version.minor); @@ -194,7 +194,7 @@ int main(int argc, char *argv[]) group_name, storageServer.ip_addr, \ storageServer.port); - if ((pStorageServer=tracker_connect_server(&storageServer, \ + if ((pStorageServer=tracker_make_connection(&storageServer, \ &result)) == NULL) { fdfs_client_destroy(); @@ -491,7 +491,7 @@ int main(int argc, char *argv[]) printf("storage=%s:%d\n", storageServer.ip_addr, \ storageServer.port); - if ((pStorageServer=tracker_connect_server(&storageServer, \ + if ((pStorageServer=tracker_make_connection(&storageServer, \ &result)) == NULL) { fdfs_client_destroy(); diff --git a/client/test/fdfs_test1.c b/client/test/fdfs_test1.c index 2fde169..9b015a8 100644 --- a/client/test/fdfs_test1.c +++ b/client/test/fdfs_test1.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include @@ -82,7 +82,7 @@ int main(int argc, char *argv[]) "\nCopyright (C) 2008, Happy Fish / YuQing\n" \ "\nFastDFS may be copied only under the terms of the GNU General\n" \ "Public License V3, which may be found in the FastDFS source kit.\n" \ -"Please visit the FastDFS Home Page http://www.csource.org/ \n" \ +"Please visit the FastDFS Home Page http://www.fastken.com/ \n" \ "for more detail.\n\n" \ , g_fdfs_version.major, g_fdfs_version.minor); @@ -191,7 +191,7 @@ int main(int argc, char *argv[]) group_name, storageServer.ip_addr, \ storageServer.port); - if ((pStorageServer=tracker_connect_server(&storageServer, \ + if ((pStorageServer=tracker_make_connection(&storageServer, \ &result)) == NULL) { fdfs_client_destroy(); @@ -458,7 +458,7 @@ int main(int argc, char *argv[]) printf("storage=%s:%d\n", storageServer.ip_addr, \ storageServer.port); - if ((pStorageServer=tracker_connect_server(&storageServer, \ + if ((pStorageServer=tracker_make_connection(&storageServer, \ &result)) == NULL) { fdfs_client_destroy(); diff --git a/client/tracker_client.c b/client/tracker_client.c index bbd7ceb..7f6a533 100644 --- a/client/tracker_client.c +++ b/client/tracker_client.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ @@ -1429,8 +1429,8 @@ int tracker_set_trunk_server(TrackerServerGroup *pTrackerGroup, \ return result; } -int tracker_get_storage_status(ConnectionInfo *pTrackerServer, \ - const char *group_name, const char *ip_addr, \ +int tracker_get_storage_status(ConnectionInfo *pTrackerServer, + const char *group_name, const char *ip_addr, FDFSStorageBrief *pDestBuff) { TrackerHeader *pHeader; diff --git a/client/tracker_client.h b/client/tracker_client.h index 58b37a1..93f0b99 100644 --- a/client/tracker_client.h +++ b/client/tracker_client.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #ifndef TRACKER_CLIENT_H diff --git a/common/fdfs_define.h b/common/fdfs_define.h index ea71032..0579bc4 100644 --- a/common/fdfs_define.h +++ b/common/fdfs_define.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //fdfs_define.h @@ -14,7 +14,7 @@ #include #include "fastcommon/common_define.h" -#define FDFS_TRACKER_SERVER_DEF_PORT 22000 +#define FDFS_TRACKER_SERVER_DEF_PORT 22122 #define FDFS_STORAGE_SERVER_DEF_PORT 23000 #define FDFS_DEF_STORAGE_RESERVED_MB 1024 #define TRACKER_ERROR_LOG_FILENAME "trackerd" diff --git a/common/fdfs_global.c b/common/fdfs_global.c index 61bf5c6..8d8f4bd 100644 --- a/common/fdfs_global.c +++ b/common/fdfs_global.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include @@ -23,7 +23,7 @@ int g_fdfs_connect_timeout = DEFAULT_CONNECT_TIMEOUT; int g_fdfs_network_timeout = DEFAULT_NETWORK_TIMEOUT; char g_fdfs_base_path[MAX_PATH_SIZE] = {'/', 't', 'm', 'p', '\0'}; -Version g_fdfs_version = {5, 12}; +Version g_fdfs_version = {6, 7}; bool g_use_connection_pool = false; ConnectionPool g_connection_pool; int g_connection_pool_max_idle_time = 3600; diff --git a/common/fdfs_global.h b/common/fdfs_global.h index 98a99df..ca0e3d3 100644 --- a/common/fdfs_global.h +++ b/common/fdfs_global.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //fdfs_global.h diff --git a/common/fdfs_http_shared.c b/common/fdfs_http_shared.c index ff79fb6..43197e1 100644 --- a/common/fdfs_http_shared.c +++ b/common/fdfs_http_shared.c @@ -4,7 +4,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include diff --git a/common/fdfs_http_shared.h b/common/fdfs_http_shared.h index 5da53ad..679eb95 100644 --- a/common/fdfs_http_shared.h +++ b/common/fdfs_http_shared.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #ifndef _FDFS_HTTP_SHARED_H diff --git a/common/mime_file_parser.c b/common/mime_file_parser.c index aa7461c..e7bcfce 100644 --- a/common/mime_file_parser.c +++ b/common/mime_file_parser.c @@ -4,7 +4,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include diff --git a/common/mime_file_parser.h b/common/mime_file_parser.h index ecb2c4f..681f388 100644 --- a/common/mime_file_parser.h +++ b/common/mime_file_parser.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #ifndef _MINE_FILE_PARSER_H diff --git a/conf/client.conf b/conf/client.conf index a34e56e..cdb84c8 100644 --- a/conf/client.conf +++ b/conf/client.conf @@ -1,23 +1,26 @@ # connect timeout in seconds # default value is 30s -connect_timeout=10 +# Note: in the intranet network (LAN), 2 seconds is enough. +connect_timeout = 5 # network timeout in seconds # default value is 30s -network_timeout=60 +network_timeout = 60 # the base path to store log files -base_path=/home/yuqing/fastdfs +base_path = /home/yuqing/fastdfs # tracker_server can ocur more than once for multi tracker servers. # the value format of tracker_server is "HOST:PORT", # the HOST can be hostname or ip address, # and the HOST can be dual IPs or hostnames seperated by comma, -# the dual IPS must be an intranet IP and an extranet IP. -# such as: 192.168.2.100,122.244.141.46 +# the dual IPS must be an inner (intranet) IP and an outer (extranet) IP, +# or two different types of inner (intranet) IPs. +# for example: 192.168.2.100,122.244.141.46:22122 +# another eg.: 192.168.1.10,172.17.4.21:22122 -tracker_server=192.168.0.196:22122 -tracker_server=192.168.0.197:22122 +tracker_server = 192.168.0.196:22122 +tracker_server = 192.168.0.197:22122 #standard log level as syslog, case insensitive, value list: ### emerg for emergency @@ -28,7 +31,7 @@ tracker_server=192.168.0.197:22122 ### notice ### info ### debug -log_level=info +log_level = info # if use connection pool # default value is false @@ -44,7 +47,7 @@ connection_pool_max_idle_time = 3600 # if load FastDFS parameters from tracker server # since V4.05 # default value is false -load_fdfs_parameters_from_tracker=false +load_fdfs_parameters_from_tracker = false # if use storage ID instead of IP address # same as tracker.conf @@ -61,7 +64,7 @@ storage_ids_filename = storage_ids.conf #HTTP settings -http.tracker_server_port=80 +http.tracker_server_port = 80 #use "#include" directive to include HTTP other settiongs ##include http.conf diff --git a/conf/http.conf b/conf/http.conf index 4d055f9..26603dd 100644 --- a/conf/http.conf +++ b/conf/http.conf @@ -5,24 +5,24 @@ http.default_content_type = application/octet-stream # MIME types file format: MIME_type extensions # such as: image/jpeg jpeg jpg jpe # you can use apache's MIME file: mime.types -http.mime_types_filename=mime.types +http.mime_types_filename = mime.types # if use token to anti-steal # default value is false (0) -http.anti_steal.check_token=false +http.anti_steal.check_token = false # token TTL (time to live), seconds # default value is 600 -http.anti_steal.token_ttl=900 +http.anti_steal.token_ttl = 900 # secret key to generate anti-steal token # this parameter must be set when http.anti_steal.check_token set to true # the length of the secret key should not exceed 128 bytes -http.anti_steal.secret_key=FastDFS1234567890 +http.anti_steal.secret_key = FastDFS1234567890 # return the content of the file when check token fail # default value is empty (no file sepecified) -http.anti_steal.token_check_fail=/home/yuqing/fastdfs/conf/anti-steal.jpg +http.anti_steal.token_check_fail = /home/yuqing/fastdfs/conf/anti-steal.jpg # if support multi regions for HTTP Range # default value is true diff --git a/conf/storage.conf b/conf/storage.conf index a317733..8ce66fd 100644 --- a/conf/storage.conf +++ b/conf/storage.conf @@ -1,67 +1,75 @@ # is this config file disabled # false for enabled # true for disabled -disabled=false +disabled = false # the name of the group this storage server belongs to # # comment or remove this item for fetching from tracker server, # in this case, use_storage_id must set to true in tracker.conf, -# and storage_ids.conf must be configed correctly. -group_name=group1 +# and storage_ids.conf must be configured correctly. +group_name = group1 # bind an address of this host # empty for bind all addresses of this host -bind_addr= +bind_addr = # if bind an address of this host when connect to other servers # (this storage server as a client) -# true for binding the address configed by above parameter: "bind_addr" +# true for binding the address configured by the above parameter: "bind_addr" # false for binding any address of this host -client_bind=true +client_bind = true # the storage server port -port=23000 +port = 23000 # connect timeout in seconds -# default value is 30s -connect_timeout=10 +# default value is 30 +# Note: in the intranet network (LAN), 2 seconds is enough. +connect_timeout = 5 -# network timeout in seconds -# default value is 30s -network_timeout=60 +# network timeout in seconds for send and recv +# default value is 30 +network_timeout = 60 -# heart beat interval in seconds -heart_beat_interval=30 +# the heart beat interval in seconds +# the storage server send heartbeat to tracker server periodically +# default value is 30 +heart_beat_interval = 30 # disk usage report interval in seconds -stat_report_interval=60 +# the storage server send disk usage report to tracker server periodically +# default value is 300 +stat_report_interval = 60 # the base path to store data and log files -base_path=/home/yuqing/fastdfs +# NOTE: the binlog files maybe are large, make sure +# the base path has enough disk space, +# eg. the disk free space should > 50GB +base_path = /home/yuqing/fastdfs -# max concurrent connections the server supported -# default value is 256 -# more max_connections means more memory will be used +# max concurrent connections the server supported, # you should set this parameter larger, eg. 10240 -max_connections=1024 +# default value is 256 +max_connections = 1024 -# the buff size to recv / send data +# the buff size to recv / send data from/to network # this parameter must more than 8KB +# 256KB or 512KB is recommended # default value is 64KB # since V2.00 buff_size = 256KB # accept thread count -# default value is 1 +# default value is 1 which is recommended # since V4.07 -accept_threads=1 +accept_threads = 1 -# work thread count, should <= max_connections -# work thread deal network io +# work thread count +# work threads to deal network io # default value is 4 # since V2.00 -work_threads=4 +work_threads = 4 # if disk read / write separated ## false for mixed read and write @@ -70,13 +78,13 @@ work_threads=4 # since V2.00 disk_rw_separated = true -# disk reader thread count per store base path +# disk reader thread count per store path # for mixed read / write, this parameter can be 0 # default value is 1 # since V2.00 disk_reader_threads = 1 -# disk writer thread count per store base path +# disk writer thread count per store path # for mixed read / write, this parameter can be 0 # default value is 1 # since V2.00 @@ -84,45 +92,58 @@ disk_writer_threads = 1 # when no entry to sync, try read binlog again after X milliseconds # must > 0, default value is 200ms -sync_wait_msec=50 +sync_wait_msec = 50 # after sync a file, usleep milliseconds # 0 for sync successively (never call usleep) -sync_interval=0 +sync_interval = 0 # storage sync start time of a day, time format: Hour:Minute # Hour from 0 to 23, Minute from 0 to 59 -sync_start_time=00:00 +sync_start_time = 00:00 # storage sync end time of a day, time format: Hour:Minute # Hour from 0 to 23, Minute from 0 to 59 -sync_end_time=23:59 +sync_end_time = 23:59 # write to the mark file after sync N files # default value is 500 -write_mark_file_freq=500 +write_mark_file_freq = 500 -# path(disk or mount point) count, default value is 1 -store_path_count=1 +# disk recovery thread count +# default value is 1 +# since V6.04 +disk_recovery_threads = 3 -# store_path#, based 0, if store_path0 not exists, it's value is base_path -# the paths must be exist -store_path0=/home/yuqing/fastdfs -#store_path1=/home/yuqing/fastdfs2 +# store path (disk or mount point) count, default value is 1 +store_path_count = 1 + +# store_path#, based on 0, to configure the store paths to store files +# if store_path0 not exists, it's value is base_path (NOT recommended) +# the paths must be exist. +# +# IMPORTANT NOTE: +# the store paths' order is very important, don't mess up!!! +# the base_path should be independent (different) of the store paths + +store_path0 = /home/yuqing/fastdfs +#store_path1 = /home/yuqing/fastdfs2 # subdir_count * subdir_count directories will be auto created under each # store_path (disk), value can be 1 to 256, default value is 256 -subdir_count_per_path=256 +subdir_count_per_path = 256 # tracker_server can ocur more than once for multi tracker servers. # the value format of tracker_server is "HOST:PORT", # the HOST can be hostname or ip address, # and the HOST can be dual IPs or hostnames seperated by comma, -# the dual IPS must be an intranet IP and an extranet IP. -# such as: 192.168.2.100,122.244.141.46 +# the dual IPS must be an inner (intranet) IP and an outer (extranet) IP, +# or two different types of inner (intranet) IPs. +# for example: 192.168.2.100,122.244.141.46:22122 +# another eg.: 192.168.1.10,172.17.4.21:22122 -tracker_server=192.168.209.121:22122 -tracker_server=192.168.209.122:22122 +tracker_server = 192.168.209.121:22122 +tracker_server = 192.168.209.122:22122 #standard log level as syslog, case insensitive, value list: ### emerg for emergency @@ -133,15 +154,15 @@ tracker_server=192.168.209.122:22122 ### notice ### info ### debug -log_level=info +log_level = info #unix group name to run this program, #not set (empty) means run by the group of current user -run_by_group= +run_by_group = #unix username to run this program, #not set (empty) means run by current user -run_by_user= +run_by_user = # allow_hosts can ocur more than once, host can be hostname or ip address, # "*" (only one asterisk) means match all ip addresses @@ -151,70 +172,71 @@ run_by_user= # allow_hosts=10.0.1.[1-15,20] # allow_hosts=host[01-08,20-25].domain.com # allow_hosts=192.168.5.64/26 -allow_hosts=* +allow_hosts = * # the mode of the files distributed to the data path # 0: round robin(default) # 1: random, distributted by hash code -file_distribute_path_mode=0 +file_distribute_path_mode = 0 -# valid when file_distribute_to_path is set to 0 (round robin), -# when the written file count reaches this number, then rotate to next path +# valid when file_distribute_to_path is set to 0 (round robin). +# when the written file count reaches this number, then rotate to next path. +# rotate to the first path (00/00) after the last path (such as FF/FF). # default value is 100 -file_distribute_rotate_count=100 +file_distribute_rotate_count = 100 # call fsync to disk when write big file # 0: never call fsync # other: call fsync when written bytes >= this bytes # default value is 0 (never call fsync) -fsync_after_written_bytes=0 +fsync_after_written_bytes = 0 # sync log buff to disk every interval seconds # must > 0, default value is 10 seconds -sync_log_buff_interval=10 +sync_log_buff_interval = 1 # sync binlog buff / cache to disk every interval seconds # default value is 60 seconds -sync_binlog_buff_interval=10 +sync_binlog_buff_interval = 1 # sync storage stat info to disk every interval seconds # default value is 300 seconds -sync_stat_file_interval=300 +sync_stat_file_interval = 300 # thread stack size, should >= 512KB # default value is 512KB -thread_stack_size=512KB +thread_stack_size = 512KB # the priority as a source server for uploading file. # the lower this value, the higher its uploading priority. # default value is 10 -upload_priority=10 +upload_priority = 10 # the NIC alias prefix, such as eth in Linux, you can see it by ifconfig -a # multi aliases split by comma. empty value means auto set by OS type # default values is empty -if_alias_prefix= +if_alias_prefix = # if check file duplicate, when set to true, use FastDHT to store file indexes # 1 or yes: need check # 0 or no: do not check # default value is 0 -check_file_duplicate=0 +check_file_duplicate = 0 # file signature method for check file duplicate ## hash: four 32 bits hash code ## md5: MD5 signature # default value is hash # since V4.01 -file_signature_method=hash +file_signature_method = hash # namespace for storing file indexes (key-value pairs) # this item must be set when check_file_duplicate is true / on -key_namespace=FastDFS +key_namespace = FastDFS # set keep_alive to 1 to enable persistent connection with FastDHT servers # default value is 0 (short connection) -keep_alive=0 +keep_alive = 0 # you can use "#include filename" (not include double quotes) directive to # load FastDHT server list, when the filename is a relative path such as @@ -237,7 +259,17 @@ rotate_access_log = false # Hour from 0 to 23, Minute from 0 to 59 # default value is 00:00 # since V4.00 -access_log_rotate_time=00:00 +access_log_rotate_time = 00:00 + +# if compress the old access log by gzip +# default value is false +# since V6.04 +compress_old_access_log = false + +# compress the access log days before +# default value is 1 +# since V6.04 +compress_access_log_days_before = 7 # if rotate the error log every day # default value is false @@ -248,7 +280,17 @@ rotate_error_log = false # Hour from 0 to 23, Minute from 0 to 59 # default value is 00:00 # since V4.02 -error_log_rotate_time=00:00 +error_log_rotate_time = 00:00 + +# if compress the old error log by gzip +# default value is false +# since V6.04 +compress_old_error_log = false + +# compress the error log days before +# default value is 1 +# since V6.04 +compress_error_log_days_before = 7 # rotate access log when the log file exceeds this size # 0 means never rotates log file by log file size @@ -270,12 +312,12 @@ log_file_keep_days = 0 # if skip the invalid record when sync file # default value is false # since V4.02 -file_sync_skip_invalid_record=false +file_sync_skip_invalid_record = false # if use connection pool # default value is false # since V4.05 -use_connection_pool = false +use_connection_pool = true # connections whose the idle time exceeds this time will be closed # unit: second @@ -283,10 +325,29 @@ use_connection_pool = false # since V4.05 connection_pool_max_idle_time = 3600 +# if compress the binlog files by gzip +# default value is false +# since V6.01 +compress_binlog = true + +# try to compress binlog time, time format: Hour:Minute +# Hour from 0 to 23, Minute from 0 to 59 +# default value is 01:30 +# since V6.01 +compress_binlog_time = 01:30 + +# if check the mark of store path to prevent confusion +# recommend to set this parameter to true +# if two storage servers (instances) MUST use a same store path for +# some specific purposes, you should set this parameter to false +# default value is true +# since V6.03 +check_store_path_mark = true + # use the ip address of this storage server if domain_name is empty, # else this domain name will ocur in the url redirected by the tracker server -http.domain_name= +http.domain_name = # the port of the web server on this storage server -http.server_port=8888 +http.server_port = 8888 diff --git a/conf/storage_ids.conf b/conf/storage_ids.conf index b444377..8f6911f 100644 --- a/conf/storage_ids.conf +++ b/conf/storage_ids.conf @@ -1,10 +1,16 @@ # +# +# id is a natural number (1, 2, 3 etc.), +# 6 bits of the id length is enough, such as 100001 +# # storage ip or hostname can be dual IPs seperated by comma, -# one is an intranet IP and another is an extranet IP. +# one is an inner (intranet) IP and another is an outer (extranet) IP, +# or two different types of inner (intranet) IPs # for example: 192.168.2.100,122.244.141.46 +# another eg.: 192.168.1.10,172.17.4.21 # # the port is optional. if you run more than one storaged instances # in a server, you must specified the port to distinguish different instances. -# 100001 group1 192.168.0.196 -# 100002 group1 192.168.0.116 +100001 group1 192.168.0.196 +100002 group1 192.168.0.197 diff --git a/conf/tracker.conf b/conf/tracker.conf index 5e28136..6bf3f4b 100644 --- a/conf/tracker.conf +++ b/conf/tracker.conf @@ -1,86 +1,88 @@ # is this config file disabled # false for enabled # true for disabled -disabled=false +disabled = false # bind an address of this host # empty for bind all addresses of this host -bind_addr= +bind_addr = # the tracker server port -port=22122 +port = 22122 # connect timeout in seconds -# default value is 30s -connect_timeout=10 +# default value is 30 +# Note: in the intranet network (LAN), 2 seconds is enough. +connect_timeout = 5 -# network timeout in seconds -# default value is 30s -network_timeout=60 +# network timeout in seconds for send and recv +# default value is 30 +network_timeout = 60 # the base path to store data and log files -base_path=/home/yuqing/fastdfs +base_path = /home/yuqing/fastdfs -# max concurrent connections this server supported -# you should set this parameter larger, eg. 102400 -max_connections=1024 +# max concurrent connections this server support +# you should set this parameter larger, eg. 10240 +# default value is 256 +max_connections = 1024 # accept thread count -# default value is 1 +# default value is 1 which is recommended # since V4.07 -accept_threads=1 +accept_threads = 1 -# work thread count, should <= max_connections +# work thread count +# work threads to deal network io # default value is 4 # since V2.00 -work_threads=4 +work_threads = 4 -# min buff size +# the min network buff size # default value 8KB min_buff_size = 8KB -# max buff size +# the max network buff size # default value 128KB max_buff_size = 128KB -# the method of selecting group to upload files +# the method for selecting group to upload files # 0: round robin # 1: specify group # 2: load balance, select the max free space group to upload file -store_lookup=2 +store_lookup = 2 # which group to upload file # when store_lookup set to 1, must set store_group to the group name -store_group=group2 +store_group = group2 # which storage server to upload file # 0: round robin (default) # 1: the first server order by ip address # 2: the first server order by priority (the minimal) # Note: if use_trunk_file set to true, must set store_server to 1 or 2 -store_server=0 +store_server = 0 -# which path(means disk or mount point) of the storage server to upload file +# which path (means disk or mount point) of the storage server to upload file # 0: round robin # 2: load balance, select the max free space path to upload file -store_path=0 +store_path = 0 # which storage server to download file # 0: round robin (default) # 1: the source storage server which the current file uploaded to -download_server=0 +download_server = 0 # reserved storage space for system or other applications. # if the free(available) space of any stoarge server in -# a group <= reserved_storage_space, -# no file can be uploaded to this group. +# a group <= reserved_storage_space, no file can be uploaded to this group. # bytes unit can be one of follows: ### G or g for gigabyte(GB) ### M or m for megabyte(MB) ### K or k for kilobyte(KB) ### no unit for byte(B) -### XX.XX% as ratio such as reserved_storage_space = 10% -reserved_storage_space = 10% +### XX.XX% as ratio such as: reserved_storage_space = 10% +reserved_storage_space = 20% #standard log level as syslog, case insensitive, value list: ### emerg for emergency @@ -91,7 +93,7 @@ reserved_storage_space = 10% ### notice ### info ### debug -log_level=info +log_level = info #unix group name to run this program, #not set (empty) means run by the group of current user @@ -99,7 +101,7 @@ run_by_group= #unix username to run this program, #not set (empty) means run by current user -run_by_user= +run_by_user = # allow_hosts can ocur more than once, host can be hostname or ip address, # "*" (only one asterisk) means match all ip addresses @@ -109,11 +111,11 @@ run_by_user= # allow_hosts=10.0.1.[1-15,20] # allow_hosts=host[01-08,20-25].domain.com # allow_hosts=192.168.5.64/26 -allow_hosts=* +allow_hosts = * # sync log buff to disk every interval seconds # default value is 10 seconds -sync_log_buff_interval = 10 +sync_log_buff_interval = 1 # check storage server alive interval seconds check_active_interval = 120 @@ -150,7 +152,24 @@ slot_min_size = 256 # store the upload file to trunk file when it's size <= this value # default value is 16MB # since V3.00 -slot_max_size = 16MB +slot_max_size = 1MB + +# the alignment size to allocate the trunk space +# default value is 0 (never align) +# since V6.05 +# NOTE: the larger the alignment size, the less likely of disk +# fragmentation, but the more space is wasted. +trunk_alloc_alignment_size = 256 + +# if merge contiguous free spaces of trunk file +# default value is false +# since V6.05 +trunk_free_space_merge = true + +# if delete / reclaim the unused trunk files +# default value is false +# since V6.05 +delete_unused_trunk_files = false # the trunk file size, should >= 4MB # default value is 64MB @@ -174,8 +193,8 @@ trunk_create_file_time_base = 02:00 trunk_create_file_interval = 86400 # the threshold to create trunk file -# when the free trunk file size less than the threshold, will create -# the trunk files +# when the free trunk file size less than the threshold, +# will create he trunk files # default value is 0 # since V3.06 trunk_create_file_space_threshold = 20G @@ -195,19 +214,41 @@ trunk_init_check_occupying = false trunk_init_reload_from_binlog = false # the min interval for compressing the trunk binlog file -# unit: second -# default value is 0, 0 means never compress +# unit: second, 0 means never compress # FastDFS compress the trunk binlog when trunk init and trunk destroy # recommand to set this parameter to 86400 (one day) +# default value is 0 # since V5.01 -trunk_compress_binlog_min_interval = 0 +trunk_compress_binlog_min_interval = 86400 -# if use storage ID instead of IP address +# the interval for compressing the trunk binlog file +# unit: second, 0 means never compress +# recommand to set this parameter to 86400 (one day) +# default value is 0 +# since V6.05 +trunk_compress_binlog_interval = 86400 + +# compress the trunk binlog time base, time format: Hour:Minute +# Hour from 0 to 23, Minute from 0 to 59 +# default value is 03:00 +# since V6.05 +trunk_compress_binlog_time_base = 03:00 + +# max backups for the trunk binlog file +# default value is 0 (never backup) +# since V6.05 +trunk_binlog_max_backups = 7 + +# if use storage server ID instead of IP address +# if you want to use dual IPs for storage server, you MUST set +# this parameter to true, and configure the dual IPs in the file +# configured by following item "storage_ids_filename", such as storage_ids.conf # default value is false # since V4.00 use_storage_id = false # specify storage ids filename, can use relative or absolute path +# this parameter is valid only when use_storage_id set to true # since V4.00 storage_ids_filename = storage_ids.conf @@ -217,7 +258,7 @@ storage_ids_filename = storage_ids.conf # this paramter is valid only when use_storage_id set to true # default value is ip # since V4.03 -id_type_in_filename = ip +id_type_in_filename = id # if store slave file use symbol link # default value is false @@ -233,7 +274,17 @@ rotate_error_log = false # Hour from 0 to 23, Minute from 0 to 59 # default value is 00:00 # since V4.02 -error_log_rotate_time=00:00 +error_log_rotate_time = 00:00 + +# if compress the old error log by gzip +# default value is false +# since V6.04 +compress_old_error_log = false + +# compress the error log days before +# default value is 1 +# since V6.04 +compress_error_log_days_before = 7 # rotate error log when the log file exceeds this size # 0 means never rotates log file by log file size @@ -249,7 +300,7 @@ log_file_keep_days = 0 # if use connection pool # default value is false # since V4.05 -use_connection_pool = false +use_connection_pool = true # connections whose the idle time exceeds this time will be closed # unit: second @@ -258,21 +309,21 @@ use_connection_pool = false connection_pool_max_idle_time = 3600 # HTTP port on this tracker server -http.server_port=8080 +http.server_port = 8080 # check storage HTTP server alive interval seconds # <= 0 for never check # default value is 30 -http.check_alive_interval=30 +http.check_alive_interval = 30 # check storage HTTP server alive type, values are: # tcp : connect to the storge server with HTTP port only, # do not request and get response # http: storage check alive url must return http status 200 # default value is tcp -http.check_alive_type=tcp +http.check_alive_type = tcp # check storage HTTP server alive uri/url # NOTE: storage embed HTTP server support uri: /status.html -http.check_alive_uri=/status.html +http.check_alive_uri = /status.html diff --git a/docker/dockerfile_local/Dockerfile b/docker/dockerfile_local/Dockerfile index 79df7bc..d7b7179 100644 --- a/docker/dockerfile_local/Dockerfile +++ b/docker/dockerfile_local/Dockerfile @@ -1,5 +1,5 @@ # centos 7 -FROM centos +FROM centos:7 # 添加配置文件 # add profiles ADD conf/client.conf /etc/fdfs/ @@ -19,7 +19,7 @@ ADD source/fastdfs-nginx-module.tar.gz /usr/local/src/ ADD source/nginx-1.15.4.tar.gz /usr/local/src/ # Run -RUN yum install git gcc gcc-c ++ make automake autoconf libtool pcre pcre-devel zlib zlib-devel openssl-devel wget vim -y \ +RUN yum install git gcc gcc-c++ make automake autoconf libtool pcre pcre-devel zlib zlib-devel openssl-devel wget vim -y \ && mkdir /home/dfs \ && cd /usr/local/src/ \ && cd libfastcommon/ \ diff --git a/docker/dockerfile_network/Dockerfile b/docker/dockerfile_network/Dockerfile index ff82a1b..8a7bdb3 100644 --- a/docker/dockerfile_network/Dockerfile +++ b/docker/dockerfile_network/Dockerfile @@ -1,5 +1,5 @@ # centos 7 -FROM centos +FROM centos:7 # 添加配置文件 ADD conf/client.conf /etc/fdfs/ ADD conf/http.conf /etc/fdfs/ @@ -11,7 +11,7 @@ ADD conf/nginx.conf /etc/fdfs/ ADD conf/mod_fastdfs.conf /etc/fdfs # run -RUN yum install git gcc gcc-c ++ make automake autoconf libtool pcre pcre-devel zlib zlib-devel openssl-devel wget vim -y \ +RUN yum install git gcc gcc-c++ make automake autoconf libtool pcre pcre-devel zlib zlib-devel openssl-devel wget vim -y \ && cd /usr/local/src \ && git clone https://github.com/happyfish100/libfastcommon.git --depth 1 \ && git clone https://github.com/happyfish100/fastdfs.git --depth 1 \ diff --git a/fastdfs.spec b/fastdfs.spec index 04268f2..f53b5de 100644 --- a/fastdfs.spec +++ b/fastdfs.spec @@ -3,7 +3,7 @@ %define FDFSClient libfdfsclient %define FDFSClientDevel libfdfsclient-devel %define FDFSTool fastdfs-tool -%define FDFSVersion 6.0.0 +%define FDFSVersion 6.0.6 %define CommitVersion %(echo $COMMIT_VERSION) Name: %{FastDFS} @@ -18,14 +18,14 @@ Source: http://perso.orange.fr/sebastien.godard/%{name}-%{version}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) Requires: %__cp %__mv %__chmod %__grep %__mkdir %__install %__id -BuildRequires: libfastcommon-devel >= 1.0.41 +BuildRequires: libfastcommon-devel >= 1.0.43 %description This package provides tracker & storage of fastdfs commit version: %{CommitVersion} %package -n %{FDFSServer} -Requires: libfastcommon >= 1.0.41 +Requires: libfastcommon >= 1.0.43 Summary: fastdfs tracker & storage %package -n %{FDFSTool} diff --git a/images/architect.png b/images/architect.png new file mode 100644 index 0000000..b7c40a3 Binary files /dev/null and b/images/architect.png differ diff --git a/make.sh b/make.sh index da084ce..69bb072 100755 --- a/make.sh +++ b/make.sh @@ -1,7 +1,6 @@ ENABLE_STATIC_LIB=0 ENABLE_SHARED_LIB=1 -DESTDIR=/usr -TARGET_PREFIX=$DESTDIR +TARGET_PREFIX=$DESTDIR/usr TARGET_CONF_PATH=$DESTDIR/etc/fdfs TARGET_INIT_PATH=$DESTDIR/etc/init.d @@ -24,15 +23,21 @@ else OS_BITS=64 fi +uname=$(uname) + if [ "$OS_BITS" -eq 64 ]; then - LIB_VERSION=lib64 + if [ "$uname" = "Darwin" ]; then + LIB_VERSION=lib + else + LIB_VERSION=lib64 + fi else LIB_VERSION=lib fi LIBS='' -uname=$(uname) + if [ "$uname" = "Linux" ]; then if [ "$OS_BITS" -eq 64 ]; then LIBS="$LIBS -L/usr/lib64" @@ -45,6 +50,7 @@ elif [ "$uname" = "FreeBSD" ] || [ "$uname" = "Darwin" ]; then CFLAGS="$CFLAGS" if [ "$uname" = "Darwin" ]; then CFLAGS="$CFLAGS -DDARWIN" + TARGET_PREFIX=$TARGET_PREFIX/local fi elif [ "$uname" = "SunOS" ]; then LIBS="$LIBS -L/usr/lib" @@ -132,6 +138,7 @@ cp Makefile.in Makefile perl -pi -e "s#\\\$\(CFLAGS\)#$CFLAGS#g" Makefile perl -pi -e "s#\\\$\(LIBS\)#$LIBS#g" Makefile perl -pi -e "s#\\\$\(TARGET_PREFIX\)#$TARGET_PREFIX#g" Makefile +perl -pi -e "s#\\\$\(LIB_VERSION\)#$LIB_VERSION#g" Makefile perl -pi -e "s#\\\$\(TARGET_CONF_PATH\)#$TARGET_CONF_PATH#g" Makefile perl -pi -e "s#\\\$\(ENABLE_STATIC_LIB\)#$ENABLE_STATIC_LIB#g" Makefile perl -pi -e "s#\\\$\(ENABLE_SHARED_LIB\)#$ENABLE_SHARED_LIB#g" Makefile diff --git a/php_client/fastdfs_appender_test.php b/php_client/fastdfs_appender_test.php index 00653b4..d6af08b 100644 --- a/php_client/fastdfs_appender_test.php +++ b/php_client/fastdfs_appender_test.php @@ -30,7 +30,6 @@ echo "fastdfs_storage_modify_by_filename fail, errno: " . fastdfs_get_last_error_no() . ", error info: " . fastdfs_get_last_error_info() . "\n"; exit; } - var_dump(fastdfs_get_file_info($group_name, $appender_filename)); if (!fastdfs_storage_truncate_file($group_name, $appender_filename, 0)) @@ -38,9 +37,23 @@ echo "fastdfs_storage_truncate_file fail, errno: " . fastdfs_get_last_error_no() . ", error info: " . fastdfs_get_last_error_info() . "\n"; exit; } - var_dump(fastdfs_get_file_info($group_name, $appender_filename)); + $new_file_info = fastdfs_storage_regenerate_appender_filename($group_name, $appender_filename); + if (!$new_file_info) + { + echo "fastdfs_storage_regenerate_appender_filename fail, errno: " . fastdfs_get_last_error_no() . ", error info: " . fastdfs_get_last_error_info() . "\n"; + exit; + } + + $group_name = $new_file_info['group_name']; + $appender_filename = $new_file_info['filename']; + echo "regenerated file id: $group_name/$appender_filename\n"; + var_dump(fastdfs_get_file_info($group_name, $appender_filename)); + + $result = fastdfs_storage_delete_file($group_name, $appender_filename); + echo "delete file $group_name/$appender_filename return: $result\n"; + echo "function test done\n\n"; $fdfs = new FastDFS(); @@ -81,8 +94,22 @@ echo "$fdfs->storage_truncate_file fail, errno: " . $fdfs->get_last_error_no() . ", error info: " . $fdfs->get_last_error_info() . "\n"; exit; } - var_dump($fdfs->get_file_info($group_name, $appender_filename)); + $new_file_info = $fdfs->storage_regenerate_appender_filename($group_name, $appender_filename); + if (!$new_file_info) + { + echo "$fdfs->storage_regenerate_appender_filename fail, errno: " . $fdfs->get_last_error_no() . ", error info: " . $fdfs->get_last_error_info() . "\n"; + exit; + } + + $group_name = $new_file_info['group_name']; + $appender_filename = $new_file_info['filename']; + echo "regenerated file id: $group_name/$appender_filename\n"; + var_dump($fdfs->get_file_info($group_name, $appender_filename)); + + $result = $fdfs->storage_delete_file($group_name, $appender_filename); + echo "delete file $group_name/$appender_filename return: $result\n"; + echo 'tracker_close_all_connections result: ' . $fdfs->tracker_close_all_connections() . "\n"; ?> diff --git a/php_client/fastdfs_appender_test1.php b/php_client/fastdfs_appender_test1.php index 107180b..9ec4368 100644 --- a/php_client/fastdfs_appender_test1.php +++ b/php_client/fastdfs_appender_test1.php @@ -25,7 +25,6 @@ echo "fastdfs_storage_modify_by_filename1 fail, errno: " . fastdfs_get_last_error_no() . ", error info: " . fastdfs_get_last_error_info() . "\n"; exit; } - var_dump(fastdfs_get_file_info1($appender_file_id)); if (!fastdfs_storage_truncate_file1($appender_file_id, 0)) @@ -33,8 +32,20 @@ echo "fastdfs_storage_truncate_file1 fail, errno: " . fastdfs_get_last_error_no() . ", error info: " . fastdfs_get_last_error_info() . "\n"; exit; } - var_dump(fastdfs_get_file_info1($appender_file_id)); + + $new_file_id = fastdfs_storage_regenerate_appender_filename1($appender_file_id); + if (!$new_file_id) + { + echo "fastdfs_storage_regenerate_appender_filename1 fail, errno: " . fastdfs_get_last_error_no() . ", error info: " . fastdfs_get_last_error_info() . "\n"; + exit; + } + $appender_file_id = $new_file_id; + var_dump(fastdfs_get_file_info1($appender_file_id)); + + $result = fastdfs_storage_delete_file1($appender_file_id); + echo "delete file $appender_file_id return: $result\n"; + echo "function test done\n\n"; $fdfs = new FastDFS(); @@ -69,8 +80,19 @@ echo "\$fdfs->torage_truncate_file1 torage_modify_by_filename1 fail, errno: " . $fdfs->get_last_error_no() . ", error info: " . $fdfs->get_last_error_info() . "\n"; exit; } - var_dump($fdfs->get_file_info1($appender_file_id)); + $new_file_id = $fdfs->storage_regenerate_appender_filename1($appender_file_id); + if (!$new_file_id) + { + echo "$fdfs->storage_regenerate_appender_filename1 fail, errno: " . $fdfs->get_last_error_no() . ", error info: " . $fdfs->get_last_error_info() . "\n"; + exit; + } + $appender_file_id = $new_file_id; + var_dump($fdfs->get_file_info1($appender_file_id)); + + $result = $fdfs->storage_delete_file1($appender_file_id); + echo "delete file $appender_file_id return: $result\n"; + echo 'tracker_close_all_connections result: ' . $fdfs->tracker_close_all_connections() . "\n"; ?> diff --git a/php_client/fastdfs_client.c b/php_client/fastdfs_client.c index 2e435d0..3c9d8ba 100644 --- a/php_client/fastdfs_client.c +++ b/php_client/fastdfs_client.c @@ -169,6 +169,8 @@ const zend_fcall_info empty_fcall_info = { 0, NULL, NULL, NULL, NULL, 0, NULL, N ZEND_FE(fastdfs_storage_file_exist1, NULL) ZEND_FE(fastdfs_gen_slave_filename, NULL) ZEND_FE(fastdfs_send_data, NULL) + ZEND_FE(fastdfs_storage_regenerate_appender_filename, NULL) + ZEND_FE(fastdfs_storage_regenerate_appender_filename1, NULL) {NULL, NULL, NULL} /* Must be the last line */ }; @@ -4047,6 +4049,195 @@ static void php_fdfs_storage_modify_file_impl( \ } } +/* +boolean fastdfs_storage_regenerate_appender_filename(string group_name, + string appender_filename, [array tracker_server, array storage_server]) +return assoc array for success, false for error +*/ +static void php_fdfs_storage_regenerate_appender_filename_impl( + INTERNAL_FUNCTION_PARAMETERS, FDFSPhpContext *pContext, + const bool bFileId) +{ + int result; + int argc; + char *appender_filename; + zval *tracker_obj; + zval *storage_obj; + char *group_name; + HashTable *tracker_hash; + HashTable *storage_hash; + ConnectionInfo tracker_server; + ConnectionInfo storage_server; + ConnectionInfo *pTrackerServer; + ConnectionInfo *pStorageServer; + char new_group_name[FDFS_GROUP_NAME_MAX_LEN + 1]; + char new_remote_filename[128]; + char new_file_id[FDFS_GROUP_NAME_MAX_LEN + 128]; + zend_size_t group_name_len; + zend_size_t appender_filename_len; + int saved_tracker_sock; + int saved_storage_sock; + int min_param_count; + int max_param_count; + + if (bFileId) + { + min_param_count = 1; + max_param_count = 3; + } + else + { + min_param_count = 2; + max_param_count = 4; + } + + argc = ZEND_NUM_ARGS(); + if (argc < min_param_count || argc > max_param_count) + { + logError("file: "__FILE__", line: %d, " \ + "storage_modify_file parameters " \ + "count: %d < %d or > %d", __LINE__, argc, \ + min_param_count, max_param_count); + pContext->err_no = EINVAL; + RETURN_BOOL(false); + } + + tracker_obj = NULL; + storage_obj = NULL; + if (bFileId) + { + char *pSeperator; + char *appender_file_id; + zend_size_t appender_file_id_len; + + result = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, + "s|aa", &appender_file_id, &appender_file_id_len, + &tracker_obj, &storage_obj); + if (result == FAILURE) + { + logError("file: "__FILE__", line: %d, " \ + "zend_parse_parameters fail!", __LINE__); + pContext->err_no = EINVAL; + RETURN_BOOL(false); + } + + snprintf(new_file_id, sizeof(new_file_id), "%s", appender_file_id); + pSeperator = strchr(new_file_id, FDFS_FILE_ID_SEPERATOR); + if (pSeperator == NULL) + { + logError("file: "__FILE__", line: %d, " + "appender_file_id is invalid, " + "appender_file_id=%s", + __LINE__, appender_file_id); + pContext->err_no = EINVAL; + RETURN_BOOL(false); + } + + *pSeperator = '\0'; + group_name = new_file_id; + appender_filename = pSeperator + 1; + } + else + { + result = zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, + "ss|aa", &group_name, &group_name_len, + &appender_filename, &appender_filename_len, + &tracker_obj, &storage_obj); + if (result == FAILURE) + { + logError("file: "__FILE__", line: %d, " + "zend_parse_parameters fail!", __LINE__); + pContext->err_no = EINVAL; + RETURN_BOOL(false); + } + } + + if (tracker_obj == NULL) + { + pTrackerServer = tracker_get_connection_no_pool( \ + pContext->pTrackerGroup); + if (pTrackerServer == NULL) + { + pContext->err_no = ENOENT; + RETURN_BOOL(false); + } + saved_tracker_sock = -1; + tracker_hash = NULL; + } + else + { + pTrackerServer = &tracker_server; + tracker_hash = Z_ARRVAL_P(tracker_obj); + if ((result=php_fdfs_get_server_from_hash(tracker_hash, \ + pTrackerServer)) != 0) + { + pContext->err_no = result; + RETURN_BOOL(false); + } + saved_tracker_sock = pTrackerServer->sock; + } + + if (storage_obj == NULL) + { + pStorageServer = NULL; + storage_hash = NULL; + saved_storage_sock = -1; + } + else + { + pStorageServer = &storage_server; + storage_hash = Z_ARRVAL_P(storage_obj); + if ((result=php_fdfs_get_server_from_hash(storage_hash, \ + pStorageServer)) != 0) + { + pContext->err_no = result; + RETURN_BOOL(false); + } + + saved_storage_sock = pStorageServer->sock; + } + + pContext->err_no = storage_regenerate_appender_filename(pTrackerServer, + pStorageServer, group_name, appender_filename, + new_group_name, new_remote_filename); + + if (tracker_hash != NULL && pTrackerServer->sock != \ + saved_tracker_sock) + { + CLEAR_HASH_SOCK_FIELD(tracker_hash) + } + if (pStorageServer != NULL && pStorageServer->sock != \ + saved_storage_sock) + { + CLEAR_HASH_SOCK_FIELD(storage_hash) + } + + if (pContext->err_no != 0) + { + RETURN_BOOL(false); + } + if (bFileId) + { + char file_id[FDFS_GROUP_NAME_MAX_LEN + 128]; + int file_id_len; + + file_id_len = sprintf(file_id, "%s%c%s", new_group_name, + FDFS_FILE_ID_SEPERATOR, new_remote_filename); + ZEND_RETURN_STRINGL(file_id, file_id_len, 1); + } + else + { + array_init(return_value); + + zend_add_assoc_stringl_ex(return_value, "group_name", + sizeof("group_name"), new_group_name, + strlen(new_group_name), 1); + zend_add_assoc_stringl_ex(return_value, "filename", + sizeof("filename"), new_remote_filename, + strlen(new_remote_filename), 1); + } +} + static void php_fdfs_storage_set_metadata_impl(INTERNAL_FUNCTION_PARAMETERS, \ FDFSPhpContext *pContext, const bool bFileId) { @@ -4271,7 +4462,7 @@ static void php_fdfs_http_gen_token_impl(INTERNAL_FUNCTION_PARAMETERS, \ if (argc != 2) { logError("file: "__FILE__", line: %d, " \ - "storage_upload_file parameters " \ + "fdfs_http_gen_token parameters " \ "count: %d != 2", __LINE__, argc); pContext->err_no = EINVAL; RETURN_BOOL(false); @@ -4359,7 +4550,7 @@ static void php_fdfs_get_file_info_impl(INTERNAL_FUNCTION_PARAMETERS, \ if (argc != param_count) { logError("file: "__FILE__", line: %d, " \ - "storage_upload_file parameters " \ + "fdfs_get_file_info parameters " \ "count: %d != %d", __LINE__, argc, param_count); pContext->err_no = EINVAL; RETURN_BOOL(false); @@ -4416,16 +4607,20 @@ static void php_fdfs_get_file_info_impl(INTERNAL_FUNCTION_PARAMETERS, \ } array_init(return_value); - zend_add_assoc_long_ex(return_value, "source_id", \ + zend_add_assoc_bool_ex(return_value, "get_from_server", + sizeof("get_from_server"), file_info.get_from_server); + zend_add_assoc_long_ex(return_value, "file_type", + sizeof("file_type"), file_info.file_type); + zend_add_assoc_long_ex(return_value, "source_id", sizeof("source_id"), file_info.source_id); - zend_add_assoc_long_ex(return_value, "create_timestamp", \ + zend_add_assoc_long_ex(return_value, "create_timestamp", sizeof("create_timestamp"), file_info.create_timestamp); - zend_add_assoc_long_ex(return_value, "file_size", \ + zend_add_assoc_long_ex(return_value, "file_size", sizeof("file_size"), (long)file_info.file_size); - zend_add_assoc_stringl_ex(return_value, "source_ip_addr", \ - sizeof("source_ip_addr"), file_info.source_ip_addr, \ + zend_add_assoc_stringl_ex(return_value, "source_ip_addr", + sizeof("source_ip_addr"), file_info.source_ip_addr, strlen(file_info.source_ip_addr), 1); - zend_add_assoc_long_ex(return_value, "crc32", \ + zend_add_assoc_long_ex(return_value, "crc32", sizeof("crc32"), file_info.crc32); } @@ -4453,7 +4648,7 @@ static void php_fdfs_gen_slave_filename_impl(INTERNAL_FUNCTION_PARAMETERS, \ if (argc != 2 && argc != 3) { logError("file: "__FILE__", line: %d, " \ - "storage_upload_file parameters " \ + "fdfs_gen_slave_filename parameters " \ "count: %d != 2 or 3", __LINE__, argc); pContext->err_no = EINVAL; RETURN_BOOL(false); @@ -4940,7 +5135,7 @@ ZEND_FUNCTION(fastdfs_storage_modify_by_callback) /* boolean fastdfs_storage_modify_by_callback1(array callback_array, - long file_offset, string group_name, string appender_filename + long file_offset, string appender_file_id, [, array tracker_server, array storage_server]) return true for success, false for error */ @@ -4950,6 +5145,28 @@ ZEND_FUNCTION(fastdfs_storage_modify_by_callback1) &php_context, FDFS_UPLOAD_BY_CALLBACK, true); } +/* +boolean fastdfs_storage_regenerate_appender_filename(string group_name, + string appender_filename, [array tracker_server, array storage_server]) +return assoc array for success, false for error +*/ +ZEND_FUNCTION(fastdfs_storage_regenerate_appender_filename) +{ + php_fdfs_storage_regenerate_appender_filename_impl( + INTERNAL_FUNCTION_PARAM_PASSTHRU, &php_context, false); +} + +/* +boolean fastdfs_storage_regenerate_appender_filename1( + string appender_file_id, [array tracker_server, array storage_server]) +return regenerated file id for success, false for error +*/ +ZEND_FUNCTION(fastdfs_storage_regenerate_appender_filename1) +{ + php_fdfs_storage_regenerate_appender_filename_impl( + INTERNAL_FUNCTION_PARAM_PASSTHRU, &php_context, true); +} + /* array fastdfs_storage_upload_appender_by_filename(string local_filename, [string file_ext_name, string meta_list, string group_name, @@ -5962,6 +6179,36 @@ PHP_METHOD(FastDFS, storage_modify_by_callback1) &(i_obj->context), FDFS_UPLOAD_BY_CALLBACK, true); } +/* +boolean fastdfs_storage_regenerate_appender_filename(string group_name, + string appender_filename, [array tracker_server, array storage_server]) +return assoc array for success, false for error +*/ +PHP_METHOD(FastDFS, storage_regenerate_appender_filename) +{ + zval *object = getThis(); + php_fdfs_t *i_obj; + + i_obj = (php_fdfs_t *) fdfs_get_object(object); + php_fdfs_storage_regenerate_appender_filename_impl( + INTERNAL_FUNCTION_PARAM_PASSTHRU, &(i_obj->context), false); +} + +/* +boolean fastdfs_storage_regenerate_appender_filename1( + string appender_file_id, [array tracker_server, array storage_server]) +return regenerated file id for success, false for error +*/ +PHP_METHOD(FastDFS, storage_regenerate_appender_filename1) +{ + zval *object = getThis(); + php_fdfs_t *i_obj; + + i_obj = (php_fdfs_t *) fdfs_get_object(object); + php_fdfs_storage_regenerate_appender_filename_impl( + INTERNAL_FUNCTION_PARAM_PASSTHRU, &(i_obj->context), true); +} + /* array FastDFS::storage_upload_appender_by_filename(string local_filename, [string file_ext_name, string meta_list, string group_name, @@ -6758,6 +7005,19 @@ ZEND_ARG_INFO(0, tracker_server) ZEND_ARG_INFO(0, storage_server) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_storage_regenerate_appender_filename, 0, 0, 2) +ZEND_ARG_INFO(0, group_name) +ZEND_ARG_INFO(0, appender_filename) +ZEND_ARG_INFO(0, tracker_server) +ZEND_ARG_INFO(0, storage_server) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO_EX(arginfo_storage_regenerate_appender_filename1, 0, 0, 1) +ZEND_ARG_INFO(0, appender_file_id) +ZEND_ARG_INFO(0, tracker_server) +ZEND_ARG_INFO(0, storage_server) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO_EX(arginfo_storage_upload_appender_by_filename, 0, 0, 1) ZEND_ARG_INFO(0, local_filename) ZEND_ARG_INFO(0, file_ext_name) @@ -7073,6 +7333,8 @@ static zend_function_entry fdfs_class_methods[] = { FDFS_ME(storage_modify_by_filebuff1, arginfo_storage_modify_by_filebuff1) FDFS_ME(storage_modify_by_callback, arginfo_storage_modify_by_callback) FDFS_ME(storage_modify_by_callback1, arginfo_storage_modify_by_callback1) + FDFS_ME(storage_regenerate_appender_filename, arginfo_storage_regenerate_appender_filename) + FDFS_ME(storage_regenerate_appender_filename1, arginfo_storage_regenerate_appender_filename1) FDFS_ME(storage_upload_appender_by_filename, arginfo_storage_upload_appender_by_filename) FDFS_ME(storage_upload_appender_by_filename1, arginfo_storage_upload_appender_by_filename1) FDFS_ME(storage_upload_appender_by_filebuff, arginfo_storage_upload_appender_by_filebuff) @@ -7539,6 +7801,13 @@ PHP_MINIT_FUNCTION(fastdfs_client) REGISTER_LONG_CONSTANT("FDFS_STORAGE_STATUS_NONE", \ FDFS_STORAGE_STATUS_NONE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("FDFS_FILE_TYPE_NORMAL", + FDFS_FILE_TYPE_NORMAL, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("FDFS_FILE_TYPE_SLAVE", + FDFS_FILE_TYPE_SLAVE, CONST_CS | CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("FDFS_FILE_TYPE_APPENDER", + FDFS_FILE_TYPE_APPENDER, CONST_CS | CONST_PERSISTENT); + return SUCCESS; } diff --git a/php_client/fastdfs_client.h b/php_client/fastdfs_client.h index 14b5c10..34fa9cb 100644 --- a/php_client/fastdfs_client.h +++ b/php_client/fastdfs_client.h @@ -88,6 +88,8 @@ ZEND_FUNCTION(fastdfs_storage_modify_by_callback); ZEND_FUNCTION(fastdfs_storage_modify_by_callback1); ZEND_FUNCTION(fastdfs_storage_truncate_file); ZEND_FUNCTION(fastdfs_storage_truncate_file1); +ZEND_FUNCTION(fastdfs_storage_regenerate_appender_filename); +ZEND_FUNCTION(fastdfs_storage_regenerate_appender_filename1); PHP_FASTDFS_API zend_class_entry *php_fdfs_get_ce(void); PHP_FASTDFS_API zend_class_entry *php_fdfs_get_exception(void); diff --git a/setup.sh b/setup.sh new file mode 100755 index 0000000..3a8d5c6 --- /dev/null +++ b/setup.sh @@ -0,0 +1,32 @@ + +if [ -n "$1" ]; then + TARGET_CONF_PATH=$1 +else + TARGET_CONF_PATH=/etc/fdfs +fi + +mkdir -p $TARGET_CONF_PATH + +if [ ! -f $TARGET_CONF_PATH/tracker.conf ]; then + cp -f conf/tracker.conf $TARGET_CONF_PATH/tracker.conf +fi + +if [ ! -f $TARGET_CONF_PATH/storage.conf ]; then + cp -f conf/storage.conf $TARGET_CONF_PATH/storage.conf +fi + +if [ ! -f $TARGET_CONF_PATH/client.conf ]; then + cp -f conf/client.conf $TARGET_CONF_PATH/client.conf +fi + +if [ ! -f $TARGET_CONF_PATH/storage_ids.conf ]; then + cp -f conf/storage_ids.conf $TARGET_CONF_PATH/storage_ids.conf +fi + +if [ ! -f $TARGET_CONF_PATH/http.conf ]; then + cp -f conf/http.conf $TARGET_CONF_PATH/http.conf +fi + +if [ ! -f $TARGET_CONF_PATH/mime.types ]; then + cp -f conf/mime.types $TARGET_CONF_PATH/mime.types +fi diff --git a/storage/fdfs_storaged.c b/storage/fdfs_storaged.c index 8ff7134..4cfc046 100644 --- a/storage/fdfs_storaged.c +++ b/storage/fdfs_storaged.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include @@ -49,14 +49,21 @@ #include "storage_dump.h" #endif +#define ACCEPT_STAGE_NONE 0 +#define ACCEPT_STAGE_DOING 1 +#define ACCEPT_STAGE_DONE 2 + static bool bTerminateFlag = false; -static bool bAcceptEndFlag = false; +static char accept_stage = ACCEPT_STAGE_NONE; static void sigQuitHandler(int sig); static void sigHupHandler(int sig); static void sigUsrHandler(int sig); static void sigAlarmHandler(int sig); +static int setupSchedules(pthread_t *schedule_tid); +static int setupSignalHandlers(); + #if defined(DEBUG_FLAG) /* @@ -68,24 +75,22 @@ static void sigSegvHandler(int signum, siginfo_t *info, void *ptr); static void sigDumpHandler(int sig); #endif -#define SCHEDULE_ENTRIES_MAX_COUNT 9 - static void usage(const char *program) { - fprintf(stderr, "Usage: %s [start | stop | restart]\n", - program); + fprintf(stderr, "FastDFS server v%d.%02d\n" + "Usage: %s [start | stop | restart]\n", + g_fdfs_version.major, g_fdfs_version.minor, + program); } int main(int argc, char *argv[]) { char *conf_filename; + char *action; int result; int sock; int wait_count; pthread_t schedule_tid; - struct sigaction act; - ScheduleEntry scheduleEntries[SCHEDULE_ENTRIES_MAX_COUNT]; - ScheduleArray scheduleArray; char pidFilename[MAX_PATH_SIZE]; bool stop; @@ -99,9 +104,21 @@ int main(int argc, char *argv[]) g_up_time = g_current_time; log_init2(); - trunk_shared_init(); + if ((result=trunk_shared_init()) != 0) + { + log_destroy(); + return result; + } conf_filename = argv[1]; + if (!fileExists(conf_filename)) + { + if (starts_with(conf_filename, "-")) + { + usage(argv[0]); + return 0; + } + } if ((result=get_base_path_from_conf_file(conf_filename, g_fdfs_base_path, sizeof(g_fdfs_base_path))) != 0) { @@ -109,9 +126,15 @@ int main(int argc, char *argv[]) return result; } + if ((result=storage_check_and_make_global_data_path()) != 0) + { + log_destroy(); + return result; + } snprintf(pidFilename, sizeof(pidFilename), "%s/data/fdfs_storaged.pid", g_fdfs_base_path); - if ((result=process_action(pidFilename, argv[2], &stop)) != 0) + action = argc >= 3 ? argv[2] : "start"; + if ((result=process_action(pidFilename, action, &stop)) != 0) { if (result == EINVAL) { @@ -145,6 +168,13 @@ int main(int argc, char *argv[]) return result; } + if ((result=setupSignalHandlers()) != 0) + { + logCrit("exit abnormally!\n"); + log_destroy(); + return result; + } + memset(g_bind_addr, 0, sizeof(g_bind_addr)); if ((result=storage_func_init(conf_filename, \ g_bind_addr, sizeof(g_bind_addr))) != 0) @@ -204,84 +234,6 @@ int main(int argc, char *argv[]) return result; } - memset(&act, 0, sizeof(act)); - sigemptyset(&act.sa_mask); - - act.sa_handler = sigUsrHandler; - if(sigaction(SIGUSR1, &act, NULL) < 0 || \ - sigaction(SIGUSR2, &act, NULL) < 0) - { - logCrit("file: "__FILE__", line: %d, " \ - "call sigaction fail, errno: %d, error info: %s", \ - __LINE__, errno, STRERROR(errno)); - logCrit("exit abnormally!\n"); - return errno; - } - - act.sa_handler = sigHupHandler; - if(sigaction(SIGHUP, &act, NULL) < 0) - { - logCrit("file: "__FILE__", line: %d, " \ - "call sigaction fail, errno: %d, error info: %s", \ - __LINE__, errno, STRERROR(errno)); - logCrit("exit abnormally!\n"); - return errno; - } - - act.sa_handler = SIG_IGN; - if(sigaction(SIGPIPE, &act, NULL) < 0) - { - logCrit("file: "__FILE__", line: %d, " \ - "call sigaction fail, errno: %d, error info: %s", \ - __LINE__, errno, STRERROR(errno)); - logCrit("exit abnormally!\n"); - return errno; - } - - act.sa_handler = sigQuitHandler; - if(sigaction(SIGINT, &act, NULL) < 0 || \ - sigaction(SIGTERM, &act, NULL) < 0 || \ - sigaction(SIGQUIT, &act, NULL) < 0) - { - logCrit("file: "__FILE__", line: %d, " \ - "call sigaction fail, errno: %d, error info: %s", \ - __LINE__, errno, STRERROR(errno)); - logCrit("exit abnormally!\n"); - return errno; - } - -#if defined(DEBUG_FLAG) - -/* -#if defined(OS_LINUX) - memset(&act, 0, sizeof(act)); - act.sa_sigaction = sigSegvHandler; - act.sa_flags = SA_SIGINFO; - if (sigaction(SIGSEGV, &act, NULL) < 0 || \ - sigaction(SIGABRT, &act, NULL) < 0) - { - logCrit("file: "__FILE__", line: %d, " \ - "call sigaction fail, errno: %d, error info: %s", \ - __LINE__, errno, STRERROR(errno)); - logCrit("exit abnormally!\n"); - return errno; - } -#endif -*/ - - memset(&act, 0, sizeof(act)); - sigemptyset(&act.sa_mask); - act.sa_handler = sigDumpHandler; - if(sigaction(SIGUSR1, &act, NULL) < 0 || \ - sigaction(SIGUSR2, &act, NULL) < 0) - { - logCrit("file: "__FILE__", line: %d, " \ - "call sigaction fail, errno: %d, error info: %s", \ - __LINE__, errno, STRERROR(errno)); - logCrit("exit abnormally!\n"); - return errno; - } -#endif #ifdef WITH_HTTPD if (!g_http_params.disabled) @@ -307,85 +259,12 @@ int main(int argc, char *argv[]) return result; } - scheduleArray.entries = scheduleEntries; - scheduleArray.count = 0; - memset(scheduleEntries, 0, sizeof(scheduleEntries)); - - INIT_SCHEDULE_ENTRY(scheduleEntries[scheduleArray.count], - scheduleArray.count + 1, TIME_NONE, TIME_NONE, TIME_NONE, - g_sync_log_buff_interval, log_sync_func, &g_log_context); - scheduleArray.count++; - - INIT_SCHEDULE_ENTRY(scheduleEntries[scheduleArray.count], - scheduleArray.count + 1, TIME_NONE, TIME_NONE, TIME_NONE, - g_sync_binlog_buff_interval, fdfs_binlog_sync_func, NULL); - scheduleArray.count++; - - INIT_SCHEDULE_ENTRY(scheduleEntries[scheduleArray.count], - scheduleArray.count + 1, TIME_NONE, TIME_NONE, TIME_NONE, - g_sync_stat_file_interval, fdfs_stat_file_sync_func, NULL); - scheduleArray.count++; - - if (g_if_use_trunk_file) - { - INIT_SCHEDULE_ENTRY(scheduleEntries[scheduleArray.count], - scheduleArray.count + 1, TIME_NONE, TIME_NONE, TIME_NONE, - 1, trunk_binlog_sync_func, NULL); - scheduleArray.count++; - } - - if (g_use_access_log) - { - INIT_SCHEDULE_ENTRY(scheduleEntries[scheduleArray.count], - scheduleArray.count + 1, TIME_NONE, TIME_NONE, TIME_NONE, - g_sync_log_buff_interval, log_sync_func, &g_access_log_context); - scheduleArray.count++; - - if (g_rotate_access_log) - { - INIT_SCHEDULE_ENTRY_EX(scheduleEntries[scheduleArray.count], - scheduleArray.count + 1, g_access_log_rotate_time, - 24 * 3600, log_notify_rotate, &g_access_log_context); - scheduleArray.count++; - - if (g_log_file_keep_days > 0) - { - log_set_keep_days(&g_access_log_context, - g_log_file_keep_days); - - INIT_SCHEDULE_ENTRY(scheduleEntries[scheduleArray.count], - scheduleArray.count + 1, 1, 0, 0, 24 * 3600, - log_delete_old_files, &g_access_log_context); - scheduleArray.count++; - } - } - } - - if (g_rotate_error_log) - { - INIT_SCHEDULE_ENTRY_EX(scheduleEntries[scheduleArray.count], - scheduleArray.count + 1, g_error_log_rotate_time, - 24 * 3600, log_notify_rotate, &g_log_context); - scheduleArray.count++; - - if (g_log_file_keep_days > 0) - { - log_set_keep_days(&g_log_context, g_log_file_keep_days); - - INIT_SCHEDULE_ENTRY(scheduleEntries[scheduleArray.count], - scheduleArray.count + 1, 1, 0, 0, 24 * 3600, - log_delete_old_files, &g_log_context); - scheduleArray.count++; - } - } - - if ((result=sched_start(&scheduleArray, &schedule_tid, \ - g_thread_stack_size, (bool * volatile)&g_continue_flag)) != 0) - { + if ((result=setupSchedules(&schedule_tid)) != 0) + { logCrit("exit abnormally!\n"); log_destroy(); return result; - } + } if ((result=set_run_by(g_run_by_group, g_run_by_user)) != 0) { @@ -403,10 +282,10 @@ int main(int argc, char *argv[]) log_set_cache(true); bTerminateFlag = false; - bAcceptEndFlag = false; + accept_stage = ACCEPT_STAGE_DOING; storage_accept_loop(sock); - bAcceptEndFlag = true; + accept_stage = ACCEPT_STAGE_DONE; fdfs_binlog_sync_func(NULL); //binlog fsync @@ -438,7 +317,7 @@ int main(int argc, char *argv[]) */ usleep(10000); - if (++wait_count > 6000) + if (++wait_count > 9000) { logWarning("waiting timeout, exit!"); break; @@ -448,7 +327,6 @@ int main(int argc, char *argv[]) tracker_report_destroy(); storage_service_destroy(); storage_sync_destroy(); - storage_func_destroy(); if (g_if_use_trunk_file) { @@ -456,6 +334,7 @@ int main(int argc, char *argv[]) storage_trunk_destroy(); } + storage_func_destroy(); delete_pid_file(pidFilename); logInfo("exit normally.\n"); log_destroy(); @@ -467,6 +346,7 @@ static void sigQuitHandler(int sig) { if (!bTerminateFlag) { + tcp_set_try_again_when_interrupt(false); set_timer(1, 1, sigAlarmHandler); bTerminateFlag = true; @@ -482,7 +362,7 @@ static void sigAlarmHandler(int sig) { ConnectionInfo server; - if (bAcceptEndFlag) + if (accept_stage != ACCEPT_STAGE_DOING) { return; } @@ -556,3 +436,179 @@ static void sigDumpHandler(int sig) } #endif +static int setupSchedules(pthread_t *schedule_tid) +{ +#define SCHEDULE_ENTRIES_MAX_COUNT 10 + + ScheduleEntry scheduleEntries[SCHEDULE_ENTRIES_MAX_COUNT]; + ScheduleArray scheduleArray; + int result; + + scheduleArray.entries = scheduleEntries; + scheduleArray.count = 0; + memset(scheduleEntries, 0, sizeof(scheduleEntries)); + + INIT_SCHEDULE_ENTRY(scheduleEntries[scheduleArray.count], + scheduleArray.count + 1, TIME_NONE, TIME_NONE, TIME_NONE, + g_sync_log_buff_interval, log_sync_func, &g_log_context); + scheduleArray.count++; + + INIT_SCHEDULE_ENTRY(scheduleEntries[scheduleArray.count], + scheduleArray.count + 1, TIME_NONE, TIME_NONE, TIME_NONE, + g_sync_binlog_buff_interval, fdfs_binlog_sync_func, NULL); + scheduleArray.count++; + + INIT_SCHEDULE_ENTRY(scheduleEntries[scheduleArray.count], + scheduleArray.count + 1, TIME_NONE, TIME_NONE, TIME_NONE, + g_sync_stat_file_interval, fdfs_stat_file_sync_func, NULL); + scheduleArray.count++; + + if (g_if_use_trunk_file) + { + INIT_SCHEDULE_ENTRY(scheduleEntries[scheduleArray.count], + scheduleArray.count + 1, TIME_NONE, TIME_NONE, TIME_NONE, + 1, trunk_binlog_sync_func, NULL); + scheduleArray.count++; + } + + if (g_use_access_log) + { + INIT_SCHEDULE_ENTRY(scheduleEntries[scheduleArray.count], + scheduleArray.count + 1, TIME_NONE, TIME_NONE, TIME_NONE, + g_sync_log_buff_interval, log_sync_func, &g_access_log_context); + scheduleArray.count++; + + if (g_rotate_access_log) + { + INIT_SCHEDULE_ENTRY_EX(scheduleEntries[scheduleArray.count], + scheduleArray.count + 1, g_access_log_rotate_time, + 24 * 3600, log_notify_rotate, &g_access_log_context); + scheduleArray.count++; + + if (g_log_file_keep_days > 0) + { + log_set_keep_days(&g_access_log_context, + g_log_file_keep_days); + + INIT_SCHEDULE_ENTRY(scheduleEntries[scheduleArray.count], + scheduleArray.count + 1, 1, 0, 0, 24 * 3600, + log_delete_old_files, &g_access_log_context); + scheduleArray.count++; + } + } + } + + if (g_rotate_error_log) + { + INIT_SCHEDULE_ENTRY_EX(scheduleEntries[scheduleArray.count], + scheduleArray.count + 1, g_error_log_rotate_time, + 24 * 3600, log_notify_rotate, &g_log_context); + scheduleArray.count++; + + if (g_log_file_keep_days > 0) + { + log_set_keep_days(&g_log_context, g_log_file_keep_days); + + INIT_SCHEDULE_ENTRY(scheduleEntries[scheduleArray.count], + scheduleArray.count + 1, 1, 0, 0, 24 * 3600, + log_delete_old_files, &g_log_context); + scheduleArray.count++; + } + } + + if (g_compress_binlog) + { + INIT_SCHEDULE_ENTRY_EX(scheduleEntries[scheduleArray.count], + scheduleArray.count + 1, g_compress_binlog_time, + 24 * 3600, fdfs_binlog_compress_func, NULL); + scheduleArray.count++; + } + + if ((result=sched_start(&scheduleArray, schedule_tid, + g_thread_stack_size, (bool * volatile)&g_continue_flag)) != 0) + { + return result; + } + + return 0; +} + +static int setupSignalHandlers() +{ + struct sigaction act; + + memset(&act, 0, sizeof(act)); + sigemptyset(&act.sa_mask); + + act.sa_handler = sigUsrHandler; + if(sigaction(SIGUSR1, &act, NULL) < 0 || \ + sigaction(SIGUSR2, &act, NULL) < 0) + { + logCrit("file: "__FILE__", line: %d, " \ + "call sigaction fail, errno: %d, error info: %s", \ + __LINE__, errno, STRERROR(errno)); + return errno != 0 ? errno : EFAULT; + } + + act.sa_handler = sigHupHandler; + if(sigaction(SIGHUP, &act, NULL) < 0) + { + logCrit("file: "__FILE__", line: %d, " \ + "call sigaction fail, errno: %d, error info: %s", \ + __LINE__, errno, STRERROR(errno)); + return errno != 0 ? errno : EFAULT; + } + + act.sa_handler = SIG_IGN; + if(sigaction(SIGPIPE, &act, NULL) < 0) + { + logCrit("file: "__FILE__", line: %d, " \ + "call sigaction fail, errno: %d, error info: %s", \ + __LINE__, errno, STRERROR(errno)); + return errno != 0 ? errno : EFAULT; + } + + act.sa_handler = sigQuitHandler; + if(sigaction(SIGINT, &act, NULL) < 0 || \ + sigaction(SIGTERM, &act, NULL) < 0 || \ + sigaction(SIGQUIT, &act, NULL) < 0) + { + logCrit("file: "__FILE__", line: %d, " \ + "call sigaction fail, errno: %d, error info: %s", \ + __LINE__, errno, STRERROR(errno)); + return errno != 0 ? errno : EFAULT; + } + +#if defined(DEBUG_FLAG) + +/* +#if defined(OS_LINUX) + memset(&act, 0, sizeof(act)); + act.sa_sigaction = sigSegvHandler; + act.sa_flags = SA_SIGINFO; + if (sigaction(SIGSEGV, &act, NULL) < 0 || \ + sigaction(SIGABRT, &act, NULL) < 0) + { + logCrit("file: "__FILE__", line: %d, " \ + "call sigaction fail, errno: %d, error info: %s", \ + __LINE__, errno, STRERROR(errno)); + return errno != 0 ? errno : EFAULT; + } +#endif +*/ + + memset(&act, 0, sizeof(act)); + sigemptyset(&act.sa_mask); + act.sa_handler = sigDumpHandler; + if(sigaction(SIGUSR1, &act, NULL) < 0 || \ + sigaction(SIGUSR2, &act, NULL) < 0) + { + logCrit("file: "__FILE__", line: %d, " \ + "call sigaction fail, errno: %d, error info: %s", \ + __LINE__, errno, STRERROR(errno)); + return errno != 0 ? errno : EFAULT; + } +#endif + + return 0; +} diff --git a/storage/fdht_client/fdht_client.c b/storage/fdht_client/fdht_client.c index 7ae6718..bd57d06 100644 --- a/storage/fdht_client/fdht_client.c +++ b/storage/fdht_client/fdht_client.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include diff --git a/storage/fdht_client/fdht_client.h b/storage/fdht_client/fdht_client.h index 07222a8..2658ee1 100644 --- a/storage/fdht_client/fdht_client.h +++ b/storage/fdht_client/fdht_client.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //fdht_client.h diff --git a/storage/fdht_client/fdht_define.h b/storage/fdht_client/fdht_define.h index c61afd9..5a479f8 100644 --- a/storage/fdht_client/fdht_define.h +++ b/storage/fdht_client/fdht_define.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //fdht_define.h diff --git a/storage/fdht_client/fdht_func.c b/storage/fdht_client/fdht_func.c index 765fd16..fa3730d 100644 --- a/storage/fdht_client/fdht_func.c +++ b/storage/fdht_client/fdht_func.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //fdht_func.c diff --git a/storage/fdht_client/fdht_func.h b/storage/fdht_client/fdht_func.h index 7bfee30..592f0f4 100644 --- a/storage/fdht_client/fdht_func.h +++ b/storage/fdht_client/fdht_func.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //fdht_func.h diff --git a/storage/fdht_client/fdht_global.c b/storage/fdht_client/fdht_global.c index ce93a63..5cd8c7b 100644 --- a/storage/fdht_client/fdht_global.c +++ b/storage/fdht_client/fdht_global.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include diff --git a/storage/fdht_client/fdht_global.h b/storage/fdht_client/fdht_global.h index c6fa467..580ae92 100644 --- a/storage/fdht_client/fdht_global.h +++ b/storage/fdht_client/fdht_global.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //fdht_global.h diff --git a/storage/fdht_client/fdht_proto.c b/storage/fdht_client/fdht_proto.c index 418ca62..8d6a6c4 100644 --- a/storage/fdht_client/fdht_proto.c +++ b/storage/fdht_client/fdht_proto.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include diff --git a/storage/fdht_client/fdht_proto.h b/storage/fdht_client/fdht_proto.h index 93e87b9..69b667a 100644 --- a/storage/fdht_client/fdht_proto.h +++ b/storage/fdht_client/fdht_proto.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //fdht_proto.h diff --git a/storage/fdht_client/fdht_proto_types.h b/storage/fdht_client/fdht_proto_types.h index cdf2588..98c5504 100644 --- a/storage/fdht_client/fdht_proto_types.h +++ b/storage/fdht_client/fdht_proto_types.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //fdht_proto_types.h diff --git a/storage/fdht_client/fdht_types.h b/storage/fdht_client/fdht_types.h index 37b0ec1..673e0e7 100644 --- a/storage/fdht_client/fdht_types.h +++ b/storage/fdht_client/fdht_types.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //fdht_types.h diff --git a/storage/storage_dio.c b/storage/storage_dio.c index 5936c17..cca3e78 100644 --- a/storage/storage_dio.c +++ b/storage/storage_dio.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include @@ -24,6 +24,7 @@ #include "fastcommon/pthread_func.h" #include "fastcommon/logger.h" #include "fastcommon/sockopt.h" +#include "fastcommon/ioevent_loop.h" #include "storage_dio.h" #include "storage_nio.h" #include "storage_service.h" @@ -144,19 +145,19 @@ void storage_dio_terminate() int storage_dio_queue_push(struct fast_task_info *pTask) { - StorageClientInfo *pClientInfo; + StorageClientInfo *pClientInfo; StorageFileContext *pFileContext; struct storage_dio_context *pContext; int result; - pClientInfo = (StorageClientInfo *)pTask->arg; + pClientInfo = (StorageClientInfo *)pTask->arg; pFileContext = &(pClientInfo->file_context); pContext = g_dio_contexts + pFileContext->dio_thread_index; pClientInfo->stage |= FDFS_STORAGE_STAGE_DIO_THREAD; if ((result=blocked_queue_push(&(pContext->queue), pTask)) != 0) { - add_to_deleted_list(pTask); + ioevent_add_to_deleted_list(pTask); return result; } @@ -222,7 +223,7 @@ int dio_delete_trunk_file(struct fast_task_info *pTask) pFileContext = &(((StorageClientInfo *)pTask->arg)->file_context); - if ((result=trunk_file_delete(pFileContext->filename, \ + if ((result=trunk_file_delete(pFileContext->filename, &(pFileContext->extra_info.upload.trunk_info))) != 0) { pFileContext->log_callback(pTask, result); @@ -245,7 +246,7 @@ int dio_discard_file(struct fast_task_info *pTask) else { pFileContext->buff_offset = 0; - storage_nio_notify(pTask); //notify nio to deal + pFileContext->continue_callback(pTask); } return 0; @@ -353,6 +354,12 @@ int dio_read_file(struct fast_task_info *pTask) break; } + if (pFileContext->calc_crc32) + { + pFileContext->crc32 = CRC32_ex(pTask->data + pTask->length, + read_bytes, pFileContext->crc32); + } + pTask->length += read_bytes; pFileContext->offset += read_bytes; @@ -363,7 +370,7 @@ int dio_read_file(struct fast_task_info *pTask) if (pFileContext->offset < pFileContext->end) { - storage_nio_notify(pTask); //notify nio to deal + pFileContext->continue_callback(pTask); } else { @@ -371,6 +378,11 @@ int dio_read_file(struct fast_task_info *pTask) close(pFileContext->fd); pFileContext->fd = -1; + if (pFileContext->calc_crc32) + { + pFileContext->crc32 = CRC32_FINAL( \ + pFileContext->crc32); + } pFileContext->done_callback(pTask, result); } @@ -475,7 +487,7 @@ int dio_write_file(struct fast_task_info *pTask) if (pFileContext->offset < pFileContext->end) { pFileContext->buff_offset = 0; - storage_nio_notify(pTask); //notify nio to deal + pFileContext->continue_callback(pTask); } else { @@ -803,35 +815,34 @@ int dio_check_trunk_file_ex(int fd, const char *filename, const int64_t offset) { int result; char old_header[FDFS_TRUNK_FILE_HEADER_SIZE]; - char expect_header[FDFS_TRUNK_FILE_HEADER_SIZE]; + static char expect_header[FDFS_TRUNK_FILE_HEADER_SIZE] = {'\0'}; if (fc_safe_read(fd, old_header, FDFS_TRUNK_FILE_HEADER_SIZE) != FDFS_TRUNK_FILE_HEADER_SIZE) { result = errno != 0 ? errno : EIO; - logError("file: "__FILE__", line: %d, " \ - "read trunk header of file: %s fail, " \ - "errno: %d, error info: %s", \ - __LINE__, filename, \ + logError("file: "__FILE__", line: %d, " + "read trunk header of file: %s fail, " + "errno: %d, error info: %s", + __LINE__, filename, result, STRERROR(result)); return result; } - memset(expect_header, 0, sizeof(expect_header)); - if (memcmp(old_header, expect_header, \ + if (memcmp(old_header, expect_header, FDFS_TRUNK_FILE_HEADER_SIZE) != 0) { FDFSTrunkHeader srcOldTrunkHeader; FDFSTrunkHeader newOldTrunkHeader; trunk_unpack_header(old_header, &srcOldTrunkHeader); - memcpy(&newOldTrunkHeader, &srcOldTrunkHeader, \ + memcpy(&newOldTrunkHeader, &srcOldTrunkHeader, sizeof(FDFSTrunkHeader)); newOldTrunkHeader.alloc_size = 0; newOldTrunkHeader.file_size = 0; newOldTrunkHeader.file_type = 0; trunk_pack_header(&newOldTrunkHeader, old_header); - if (memcmp(old_header, expect_header, \ + if (memcmp(old_header, expect_header, FDFS_TRUNK_FILE_HEADER_SIZE) != 0) { char buff[256]; diff --git a/storage/storage_dio.h b/storage/storage_dio.h index 9d517fa..e58b90b 100644 --- a/storage/storage_dio.h +++ b/storage/storage_dio.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //storage_dio.h diff --git a/storage/storage_disk_recovery.c b/storage/storage_disk_recovery.c index 6cd9a11..372a365 100644 --- a/storage/storage_disk_recovery.c +++ b/storage/storage_disk_recovery.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ @@ -23,13 +23,14 @@ #include #include "fdfs_define.h" #include "fastcommon/logger.h" -#include "fdfs_global.h" #include "fastcommon/sockopt.h" #include "fastcommon/avl_tree.h" #include "fastcommon/shared_func.h" +#include "fdfs_global.h" #include "tracker_types.h" #include "tracker_proto.h" #include "storage_global.h" +#include "trunk_mgr/trunk_shared.h" #include "storage_func.h" #include "storage_sync.h" #include "tracker_client.h" @@ -42,17 +43,76 @@ typedef struct { int id; //trunk file id } FDFSTrunkFileIdInfo; +typedef struct recovery_thread_data { + int thread_index; //-1 for global + int result; + volatile int alive; + bool done; + const char *base_path; + pthread_t tid; +} RecoveryThreadData; + #define RECOVERY_BINLOG_FILENAME ".binlog.recovery" +#define RECOVERY_FLAG_FILENAME ".recovery.flag" #define RECOVERY_MARK_FILENAME ".recovery.mark" -#define MARK_ITEM_BINLOG_OFFSET "binlog_offset" -#define MARK_ITEM_FETCH_BINLOG_DONE "fetch_binlog_done" -#define MARK_ITEM_SAVED_STORAGE_STATUS "saved_storage_status" +#define FLAG_ITEM_RECOVERY_THREADS "recovery_threads" +#define FLAG_ITEM_SAVED_STORAGE_STATUS "saved_storage_status" +#define FLAG_ITEM_FETCH_BINLOG_DONE "fetch_binlog_done" +#define MARK_ITEM_BINLOG_OFFSET "binlog_offset" + +static int last_recovery_threads = -1; //for rebalance binlog data +static volatile int current_recovery_thread_count = 0; static int saved_storage_status = FDFS_STORAGE_STATUS_NONE; -static char *recovery_get_binlog_filename(const void *pArg, \ - char *full_filename); +static char *recovery_get_binlog_filename(const void *pArg, + char *full_filename); + +static int disk_recovery_write_to_binlog(FILE *fp, + const char *binlog_filename, StorageBinLogRecord *pRecord); + +static char *recovery_get_full_filename_ex(const char *pBasePath, + const int thread_index, const char *filename, char *full_filename) +{ + static char buff[MAX_PATH_SIZE]; + int len; + + if (full_filename == NULL) + { + full_filename = buff; + } + + len = snprintf(full_filename, MAX_PATH_SIZE, + "%s/data/%s", pBasePath, filename); + if (thread_index >= 0) + { + snprintf(full_filename + len, MAX_PATH_SIZE - len, + ".%d", thread_index); + } + return full_filename; +} + +static inline char *recovery_get_full_filename(const RecoveryThreadData + *pThreadData, const char *filename, char *full_filename) +{ + return recovery_get_full_filename_ex(pThreadData->base_path, + pThreadData->thread_index, filename, full_filename); +} + +static inline char *recovery_get_global_full_filename(const char *pBasePath, + const char *filename, char *full_filename) +{ + return recovery_get_full_filename_ex(pBasePath, -1, + filename, full_filename); +} + +static inline char *recovery_get_global_binlog_filename(const char *pBasePath, + char *full_filename) +{ + return recovery_get_global_full_filename(pBasePath, + RECOVERY_BINLOG_FILENAME, full_filename); +} static int storage_do_fetch_binlog(ConnectionInfo *pSrcStorage, \ const int store_path_index) @@ -64,9 +124,11 @@ static int storage_do_fetch_binlog(ConnectionInfo *pSrcStorage, \ int64_t in_bytes; int64_t file_bytes; int result; + int network_timeout; - pBasePath = g_fdfs_store_paths.paths[store_path_index]; - recovery_get_binlog_filename(pBasePath, full_binlog_filename); + pBasePath = g_fdfs_store_paths.paths[store_path_index].path; + recovery_get_full_filename_ex(pBasePath, 0, + RECOVERY_BINLOG_FILENAME, full_binlog_filename); memset(out_buff, 0, sizeof(out_buff)); pHeader = (TrackerHeader *)out_buff; @@ -74,21 +136,30 @@ static int storage_do_fetch_binlog(ConnectionInfo *pSrcStorage, \ long2buff(FDFS_GROUP_NAME_MAX_LEN + 1, pHeader->pkg_len); pHeader->cmd = STORAGE_PROTO_CMD_FETCH_ONE_PATH_BINLOG; strcpy(out_buff + sizeof(TrackerHeader), g_group_name); - *(out_buff + sizeof(TrackerHeader) + FDFS_GROUP_NAME_MAX_LEN) = \ + *(out_buff + sizeof(TrackerHeader) + FDFS_GROUP_NAME_MAX_LEN) = store_path_index; - if((result=tcpsenddata_nb(pSrcStorage->sock, out_buff, \ + if((result=tcpsenddata_nb(pSrcStorage->sock, out_buff, sizeof(out_buff), g_fdfs_network_timeout)) != 0) { - logError("file: "__FILE__", line: %d, " \ - "tracker server %s:%d, send data fail, " \ - "errno: %d, error info: %s.", \ - __LINE__, pSrcStorage->ip_addr, pSrcStorage->port, \ + logError("file: "__FILE__", line: %d, " + "storage server %s:%d, send data fail, " + "errno: %d, error info: %s.", + __LINE__, pSrcStorage->ip_addr, pSrcStorage->port, result, STRERROR(result)); return result; } - if ((result=fdfs_recv_header(pSrcStorage, &in_bytes)) != 0) + if (g_fdfs_network_timeout >= 600) + { + network_timeout = g_fdfs_network_timeout; + } + else + { + network_timeout = 600; + } + if ((result=fdfs_recv_header_ex(pSrcStorage, network_timeout, + &in_bytes)) != 0) { logError("file: "__FILE__", line: %d, " "fdfs_recv_header fail, result: %d", @@ -96,21 +167,20 @@ static int storage_do_fetch_binlog(ConnectionInfo *pSrcStorage, \ return result; } - if ((result=tcprecvfile(pSrcStorage->sock, full_binlog_filename, \ - in_bytes, 0, g_fdfs_network_timeout, \ - &file_bytes)) != 0) + if ((result=tcprecvfile(pSrcStorage->sock, full_binlog_filename, + in_bytes, 0, network_timeout, &file_bytes)) != 0) { - logError("file: "__FILE__", line: %d, " \ - "tracker server %s:%d, tcprecvfile fail, " \ - "errno: %d, error info: %s.", \ - __LINE__, pSrcStorage->ip_addr, pSrcStorage->port, \ + logError("file: "__FILE__", line: %d, " + "storage server %s:%d, tcprecvfile fail, " + "errno: %d, error info: %s.", + __LINE__, pSrcStorage->ip_addr, pSrcStorage->port, result, STRERROR(result)); return result; } - logInfo("file: "__FILE__", line: %d, " \ - "recovery binlog file size: %"PRId64, \ - __LINE__, file_bytes); + logInfo("file: "__FILE__", line: %d, " + "recovery binlog from %s:%d, file size: %"PRId64, __LINE__, + pSrcStorage->ip_addr, pSrcStorage->port, file_bytes); return 0; } @@ -119,12 +189,14 @@ static int recovery_get_src_storage_server(ConnectionInfo *pSrcStorage) { int result; int storage_count; + int i; + static unsigned int current_index = 0; TrackerServerInfo trackerServer; ConnectionInfo *pTrackerConn; FDFSGroupStat groupStat; FDFSStorageInfo storageStats[FDFS_MAX_SERVERS_EACH_GROUP]; FDFSStorageInfo *pStorageStat; - FDFSStorageInfo *pStorageEnd; + bool found; memset(pSrcStorage, 0, sizeof(ConnectionInfo)); pSrcStorage->sock = -1; @@ -135,14 +207,14 @@ static int recovery_get_src_storage_server(ConnectionInfo *pSrcStorage) while (g_continue_flag) { result = tracker_get_storage_max_status(&g_tracker_group, - g_group_name, g_tracker_client_ip.ips[0], + g_group_name, g_tracker_client_ip.ips[0].address, g_my_server_id_str, &saved_storage_status); if (result == ENOENT) { logWarning("file: "__FILE__", line: %d, " \ "current storage: %s does not exist " \ "in tracker server", __LINE__, \ - g_tracker_client_ip.ips[0]); + g_tracker_client_ip.ips[0].address); return ENOENT; } @@ -153,7 +225,7 @@ static int recovery_get_src_storage_server(ConnectionInfo *pSrcStorage) logInfo("file: "__FILE__", line: %d, " \ "current storage: %s 's status is %d" \ ", does not need recovery", __LINE__, \ - g_tracker_client_ip.ips[0], \ + g_tracker_client_ip.ips[0].address, \ saved_storage_status); return ENOENT; } @@ -164,7 +236,8 @@ static int recovery_get_src_storage_server(ConnectionInfo *pSrcStorage) logWarning("file: "__FILE__", line: %d, " \ "current storage: %s 's status is %d" \ ", does not need recovery", __LINE__, \ - g_tracker_client_ip.ips[0], saved_storage_status); + g_tracker_client_ip.ips[0].address, + saved_storage_status); return ENOENT; } @@ -174,6 +247,7 @@ static int recovery_get_src_storage_server(ConnectionInfo *pSrcStorage) sleep(1); } + found = false; while (g_continue_flag) { if ((pTrackerConn=tracker_get_connection_r(&trackerServer, \ @@ -232,8 +306,8 @@ static int recovery_get_src_storage_server(ConnectionInfo *pSrcStorage) continue; } - result = tracker_list_servers(pTrackerConn, \ - g_group_name, NULL, storageStats, \ + result = tracker_list_servers(pTrackerConn, + g_group_name, NULL, storageStats, FDFS_MAX_SERVERS_EACH_GROUP, &storage_count); tracker_close_connection_ex(pTrackerConn, result != 0); if (result != 0) @@ -252,10 +326,9 @@ static int recovery_get_src_storage_server(ConnectionInfo *pSrcStorage) continue; } - pStorageEnd = storageStats + storage_count; - for (pStorageStat=storageStats; pStorageStatid, g_my_server_id_str) == 0) { continue; @@ -263,14 +336,14 @@ static int recovery_get_src_storage_server(ConnectionInfo *pSrcStorage) if (pStorageStat->status == FDFS_STORAGE_STATUS_ACTIVE) { - strcpy(pSrcStorage->ip_addr, \ - pStorageStat->ip_addr); + found = true; + strcpy(pSrcStorage->ip_addr, pStorageStat->ip_addr); pSrcStorage->port = pStorageStat->storage_port; break; } } - if (pStorageStat < pStorageEnd) //found src storage server + if (found) //found src storage server { break; } @@ -283,188 +356,239 @@ static int recovery_get_src_storage_server(ConnectionInfo *pSrcStorage) return EINTR; } - logDebug("file: "__FILE__", line: %d, " \ - "disk recovery: get source storage server %s:%d", \ + logDebug("file: "__FILE__", line: %d, " + "disk recovery: get source storage server %s:%d", __LINE__, pSrcStorage->ip_addr, pSrcStorage->port); return 0; } -static char *recovery_get_full_filename(const void *pArg, \ - const char *filename, char *full_filename) +static char *recovery_get_binlog_filename(const void *pArg, + char *full_filename) { - const char *pBasePath; - static char buff[MAX_PATH_SIZE]; - - pBasePath = (const char *)pArg; - if (full_filename == NULL) - { - full_filename = buff; - } - - snprintf(full_filename, MAX_PATH_SIZE, \ - "%s/data/%s", pBasePath, filename); - - return full_filename; -} - -static char *recovery_get_binlog_filename(const void *pArg, \ - char *full_filename) -{ - return recovery_get_full_filename(pArg, \ + return recovery_get_full_filename((const RecoveryThreadData *)pArg, RECOVERY_BINLOG_FILENAME, full_filename); } -static char *recovery_get_mark_filename(const void *pArg, \ - char *full_filename) +static char *recovery_get_flag_filename(const char *pBasePath, + char *full_filename) { - return recovery_get_full_filename(pArg, \ + return recovery_get_global_full_filename(pBasePath, + RECOVERY_FLAG_FILENAME, full_filename); +} + +static char *recovery_get_mark_filename(const RecoveryThreadData *pThreadData, + char *full_filename) +{ + return recovery_get_full_filename(pThreadData, RECOVERY_MARK_FILENAME, full_filename); } +static int storage_disk_recovery_delete_thread_files(const char *pBasePath, + const int index_start, const int index_end) +{ + int i; + char mark_filename[MAX_PATH_SIZE]; + char binlog_filename[MAX_PATH_SIZE]; + + for (i=index_start; ibinlog_offset, \ - MARK_ITEM_FETCH_BINLOG_DONE); + len = sprintf(buff, + "%s=%"PRId64"\n", + MARK_ITEM_BINLOG_OFFSET, binlog_offset); - return storage_write_to_fd(pReader->mark_fd, \ - recovery_get_mark_filename, pBasePath, buff, len); + return safeWriteToFile(mark_filename, buff, len); } -static int recovery_init_binlog_file(const char *pBasePath) +static inline int recovery_write_to_mark_file(StorageBinLogReader *pReader) +{ + return do_write_to_mark_file(pReader->mark_filename, + pReader->binlog_offset); +} + +static int recovery_init_global_binlog_file(const char *pBasePath) { char full_binlog_filename[MAX_PATH_SIZE]; char buff[1]; *buff = '\0'; - recovery_get_binlog_filename(pBasePath, full_binlog_filename); + recovery_get_full_filename_ex(pBasePath, 0, + RECOVERY_BINLOG_FILENAME, full_binlog_filename); return writeToFile(full_binlog_filename, buff, 0); } -static int recovery_init_mark_file(const char *pBasePath, \ - const bool fetch_binlog_done) +static int recovery_init_flag_file(const char *pBasePath, + const bool fetch_binlog_done, const int recovery_threads) { char full_filename[MAX_PATH_SIZE]; - char buff[128]; - int len; - recovery_get_mark_filename(pBasePath, full_filename); - - len = sprintf(buff, \ - "%s=%d\n" \ - "%s=0\n" \ - "%s=%d\n", \ - MARK_ITEM_SAVED_STORAGE_STATUS, saved_storage_status, \ - MARK_ITEM_BINLOG_OFFSET, \ - MARK_ITEM_FETCH_BINLOG_DONE, fetch_binlog_done); - return writeToFile(full_filename, buff, len); + recovery_get_flag_filename(pBasePath, full_filename); + return do_write_to_flag_file(full_filename, + fetch_binlog_done, recovery_threads); } -static int recovery_reader_init(const char *pBasePath, \ +static int recovery_load_params_from_flag_file(const char *full_flag_filename) +{ + IniContext iniContext; + int result; + + memset(&iniContext, 0, sizeof(IniContext)); + if ((result=iniLoadFromFile(full_flag_filename, + &iniContext)) != 0) + { + logError("file: "__FILE__", line: %d, " + "load from flag file \"%s\" fail, " + "error code: %d", __LINE__, + full_flag_filename, result); + return result; + } + + if (!iniGetBoolValue(NULL, FLAG_ITEM_FETCH_BINLOG_DONE, + &iniContext, false)) + { + iniFreeContext(&iniContext); + + logInfo("file: "__FILE__", line: %d, " + "flag file \"%s\", %s=0, " + "need to fetch binlog again", __LINE__, + full_flag_filename, FLAG_ITEM_FETCH_BINLOG_DONE); + return EAGAIN; + } + + saved_storage_status = iniGetIntValue(NULL, + FLAG_ITEM_SAVED_STORAGE_STATUS, &iniContext, -1); + if (saved_storage_status < 0) + { + iniFreeContext(&iniContext); + + logError("file: "__FILE__", line: %d, " + "in flag file \"%s\", %s: %d < 0", __LINE__, + full_flag_filename, FLAG_ITEM_SAVED_STORAGE_STATUS, + saved_storage_status); + return EINVAL; + } + + last_recovery_threads = iniGetIntValue(NULL, + FLAG_ITEM_RECOVERY_THREADS, &iniContext, -1); + + iniFreeContext(&iniContext); + return 0; +} + +static int recovery_reader_init(const RecoveryThreadData *pThreadData, StorageBinLogReader *pReader) { - char full_mark_filename[MAX_PATH_SIZE]; IniContext iniContext; int result; memset(pReader, 0, sizeof(StorageBinLogReader)); - pReader->mark_fd = -1; pReader->binlog_fd = -1; pReader->binlog_index = g_binlog_index + 1; - pReader->binlog_buff.buffer = (char *)malloc( \ + pReader->binlog_buff.buffer = (char *)malloc( STORAGE_BINLOG_BUFFER_SIZE); if (pReader->binlog_buff.buffer == NULL) { - logError("file: "__FILE__", line: %d, " \ - "malloc %d bytes fail, " \ - "errno: %d, error info: %s", \ - __LINE__, STORAGE_BINLOG_BUFFER_SIZE, \ + logError("file: "__FILE__", line: %d, " + "malloc %d bytes fail, " + "errno: %d, error info: %s", + __LINE__, STORAGE_BINLOG_BUFFER_SIZE, errno, STRERROR(errno)); return errno != 0 ? errno : ENOMEM; } pReader->binlog_buff.current = pReader->binlog_buff.buffer; - recovery_get_mark_filename(pBasePath, full_mark_filename); + recovery_get_mark_filename(pThreadData, pReader->mark_filename); memset(&iniContext, 0, sizeof(IniContext)); - if ((result=iniLoadFromFile(full_mark_filename, &iniContext)) != 0) + if ((result=iniLoadFromFile(pReader->mark_filename, + &iniContext)) != 0) { - logError("file: "__FILE__", line: %d, " \ - "load from mark file \"%s\" fail, " \ - "error code: %d", __LINE__, \ - full_mark_filename, result); + logError("file: "__FILE__", line: %d, " + "load from mark file \"%s\" fail, " + "error code: %d", __LINE__, + pReader->mark_filename, result); return result; } - if (!iniGetBoolValue(NULL, MARK_ITEM_FETCH_BINLOG_DONE, \ - &iniContext, false)) - { - iniFreeContext(&iniContext); - - logInfo("file: "__FILE__", line: %d, " \ - "mark file \"%s\", %s=0, " \ - "need to fetch binlog again", __LINE__, \ - full_mark_filename, MARK_ITEM_FETCH_BINLOG_DONE); - return EAGAIN; - } - - saved_storage_status = iniGetIntValue(NULL, \ - MARK_ITEM_SAVED_STORAGE_STATUS, &iniContext, -1); - if (saved_storage_status < 0) - { - iniFreeContext(&iniContext); - - logError("file: "__FILE__", line: %d, " \ - "in mark file \"%s\", %s: %d < 0", __LINE__, \ - full_mark_filename, MARK_ITEM_SAVED_STORAGE_STATUS, \ - saved_storage_status); - return EINVAL; - } - - pReader->binlog_offset = iniGetInt64Value(NULL, \ + pReader->binlog_offset = iniGetInt64Value(NULL, MARK_ITEM_BINLOG_OFFSET, &iniContext, -1); if (pReader->binlog_offset < 0) { @@ -473,26 +597,15 @@ static int recovery_reader_init(const char *pBasePath, \ logError("file: "__FILE__", line: %d, " \ "in mark file \"%s\", %s: "\ "%"PRId64" < 0", __LINE__, \ - full_mark_filename, MARK_ITEM_BINLOG_OFFSET, \ + pReader->mark_filename, MARK_ITEM_BINLOG_OFFSET, \ pReader->binlog_offset); return EINVAL; } iniFreeContext(&iniContext); - pReader->mark_fd = open(full_mark_filename, O_WRONLY | O_CREAT, 0644); - if (pReader->mark_fd < 0) - { - logError("file: "__FILE__", line: %d, " \ - "open mark file \"%s\" fail, " \ - "error no: %d, error info: %s", \ - __LINE__, full_mark_filename, \ - errno, STRERROR(errno)); - return errno != 0 ? errno : ENOENT; - } - - if ((result=storage_open_readable_binlog(pReader, \ - recovery_get_binlog_filename, pBasePath)) != 0) + if ((result=storage_open_readable_binlog(pReader, + recovery_get_binlog_filename, pThreadData)) != 0) { return result; } @@ -500,30 +613,108 @@ static int recovery_reader_init(const char *pBasePath, \ return 0; } -static int recovery_reader_check_init(const char *pBasePath, \ - StorageBinLogReader *pReader) +static int recovery_reader_check_init(const RecoveryThreadData *pThreadData, + StorageBinLogReader *pReader) { if (pReader->binlog_fd >= 0 && pReader->binlog_buff.buffer != NULL) { return 0; } - return recovery_reader_init(pBasePath, pReader); + return recovery_reader_init(pThreadData, pReader); } -static int storage_do_recovery(const char *pBasePath, StorageBinLogReader *pReader, \ - ConnectionInfo *pSrcStorage) +static int recovery_download_file_to_local(StorageBinLogRecord *pRecord, + ConnectionInfo *pTrackerServer, ConnectionInfo *pStorageConn) { + int result; + bool bTrunkFile; + char local_filename[MAX_PATH_SIZE]; + char tmp_filename[MAX_PATH_SIZE + 32]; + char *download_filename; + int64_t file_size; + + if (fdfs_is_trunk_file(pRecord->filename, pRecord->filename_len)) + { + FDFSTrunkFullInfo trunk_info; + char *pTrunkPathEnd; + char *pLocalFilename; + + bTrunkFile = true; + if (fdfs_decode_trunk_info(pRecord->store_path_index, + pRecord->true_filename, pRecord->true_filename_len, + &trunk_info) != 0) + { + return -EINVAL; + } + + trunk_get_full_filename(&trunk_info, + local_filename, sizeof(local_filename)); + + pTrunkPathEnd = strrchr(pRecord->filename, '/'); + pLocalFilename = strrchr(local_filename, '/'); + if (pTrunkPathEnd == NULL || pLocalFilename == NULL) + { + return -EINVAL; + } + sprintf(pTrunkPathEnd + 1, "%s", pLocalFilename + 1); + } + else + { + bTrunkFile = false; + sprintf(local_filename, "%s/data/%s", + g_fdfs_store_paths.paths[pRecord->store_path_index].path, + pRecord->true_filename); + } + + if (access(local_filename, F_OK) == 0) + { + sprintf(tmp_filename, "%s.recovery.tmp", local_filename); + download_filename = tmp_filename; + } + else + { + download_filename = local_filename; + } + + result = storage_download_file_to_file(pTrackerServer, + pStorageConn, g_group_name, pRecord->filename, + download_filename, &file_size); + if (result == 0) + { + if (download_filename != local_filename) + { + if (rename(download_filename, local_filename) != 0) + { + logError("file: "__FILE__", line: %d, " + "rename file %s to %s fail, " + "errno: %d, error info: %s", __LINE__, + download_filename, local_filename, + errno, STRERROR(errno)); + return errno != 0 ? errno : EPERM; + } + } + if (!bTrunkFile) + { + set_file_utimes(local_filename, pRecord->timestamp); + } + } + + return result; +} + +static int storage_do_recovery(RecoveryThreadData *pThreadData, + StorageBinLogReader *pReader, ConnectionInfo *pSrcStorage) +{ + TrackerServerInfo trackerServer; ConnectionInfo *pTrackerServer; ConnectionInfo *pStorageConn; - FDFSTrunkFullInfo trunk_info; StorageBinLogRecord record; int record_length; int result; int log_level; int count; int store_path_index; - int64_t file_size; int64_t total_count; int64_t success_count; int64_t noent_count; @@ -531,310 +722,726 @@ static int storage_do_recovery(const char *pBasePath, StorageBinLogReader *pRead char local_filename[MAX_PATH_SIZE]; char src_filename[MAX_PATH_SIZE]; - pTrackerServer = g_tracker_group.servers->connections; //TODO: fix me !!! + pTrackerServer = tracker_get_connection_r(&trackerServer, &result); + if (pTrackerServer == NULL) + { + logError("file: "__FILE__", line: %d, " + "get tracker connection fail, result: %d", + __LINE__, result); + return result; + } + count = 0; total_count = 0; success_count = 0; noent_count = 0; result = 0; - logInfo("file: "__FILE__", line: %d, " \ - "disk recovery: recovering files of data path: %s ...", \ - __LINE__, pBasePath); + logInfo("file: "__FILE__", line: %d, " + "disk recovery thread #%d, src storage server %s:%d, " + "recovering files of data path: %s ...", __LINE__, + pThreadData->thread_index, pSrcStorage->ip_addr, + pSrcStorage->port, pThreadData->base_path); bContinueFlag = true; while (bContinueFlag) - { - if ((result=recovery_reader_check_init(pBasePath, pReader)) != 0) { - break; - } - if ((pStorageConn=tracker_make_connection(pSrcStorage, &result)) == NULL) - { - sleep(5); - continue; - } + if ((result=recovery_reader_check_init(pThreadData, pReader)) != 0) + { + break; + } + if ((pStorageConn=tracker_make_connection(pSrcStorage, + &result)) == NULL) + { + sleep(5); + continue; + } - while (g_continue_flag) - { - result=storage_binlog_read(pReader, &record, &record_length); - if (result != 0) - { - if (result == ENOENT) - { - result = 0; - } - bContinueFlag = false; - break; - } - - total_count++; - if (record.op_type == STORAGE_OP_TYPE_SOURCE_CREATE_FILE - || record.op_type == STORAGE_OP_TYPE_REPLICA_CREATE_FILE) - { - bool bTrunkFile; - - if (fdfs_is_trunk_file(record.filename, \ - record.filename_len)) - { - char *pTrunkPathEnd; - char *pLocalFilename; - - bTrunkFile = true; - if (fdfs_decode_trunk_info(record.store_path_index, \ - record.true_filename, record.true_filename_len,\ - &trunk_info) != 0) - { - pReader->binlog_offset += record_length; - count++; - continue; - } - - trunk_get_full_filename(&trunk_info, \ - local_filename, sizeof(local_filename)); - - pTrunkPathEnd = strrchr(record.filename, '/'); - pLocalFilename = strrchr(local_filename, '/'); - if (pTrunkPathEnd == NULL || pLocalFilename == NULL) - { - pReader->binlog_offset += record_length; - count++; - continue; - } - sprintf(pTrunkPathEnd + 1, "%s", pLocalFilename + 1); - } - else - { - bTrunkFile = false; - sprintf(local_filename, "%s/data/%s", \ - g_fdfs_store_paths.paths[record.store_path_index], \ - record.true_filename); - } - - result = storage_download_file_to_file(pTrackerServer, \ - pStorageConn, g_group_name, \ - record.filename, local_filename, \ - &file_size); - if (result == 0) - { - if (!bTrunkFile) - { - set_file_utimes(local_filename, \ - record.timestamp); - } - - success_count++; - } - else if (result == ENOENT) - { - result = 0; - noent_count++; - } - else + while (g_continue_flag) + { + result = storage_binlog_read(pReader, &record, &record_length); + if (result != 0) { - break; - } - } - else if (record.op_type == STORAGE_OP_TYPE_SOURCE_CREATE_LINK - || record.op_type == STORAGE_OP_TYPE_REPLICA_CREATE_LINK) - { - if (record.src_filename_len == 0) - { - logError("file: "__FILE__", line: %d, " \ - "invalid binlog line, filename: %s, " \ - "expect src filename", __LINE__, \ - record.filename); - result = EINVAL; - bContinueFlag = false; - break; - } + if (result == ENOENT) + { + pThreadData->done = true; + result = 0; + } + bContinueFlag = false; + break; + } - if ((result=storage_split_filename_ex(record.filename, \ - &record.filename_len, record.true_filename, \ - &store_path_index)) != 0) - { - bContinueFlag = false; - break; - } - sprintf(local_filename, "%s/data/%s", \ - g_fdfs_store_paths.paths[store_path_index], \ - record.true_filename); - - if ((result=storage_split_filename_ex( \ - record.src_filename, &record.src_filename_len,\ - record.true_filename, &store_path_index)) != 0) - { - bContinueFlag = false; - break; - } - sprintf(src_filename, "%s/data/%s", \ - g_fdfs_store_paths.paths[store_path_index], \ - record.true_filename); - if (symlink(src_filename, local_filename) == 0) - { - success_count++; - } - else - { - result = errno != 0 ? errno : ENOENT; - if (result == ENOENT || result == EEXIST) - { - log_level = LOG_DEBUG; - } - else - { - log_level = LOG_ERR; - } - - log_it_ex(&g_log_context, log_level, \ - "file: "__FILE__", line: %d, " \ - "link file %s to %s fail, " \ - "errno: %d, error info: %s", __LINE__,\ - src_filename, local_filename, \ - result, STRERROR(result)); - - if (result != ENOENT && result != EEXIST) - { - bContinueFlag = false; - break; - } - else + total_count++; + if (record.op_type == STORAGE_OP_TYPE_SOURCE_CREATE_FILE + || record.op_type == STORAGE_OP_TYPE_REPLICA_CREATE_FILE) + { + result = recovery_download_file_to_local(&record, + pTrackerServer, pStorageConn); + if (result == 0) + { + success_count++; + } + else if (result == -EINVAL) { result = 0; } - } - } - else - { - logError("file: "__FILE__", line: %d, " \ - "invalid file op type: %d", \ - __LINE__, record.op_type); - result = EINVAL; - bContinueFlag = false; - break; - } + else if (result == ENOENT) + { + result = 0; + noent_count++; + } + else + { + break; + } + } + else if (record.op_type == STORAGE_OP_TYPE_SOURCE_CREATE_LINK + || record.op_type == STORAGE_OP_TYPE_REPLICA_CREATE_LINK) + { + if (record.src_filename_len == 0) + { + logError("file: "__FILE__", line: %d, " \ + "invalid binlog line, filename: %s, " \ + "expect src filename", __LINE__, \ + record.filename); + result = EINVAL; + bContinueFlag = false; + break; + } - pReader->binlog_offset += record_length; - count++; - if (count == 1000) - { - logDebug("file: "__FILE__", line: %d, " \ - "disk recovery: recover path: %s, " \ - "file count: %"PRId64 \ - ", success count: %"PRId64", noent_count: %"PRId64, \ - __LINE__, pBasePath, total_count, \ - success_count, noent_count); - recovery_write_to_mark_file(pBasePath, pReader); - count = 0; - } - } + if ((result=storage_split_filename_ex(record.filename, \ + &record.filename_len, record.true_filename, \ + &store_path_index)) != 0) + { + bContinueFlag = false; + break; + } + sprintf(local_filename, "%s/data/%s", \ + g_fdfs_store_paths.paths[store_path_index].path, \ + record.true_filename); - tracker_close_connection_ex(pStorageConn, result != 0); - recovery_write_to_mark_file(pBasePath, pReader); - if (bContinueFlag) - { - storage_reader_destroy(pReader); + if ((result=storage_split_filename_ex( \ + record.src_filename, &record.src_filename_len,\ + record.true_filename, &store_path_index)) != 0) + { + bContinueFlag = false; + break; + } + sprintf(src_filename, "%s/data/%s", \ + g_fdfs_store_paths.paths[store_path_index].path, \ + record.true_filename); + if (symlink(src_filename, local_filename) == 0) + { + success_count++; + } + else + { + result = errno != 0 ? errno : ENOENT; + if (result == ENOENT || result == EEXIST) + { + log_level = LOG_DEBUG; + } + else + { + log_level = LOG_ERR; + } + + log_it_ex(&g_log_context, log_level, \ + "file: "__FILE__", line: %d, " \ + "link file %s to %s fail, " \ + "errno: %d, error info: %s", __LINE__,\ + src_filename, local_filename, \ + result, STRERROR(result)); + + if (result != ENOENT && result != EEXIST) + { + bContinueFlag = false; + break; + } + else + { + result = 0; + } + } + } + else + { + logError("file: "__FILE__", line: %d, " \ + "invalid file op type: %d", \ + __LINE__, record.op_type); + result = EINVAL; + bContinueFlag = false; + break; + } + + pReader->binlog_offset += record_length; + count++; + if (count == 1000) + { + logDebug("file: "__FILE__", line: %d, " + "disk recovery thread #%d recover path: %s, " + "file count: %"PRId64", success count: %"PRId64 + ", noent_count: %"PRId64, __LINE__, + pThreadData->thread_index, + pThreadData->base_path, total_count, + success_count, noent_count); + recovery_write_to_mark_file(pReader); + count = 0; + } + } + + tracker_close_connection_ex(pStorageConn, result != 0); + recovery_write_to_mark_file(pReader); + + if (!g_continue_flag) + { + bContinueFlag = false; + } + else if (bContinueFlag) + { + storage_reader_destroy(pReader); + } + + if (count > 0) + { + logInfo("file: "__FILE__", line: %d, " + "disk recovery thread #%d, recover path: %s, " + "file count: %"PRId64", success count: " + "%"PRId64", noent_count: %"PRId64, + __LINE__, pThreadData->thread_index, + pThreadData->base_path, total_count, + success_count, noent_count); + count = 0; + } + + if (bContinueFlag) + { + sleep(5); + } } - if (count > 0) - { - count = 0; + tracker_close_connection_ex(pTrackerServer, true); - logInfo("file: "__FILE__", line: %d, " \ - "disk recovery: recover path: %s, " \ - "file count: %"PRId64 \ - ", success count: %"PRId64", noent_count: %"PRId64, \ - __LINE__, pBasePath, total_count, success_count, noent_count); - } - else + if (pThreadData->done) { - sleep(5); - } + logInfo("file: "__FILE__", line: %d, " + "disk recovery thread #%d, src storage server %s:%d, " + "recover files of data path: %s done", __LINE__, + pThreadData->thread_index, pSrcStorage->ip_addr, + pSrcStorage->port, pThreadData->base_path); } - if (result == 0) - { - logInfo("file: "__FILE__", line: %d, " \ - "disk recovery: recover files of data path: %s done", \ - __LINE__, pBasePath); - } - - return result; + return g_continue_flag ? result :EINTR; } -int storage_disk_recovery_restore(const char *pBasePath) +static void *storage_disk_recovery_restore_entrance(void *arg) { - char full_binlog_filename[MAX_PATH_SIZE]; - char full_mark_filename[MAX_PATH_SIZE]; - ConnectionInfo srcStorage; - int result; StorageBinLogReader reader; + RecoveryThreadData *pThreadData; + ConnectionInfo srcStorage; - recovery_get_binlog_filename(pBasePath, full_binlog_filename); - recovery_get_mark_filename(pBasePath, full_mark_filename); + pThreadData = (RecoveryThreadData *)arg; + pThreadData->tid = pthread_self(); + __sync_add_and_fetch(&pThreadData->alive, 1); + __sync_add_and_fetch(¤t_recovery_thread_count, 1); - if (!(fileExists(full_mark_filename) && \ - fileExists(full_binlog_filename))) + do + { + if ((pThreadData->result=recovery_get_src_storage_server(&srcStorage)) != 0) + { + if (pThreadData->result == ENOENT) + { + logWarning("file: "__FILE__", line: %d, " + "no source storage server, " + "disk recovery finished!", __LINE__); + pThreadData->result = 0; + } + break; + } + + if ((pThreadData->result=recovery_reader_init(pThreadData, &reader)) != 0) + { + storage_reader_destroy(&reader); + break; + } + + pThreadData->result = storage_do_recovery(pThreadData, &reader, &srcStorage); + + recovery_write_to_mark_file(&reader); + storage_reader_destroy(&reader); + + } while (0); + + __sync_sub_and_fetch(¤t_recovery_thread_count, 1); + __sync_sub_and_fetch(&pThreadData->alive, 1); + sleep(1); + + return NULL; +} + +static int storage_disk_recovery_old_version_migrate(const char *pBasePath) +{ + char old_binlog_filename[MAX_PATH_SIZE]; + char old_mark_filename[MAX_PATH_SIZE]; + char new_binlog_filename[MAX_PATH_SIZE]; + char new_mark_filename[MAX_PATH_SIZE]; + int result; + + recovery_get_global_binlog_filename(pBasePath, old_binlog_filename); + recovery_get_global_full_filename(pBasePath, + RECOVERY_MARK_FILENAME, old_mark_filename); + + if (!(fileExists(old_mark_filename) && + fileExists(old_binlog_filename))) { - return 0; + return ENOENT; } - logInfo("file: "__FILE__", line: %d, " \ - "disk recovery: begin recovery data path: %s ...", \ - __LINE__, pBasePath); + logInfo("file: "__FILE__", line: %d, " + "try to migrate data from old version ...", __LINE__); - if ((result=recovery_get_src_storage_server(&srcStorage)) != 0) + result = recovery_load_params_from_flag_file(old_mark_filename); + if (result != 0) + { + if (result == EAGAIN) + { + unlink(old_mark_filename); + } + return result; + } + + if ((result=recovery_init_flag_file(pBasePath, true, 1)) != 0) + { + return result; + } + + recovery_get_full_filename_ex(pBasePath, 0, + RECOVERY_MARK_FILENAME, new_mark_filename); + if (rename(old_mark_filename, new_mark_filename) != 0) { - if (result == ENOENT) - { - logWarning("file: "__FILE__", line: %d, " \ - "no source storage server, " \ - "disk recovery finished!", __LINE__); - return storage_disk_recovery_finish(pBasePath); - } - else - { - return result; - } + logError("file: "__FILE__", line: %d, " + "rename file %s to %s fail, " + "errno: %d, error info: %s", __LINE__, + old_mark_filename, new_mark_filename, + errno, STRERROR(errno)); + return errno != 0 ? errno : EPERM; } - if ((result=recovery_reader_init(pBasePath, &reader)) != 0) + recovery_get_full_filename_ex(pBasePath, 0, + RECOVERY_BINLOG_FILENAME, new_binlog_filename); + if (rename(old_binlog_filename, new_binlog_filename) != 0) { - storage_reader_destroy(&reader); - return result; + logError("file: "__FILE__", line: %d, " + "rename file %s to %s fail, " + "errno: %d, error info: %s", __LINE__, + old_binlog_filename, new_binlog_filename, + errno, STRERROR(errno)); + return errno != 0 ? errno : EPERM; } - result = storage_do_recovery(pBasePath, &reader, &srcStorage); + logInfo("file: "__FILE__", line: %d, " + "migrate data from old version successfully.", __LINE__); + return 0; +} - recovery_write_to_mark_file(pBasePath, &reader); - storage_reader_destroy(&reader); +static int do_dispatch_binlog_for_threads(const char *pBasePath) +{ + typedef struct { + FILE *fp; + int64_t count; + char binlog_filename[MAX_PATH_SIZE]; + char temp_filename[MAX_PATH_SIZE]; + } RecoveryDispatchInfo; - if (result != 0) - { - return result; - } + char mark_filename[MAX_PATH_SIZE]; + string_t log_buff; + char buff[2 * 1024]; + struct stat file_stat; + RecoveryThreadData thread_data; + StorageBinLogReader reader; + StorageBinLogRecord record; + int record_length; + RecoveryDispatchInfo *dispatchs; + RecoveryDispatchInfo *disp; + int64_t total_count; + int hash_code; + int bytes; + int result; + int i; - while (g_continue_flag) - { - if (storage_report_storage_status(g_my_server_id_str, \ - g_tracker_client_ip.ips[0], saved_storage_status) == 0) - { - break; - } + bytes = sizeof(RecoveryDispatchInfo) * g_disk_recovery_threads; + dispatchs = (RecoveryDispatchInfo *)malloc(bytes); + if (dispatchs == NULL) + { + logError("file: "__FILE__", line: %d, " + "malloc %d bytes fail", + __LINE__, bytes); + return ENOMEM; + } + memset(dispatchs, 0, bytes); - sleep(5); - } + result = 0; + for (i=0; i 0) + { + hash_code = Time33Hash(record.src_filename, + record.src_filename_len); + } + else + { + hash_code = Time33Hash(record.filename, + record.filename_len); + } + disp = dispatchs + ((unsigned int)hash_code) % + g_disk_recovery_threads; + if ((result=disk_recovery_write_to_binlog(disp->fp, + disp->temp_filename, &record)) != 0) + { + break; + } + disp->count++; + } + + storage_reader_destroy(&reader); + if (result != 0) + { + break; + } + } + + total_count = 0; + *buff = '\0'; + log_buff.str = buff; + log_buff.len = 0; + for (i=0; i record count: %"PRId64"%s", + __LINE__, total_count, log_buff.str); + } + return result; +} + +static int storage_disk_recovery_dispatch_binlog_for_threads( + const char *pBasePath) +{ + int result; + int i; + char binlog_filename[MAX_PATH_SIZE]; + + if (last_recovery_threads <= 0) + { + logError("file: "__FILE__", line: %d, " + "invalid last recovery threads: %d, " + "retry restore data for %s again ...", + __LINE__, last_recovery_threads, pBasePath); + return EAGAIN; + } + + for (i=0; i 0); + + if (__sync_fetch_and_add(¤t_recovery_thread_count, 0) > 0) + { +#define MAX_WAIT_COUNT 30 + + sig = SIGINT; + for (i=0; i= MAX_WAIT_COUNT / 2) + { + sig = SIGTERM; + } + + for (k=0; k 0) + { + pthread_kill(thread_data[k].tid, sig); + } + } + + logInfo("file: "__FILE__", line: %d, " + "waiting for recovery threads exit, " + "waiting count: %d, current thread count: %d", + __LINE__, i+1, thread_count); + sleep(1); + } + } + + sleep(1); //wait for thread exit + free(thread_data); + free(args); + free(recovery_tids); + + if (!g_continue_flag) + { + return EINTR; + } + + while (g_continue_flag) + { + if (storage_report_storage_status(g_my_server_id_str, + g_tracker_client_ip.ips[0].address, + saved_storage_status) == 0) + { + break; + } + + sleep(5); + } + + if (!g_continue_flag) + { + return EINTR; + } + + for (i=0; iline) > 0) { return 0; @@ -863,14 +1470,54 @@ static int tree_write_file_walk_callback(void *data, void *args) else { result = errno != 0 ? errno : EIO; - logError("file: "__FILE__", line: %d, " \ - "write to binlog file fail, " \ - "errno: %d, error info: %s.", \ + logError("file: "__FILE__", line: %d, " + "write to binlog file fail, " + "errno: %d, error info: %s.", __LINE__, result, STRERROR(result)); return EIO; } } +static int disk_recovery_write_to_binlog(FILE *fp, + const char *binlog_filename, StorageBinLogRecord *pRecord) +{ + int result; + if (pRecord->op_type == STORAGE_OP_TYPE_SOURCE_CREATE_FILE + || pRecord->op_type == STORAGE_OP_TYPE_REPLICA_CREATE_FILE) + { + if (fprintf(fp, "%d %c %s\n", + (int)pRecord->timestamp, + pRecord->op_type, pRecord->filename) < 0) + { + result = errno != 0 ? errno : EIO; + logError("file: "__FILE__", line: %d, " + "write to file: %s fail, " + "errno: %d, error info: %s.", + __LINE__, binlog_filename, + result, STRERROR(result)); + return result; + } + } + else + { + if (fprintf(fp, "%d %c %s %s\n", + (int)pRecord->timestamp, + pRecord->op_type, pRecord->filename, + pRecord->src_filename) < 0) + { + result = errno != 0 ? errno : EIO; + logError("file: "__FILE__", line: %d, " + "write to file: %s fail, " + "errno: %d, error info: %s.", + __LINE__, binlog_filename, + result, STRERROR(result)); + return result; + } + } + + return 0; +} + static int storage_do_split_trunk_binlog(const int store_path_index, StorageBinLogReader *pReader) { @@ -886,8 +1533,8 @@ static int storage_do_split_trunk_binlog(const int store_path_index, int record_length; int result; - pBasePath = g_fdfs_store_paths.paths[store_path_index]; - recovery_get_full_filename(pBasePath, \ + pBasePath = g_fdfs_store_paths.paths[store_path_index].path; + recovery_get_full_filename_ex(pBasePath, -1, RECOVERY_BINLOG_FILENAME".tmp", tmpFullFilename); fp = fopen(tmpFullFilename, "w"); if (fp == NULL) @@ -974,38 +1621,11 @@ static int storage_do_split_trunk_binlog(const int store_path_index, } else { - if (record.op_type == STORAGE_OP_TYPE_SOURCE_CREATE_FILE - || record.op_type == STORAGE_OP_TYPE_REPLICA_CREATE_FILE) - { - if (fprintf(fp, "%d %c %s\n", \ - (int)record.timestamp, \ - record.op_type, record.filename) < 0) - { - result = errno != 0 ? errno : EIO; - logError("file: "__FILE__", line: %d, " \ - "write to file: %s fail, " \ - "errno: %d, error info: %s.", \ - __LINE__, tmpFullFilename, - result, STRERROR(result)); - break; - } - } - else - { - if (fprintf(fp, "%d %c %s %s\n", \ - (int)record.timestamp, \ - record.op_type, record.filename, \ - record.src_filename) < 0) - { - result = errno != 0 ? errno : EIO; - logError("file: "__FILE__", line: %d, " \ - "write to file: %s fail, " \ - "errno: %d, error info: %s.", \ - __LINE__, tmpFullFilename, - result, STRERROR(result)); - break; - } - } + if ((result=disk_recovery_write_to_binlog(fp, + tmpFullFilename, &record)) != 0) + { + break; + } } } @@ -1036,7 +1656,7 @@ static int storage_do_split_trunk_binlog(const int store_path_index, return result; } - recovery_get_full_filename(pBasePath, \ + recovery_get_full_filename_ex(pBasePath, 0, RECOVERY_BINLOG_FILENAME, binlogFullFilename); if (rename(tmpFullFilename, binlogFullFilename) != 0) { @@ -1053,37 +1673,45 @@ static int storage_do_split_trunk_binlog(const int store_path_index, static int storage_disk_recovery_split_trunk_binlog(const int store_path_index) { - char *pBasePath; + char mark_filename[MAX_PATH_SIZE]; + RecoveryThreadData thread_data; StorageBinLogReader reader; int result; - pBasePath = g_fdfs_store_paths.paths[store_path_index]; - if ((result=recovery_reader_init(pBasePath, &reader)) != 0) + thread_data.base_path = g_fdfs_store_paths.paths[store_path_index].path; + thread_data.thread_index = 0; + + recovery_get_mark_filename(&thread_data, mark_filename); + if ((result=do_write_to_mark_file(mark_filename, 0)) != 0) + { + return result; + } + + if ((result=recovery_reader_init(&thread_data, &reader)) != 0) { storage_reader_destroy(&reader); return result; } result = storage_do_split_trunk_binlog(store_path_index, &reader); - storage_reader_destroy(&reader); return result; } -int storage_disk_recovery_start(const int store_path_index) +int storage_disk_recovery_prepare(const int store_path_index) { ConnectionInfo srcStorage; ConnectionInfo *pStorageConn; int result; char *pBasePath; - pBasePath = g_fdfs_store_paths.paths[store_path_index]; - if ((result=recovery_init_mark_file(pBasePath, false)) != 0) + pBasePath = g_fdfs_store_paths.paths[store_path_index].path; + if ((result=recovery_init_flag_file(pBasePath, false, -1)) != 0) { return result; } - if ((result=recovery_init_binlog_file(pBasePath)) != 0) + if ((result=recovery_init_global_binlog_file(pBasePath)) != 0) { return result; } @@ -1103,7 +1731,8 @@ int storage_disk_recovery_start(const int store_path_index) while (g_continue_flag) { if (storage_report_storage_status(g_my_server_id_str, \ - g_tracker_client_ip.ips[0], FDFS_STORAGE_STATUS_RECOVERY) == 0) + g_tracker_client_ip.ips[0].address, + FDFS_STORAGE_STATUS_RECOVERY) == 0) { break; } @@ -1119,6 +1748,10 @@ int storage_disk_recovery_start(const int store_path_index) return result; } + logInfo("file: "__FILE__", line: %d, " + "try to fetch binlog from %s:%d ...", __LINE__, + pStorageConn->ip_addr, pStorageConn->port); + result = storage_do_fetch_binlog(pStorageConn, store_path_index); tracker_close_connection_ex(pStorageConn, true); if (result != 0) @@ -1126,20 +1759,23 @@ int storage_disk_recovery_start(const int store_path_index) return result; } - //set fetch binlog done - if ((result=recovery_init_mark_file(pBasePath, true)) != 0) + logInfo("file: "__FILE__", line: %d, " + "fetch binlog from %s:%d successfully.", __LINE__, + pStorageConn->ip_addr, pStorageConn->port); + + if ((result=storage_disk_recovery_split_trunk_binlog( + store_path_index)) != 0) { + char flagFullFilename[MAX_PATH_SIZE]; + unlink(recovery_get_flag_filename(pBasePath, flagFullFilename)); return result; } - if ((result=storage_disk_recovery_split_trunk_binlog( \ - store_path_index)) != 0) + //set fetch binlog done + if ((result=recovery_init_flag_file(pBasePath, true, 1)) != 0) { - char markFullFilename[MAX_PATH_SIZE]; - unlink(recovery_get_mark_filename(pBasePath, markFullFilename)); return result; } return 0; } - diff --git a/storage/storage_disk_recovery.h b/storage/storage_disk_recovery.h index 053f1dd..b07ab63 100644 --- a/storage/storage_disk_recovery.h +++ b/storage/storage_disk_recovery.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //storage_disk_recovery.h @@ -18,8 +18,8 @@ extern "C" { #endif -int storage_disk_recovery_start(const int store_path_index); -int storage_disk_recovery_restore(const char *pBasePath); +int storage_disk_recovery_prepare(const int store_path_index); +int storage_disk_recovery_check_restore(const char *pBasePath); #ifdef __cplusplus } diff --git a/storage/storage_dump.c b/storage/storage_dump.c index c7707d7..e7c8dd6 100644 --- a/storage/storage_dump.c +++ b/storage/storage_dump.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include @@ -246,9 +246,9 @@ static int fdfs_dump_global_vars(char *buff, const int buffSize) total_len += snprintf(buff + total_len, buffSize - total_len, "\tg_fdfs_store_paths.paths[%d]=%s, " \ "total=%d MB, free=%d MB\n", i, \ - g_fdfs_store_paths.paths[i], \ - g_path_space_list[i].total_mb, \ - g_path_space_list[i].free_mb); + g_fdfs_store_paths.paths[i].path, \ + g_fdfs_store_paths.paths[i].total_mb, \ + g_fdfs_store_paths.paths[i].free_mb); } if (total_len < buffSize - 1) diff --git a/storage/storage_dump.h b/storage/storage_dump.h index 4da03a0..2fc090c 100644 --- a/storage/storage_dump.h +++ b/storage/storage_dump.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //storage_dump.h diff --git a/storage/storage_func.c b/storage/storage_func.c index e0eb796..2593cdc 100644 --- a/storage/storage_func.c +++ b/storage/storage_func.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //storage_func.c @@ -51,8 +51,18 @@ #include "fdfs_http_shared.h" #endif +typedef struct +{ + char ip_addr[IP_ADDRESS_SIZE]; + short port; + unsigned char store_path_index; + char padding; + int create_time; +} FDFSStorePathMarkInfo; + #define DATA_DIR_INITED_FILENAME ".data_init_flag" #define STORAGE_STAT_FILENAME "storage_stat.dat" +#define STORE_PATH_MARK_FILENAME ".fastdfs_vars" #define INIT_ITEM_STORAGE_JOIN_TIME "storage_join_time" #define INIT_ITEM_SYNC_OLD_DONE "sync_old_done" @@ -63,6 +73,9 @@ #define INIT_ITEM_LAST_HTTP_PORT "last_http_port" #define INIT_ITEM_CURRENT_TRUNK_FILE_ID "current_trunk_file_id" #define INIT_ITEM_TRUNK_LAST_COMPRESS_TIME "trunk_last_compress_time" +#define INIT_ITEM_TRUNK_BINLOG_COMPRESS_STAGE \ + "trunk_binlog_compress_stage" +#define INIT_ITEM_STORE_PATH_MARK_PREFIX "store_path_mark" #define STAT_ITEM_TOTAL_UPLOAD "total_upload_count" #define STAT_ITEM_SUCCESS_UPLOAD "success_upload_count" @@ -210,7 +223,7 @@ static int tracker_get_my_server_id() struct in_addr ip_addr; char ip_str[256]; - if (inet_pton(AF_INET, g_tracker_client_ip.ips[0], &ip_addr) == 1) + if (inet_pton(AF_INET, g_tracker_client_ip.ips[0].address, &ip_addr) == 1) { g_server_id_in_filename = ip_addr.s_addr; } @@ -218,7 +231,7 @@ static int tracker_get_my_server_id() { logError("file: "__FILE__", line: %d, " \ "call inet_pton for ip: %s fail", \ - __LINE__, g_tracker_client_ip.ips[0]); + __LINE__, g_tracker_client_ip.ips[0].address); g_server_id_in_filename = INADDR_NONE; } @@ -234,7 +247,7 @@ static int tracker_get_my_server_id() } result = tracker_get_storage_id(pTrackerServer, - g_group_name, g_tracker_client_ip.ips[0], + g_group_name, g_tracker_client_ip.ips[0].address, g_my_server_id_str); tracker_close_connection_ex(pTrackerServer, result != 0); if (result != 0) @@ -250,7 +263,7 @@ static int tracker_get_my_server_id() else { snprintf(g_my_server_id_str, sizeof(g_my_server_id_str), "%s", - g_tracker_client_ip.ips[0]); + g_tracker_client_ip.ips[0].address); } fdfs_multi_ips_to_string(&g_tracker_client_ip, @@ -628,62 +641,337 @@ int storage_write_to_stat_file() int storage_write_to_sync_ini_file() { char full_filename[MAX_PATH_SIZE]; - char buff[512]; + char buff[4 * 1024]; char ip_str[256]; - int fd; int len; + int result; + int i; - snprintf(full_filename, sizeof(full_filename), \ + snprintf(full_filename, sizeof(full_filename), "%s/data/%s", g_fdfs_base_path, DATA_DIR_INITED_FILENAME); - if ((fd=open(full_filename, O_WRONLY | O_CREAT | O_TRUNC, 0644)) < 0) - { - logError("file: "__FILE__", line: %d, " \ - "open file \"%s\" fail, " \ - "errno: %d, error info: %s", \ - __LINE__, full_filename, \ - errno, STRERROR(errno)); - return errno != 0 ? errno : ENOENT; - } fdfs_multi_ips_to_string(&g_tracker_client_ip, ip_str, sizeof(ip_str)); - len = sprintf(buff, "%s=%d\n" \ - "%s=%d\n" \ - "%s=%s\n" \ - "%s=%d\n" \ - "%s=%s\n" \ - "%s=%d\n" \ - "%s=%d\n" \ - "%s=%d\n" \ - "%s=%d\n", \ - INIT_ITEM_STORAGE_JOIN_TIME, g_storage_join_time, \ - INIT_ITEM_SYNC_OLD_DONE, g_sync_old_done, \ - INIT_ITEM_SYNC_SRC_SERVER, g_sync_src_id, \ - INIT_ITEM_SYNC_UNTIL_TIMESTAMP, g_sync_until_timestamp, \ - INIT_ITEM_LAST_IP_ADDRESS, ip_str, \ - INIT_ITEM_LAST_SERVER_PORT, g_last_server_port, \ - INIT_ITEM_LAST_HTTP_PORT, g_last_http_port, - INIT_ITEM_CURRENT_TRUNK_FILE_ID, g_current_trunk_file_id, \ - INIT_ITEM_TRUNK_LAST_COMPRESS_TIME, (int)g_trunk_last_compress_time - ); - if (fc_safe_write(fd, buff, len) != len) - { - logError("file: "__FILE__", line: %d, " \ - "write to file \"%s\" fail, " \ - "errno: %d, error info: %s", \ - __LINE__, full_filename, \ - errno, STRERROR(errno)); - close(fd); - return errno != 0 ? errno : EIO; - } + len = sprintf(buff, "%s=%d\n" + "%s=%d\n" + "%s=%s\n" + "%s=%d\n" + "%s=%s\n" + "%s=%d\n" + "%s=%d\n" + "%s=%u\n" + "%s=%d\n" + "%s=%d\n", + INIT_ITEM_STORAGE_JOIN_TIME, g_storage_join_time, + INIT_ITEM_SYNC_OLD_DONE, g_sync_old_done, + INIT_ITEM_SYNC_SRC_SERVER, g_sync_src_id, + INIT_ITEM_SYNC_UNTIL_TIMESTAMP, g_sync_until_timestamp, + INIT_ITEM_LAST_IP_ADDRESS, ip_str, + INIT_ITEM_LAST_SERVER_PORT, g_last_server_port, + INIT_ITEM_LAST_HTTP_PORT, g_last_http_port, + INIT_ITEM_CURRENT_TRUNK_FILE_ID, g_current_trunk_file_id, + INIT_ITEM_TRUNK_LAST_COMPRESS_TIME, + (int)g_trunk_last_compress_time, + INIT_ITEM_TRUNK_BINLOG_COMPRESS_STAGE, + g_trunk_binlog_compress_stage); - close(fd); + if (g_check_store_path_mark) + { + for (i=0; i 0) + { + char time_str[32]; + + mark_info.ip_addr[IP_ADDRESS_SIZE - 1] = '\0'; + formatDatetime(mark_info.create_time, + "%Y-%m-%d %H:%M:%S", + time_str, sizeof(time_str)); + + logCrit("file: "__FILE__", line: %d, " + "the store path #%d: %s maybe used by other " + "storage server. fields in the mark file: " + "{ ip_addr: %s, port: %d," + " store_path_index: %d," + " create_time: %s }, " + "if you confirm that it is NOT " + "used by other storage server, you can delete " + "the mark file %s then try again. if you DON'T " + "really need to check store path mark to prevent " + "confusion, you can set the parameter " + "check_store_path_mark to false in storage.conf", + __LINE__, store_path_index, g_fdfs_store_paths. + paths[store_path_index].path, + mark_info.ip_addr, mark_info.port, + mark_info.store_path_index, time_str, + full_filename); + } + else + { + logCrit("file: "__FILE__", line: %d, " + "the store path #%d: %s maybe used by other " + "storage server. if you confirm that it is NOT " + "used by other storage server, you can delete " + "the mark file %s then try again", __LINE__, + store_path_index, g_fdfs_store_paths. + paths[store_path_index].path, full_filename); + } + + free(mark); + return EINVAL; + } + } + else + { + if (!bPathCreated) + { + logWarning("file: "__FILE__", line: %d, " + "the mark file of store path #%d: %s is missed, " + "try to re-create the mark file: %s", __LINE__, + store_path_index, g_fdfs_store_paths. + paths[store_path_index].path, full_filename); + } + } + } + + if ((result=storage_generate_store_path_mark(store_path_index)) != 0) + { + return result; + } + + return storage_write_to_sync_ini_file(); +} + static int storage_check_and_make_data_dirs() { int result; @@ -693,9 +981,9 @@ static int storage_check_and_make_data_dirs() char error_info[256]; bool pathCreated; - snprintf(data_path, sizeof(data_path), "%s/data", \ + snprintf(data_path, sizeof(data_path), "%s/data", g_fdfs_base_path); - snprintf(full_filename, sizeof(full_filename), "%s/%s", \ + snprintf(full_filename, sizeof(full_filename), "%s/%s", data_path, DATA_DIR_INITED_FILENAME); if (fileExists(full_filename)) { @@ -778,10 +1066,19 @@ static int storage_check_and_make_data_dirs() g_last_http_port = atoi(pValue); } - g_current_trunk_file_id = iniGetIntValue(NULL, \ + g_current_trunk_file_id = iniGetIntValue(NULL, INIT_ITEM_CURRENT_TRUNK_FILE_ID, &iniContext, 0); - g_trunk_last_compress_time = iniGetIntValue(NULL, \ + g_trunk_last_compress_time = iniGetIntValue(NULL, INIT_ITEM_TRUNK_LAST_COMPRESS_TIME , &iniContext, 0); + g_trunk_binlog_compress_stage = iniGetIntValue(NULL, + INIT_ITEM_TRUNK_BINLOG_COMPRESS_STAGE, + &iniContext, STORAGE_TRUNK_COMPRESS_STAGE_NONE); + + if ((result=storage_load_store_path_marks(&iniContext)) != 0) + { + iniFreeContext(&iniContext); + return result; + } iniFreeContext(&iniContext); @@ -810,7 +1107,7 @@ static int storage_check_and_make_data_dirs() "g_last_storage_ip = %s, " "g_last_server_port = %d, " "g_last_http_port = %d, " - "g_current_trunk_file_id = %d, " + "g_current_trunk_file_id = %u, " "g_trunk_last_compress_time = %d", g_sync_old_done, g_sync_src_id, g_sync_until_timestamp, g_last_storage_ip, g_last_server_port, g_last_http_port, @@ -820,21 +1117,10 @@ static int storage_check_and_make_data_dirs() } else { - if (!fileExists(data_path)) - { - if (mkdir(data_path, 0755) != 0) - { - logError("file: "__FILE__", line: %d, " \ - "mkdir \"%s\" fail, " \ - "errno: %d, error info: %s", \ - __LINE__, data_path, \ - errno, STRERROR(errno)); - return errno != 0 ? errno : EPERM; - } - - STORAGE_CHOWN(data_path, geteuid(), getegid()) - } - + if ((result=storage_check_and_make_global_data_path()) != 0) + { + return result; + } g_last_server_port = g_server_port; g_last_http_port = g_http_port; g_storage_join_time = g_current_time; @@ -846,29 +1132,36 @@ static int storage_check_and_make_data_dirs() for (i=0; imy_status = -1; - pReportStatus->src_storage_status = -1; + pReportStatus->my_result = -1; + pReportStatus->src_storage_result = -1; pReportStatus++; } @@ -1138,13 +1422,6 @@ int storage_func_init(const char *filename, \ int64_t rotate_access_log_size; int64_t rotate_error_log_size; - /* - while (nThreadCount > 0) - { - sleep(1); - } - */ - if ((result=iniLoadFromFile(filename, &iniContext)) != 0) { logError("file: "__FILE__", line: %d, " \ @@ -1444,6 +1721,18 @@ int storage_func_init(const char *filename, \ break; } + g_disk_recovery_threads = iniGetIntValue(NULL, + "disk_recovery_threads", &iniContext, 1); + if (g_disk_recovery_threads <= 0) + { + logError("file: "__FILE__", line: %d, " + "item \"disk_recovery_threads\" is invalid, " + "value: %d <= 0!", __LINE__, + g_disk_recovery_threads); + result = EINVAL; + break; + } + /* g_disk_rw_direct = iniGetBoolValue(NULL, \ "disk_rw_direct", &iniContext, false); @@ -1726,6 +2015,30 @@ int storage_func_init(const char *filename, \ g_rotate_error_log = iniGetBoolValue(NULL, "rotate_error_log",\ &iniContext, false); + g_compress_old_access_log = iniGetBoolValue(NULL, "compress_old_access_log", + &iniContext, false); + g_compress_old_error_log = iniGetBoolValue(NULL, "compress_old_error_log", + &iniContext, false); + g_compress_error_log_days_before = iniGetIntValue(NULL, + "compress_error_log_days_before", &iniContext, 1); + g_compress_access_log_days_before = iniGetIntValue(NULL, + "compress_access_log_days_before", &iniContext, 1); + + if (g_compress_old_error_log) + { + log_set_compress_log_flags(LOG_COMPRESS_FLAGS_ENABLED | + LOG_COMPRESS_FLAGS_NEW_THREAD); + log_set_compress_log_days_before(g_compress_error_log_days_before); + } + if (g_use_access_log && g_compress_old_access_log) + { + log_set_compress_log_flags_ex(&g_access_log_context, + LOG_COMPRESS_FLAGS_ENABLED | + LOG_COMPRESS_FLAGS_NEW_THREAD); + log_set_compress_log_days_before_ex(&g_access_log_context, + g_compress_access_log_days_before); + } + if ((result=get_time_item_from_conf(&iniContext, \ "error_log_rotate_time", &g_error_log_rotate_time, \ 0, 0)) != 0) @@ -1785,6 +2098,16 @@ int storage_func_init(const char *filename, \ g_file_sync_skip_invalid_record = iniGetBoolValue(NULL, \ "file_sync_skip_invalid_record", &iniContext, false); + g_compress_binlog = iniGetBoolValue(NULL, + "compress_binlog", &iniContext, false); + if ((result=get_time_item_from_conf(&iniContext, + "compress_binlog_time", &g_compress_binlog_time, 1, 30)) != 0) + { + break; + } + + g_check_store_path_mark = iniGetBoolValue(NULL, + "check_store_path_mark", &iniContext, true); if ((result=fdfs_connection_pool_init(filename, &iniContext)) != 0) { break; @@ -1825,7 +2148,7 @@ int storage_func_init(const char *filename, \ "max_connections=%d, accept_threads=%d, " \ "work_threads=%d, " \ "disk_rw_separated=%d, disk_reader_threads=%d, " \ - "disk_writer_threads=%d, " \ + "disk_writer_threads=%d, disk_recovery_threads=%d, " \ "buff_size=%d KB, heart_beat_interval=%ds, " \ "stat_report_interval=%ds, tracker_server_count=%d, " \ "sync_wait_msec=%dms, sync_interval=%dms, " \ @@ -1846,14 +2169,21 @@ int storage_func_init(const char *filename, \ "HTTP server port=%d, domain name=%s, " \ "use_access_log=%d, rotate_access_log=%d, " \ "access_log_rotate_time=%02d:%02d, " \ + "compress_old_access_log=%d, " \ + "compress_access_log_days_before=%d, " \ "rotate_error_log=%d, " \ "error_log_rotate_time=%02d:%02d, " \ + "compress_old_error_log=%d, " \ + "compress_error_log_days_before=%d, " \ "rotate_access_log_size=%"PRId64", " \ "rotate_error_log_size=%"PRId64", " \ "log_file_keep_days=%d, " \ "file_sync_skip_invalid_record=%d, " \ "use_connection_pool=%d, " \ - "g_connection_pool_max_idle_time=%ds", \ + "g_connection_pool_max_idle_time=%ds, " \ + "compress_binlog=%d, " \ + "compress_binlog_time=%02d:%02d, " \ + "check_store_path_mark=%d", \ g_fdfs_version.major, g_fdfs_version.minor, \ g_fdfs_base_path, g_fdfs_store_paths.count, \ g_subdir_count_per_path, \ @@ -1863,7 +2193,7 @@ int storage_func_init(const char *filename, \ g_client_bind_addr, g_max_connections, \ g_accept_threads, g_work_threads, g_disk_rw_separated, \ g_disk_reader_threads, g_disk_writer_threads, \ - g_buff_size / 1024, \ + g_disk_recovery_threads, g_buff_size / 1024, \ g_heart_beat_interval, g_stat_report_interval, \ g_tracker_group.server_count, g_sync_wait_usec / 1000, \ g_sync_interval / 1000, \ @@ -1882,13 +2212,17 @@ int storage_func_init(const char *filename, \ g_key_namespace, g_keep_alive, \ g_http_port, g_http_domain, g_use_access_log, \ g_rotate_access_log, g_access_log_rotate_time.hour, \ - g_access_log_rotate_time.minute, \ + g_access_log_rotate_time.minute, g_compress_old_access_log, \ + g_compress_access_log_days_before, \ g_rotate_error_log, g_error_log_rotate_time.hour, \ - g_error_log_rotate_time.minute, \ + g_error_log_rotate_time.minute, g_compress_old_error_log, \ + g_compress_error_log_days_before, \ g_access_log_context.rotate_size, \ g_log_context.rotate_size, g_log_file_keep_days, \ g_file_sync_skip_invalid_record, \ - g_use_connection_pool, g_connection_pool_max_idle_time); + g_use_connection_pool, g_connection_pool_max_idle_time, \ + g_compress_binlog, g_compress_binlog_time.hour, \ + g_compress_binlog_time.minute, g_check_store_path_mark); #ifdef WITH_HTTPD if (!g_http_params.disabled) @@ -1922,7 +2256,7 @@ int storage_func_init(const char *filename, \ return result; } - if ((result=init_my_status_per_tracker()) != 0) + if ((result=init_my_result_per_tracker()) != 0) { return result; } @@ -1968,6 +2302,11 @@ int storage_func_init(const char *filename, \ return result; } + if ((result=storage_trunk_binlog_compress_check_recovery()) != 0) + { + return result; + } + if ((result=init_pthread_lock(&sync_stat_file_lock)) != 0) { return result; @@ -1986,10 +2325,10 @@ int storage_func_destroy() { for (i=0; iip_addr, conn->port, - multi_ip.ips[i], error_info); + multi_ip.ips[i].address, error_info); return result; } - insert_into_local_host_ip(multi_ip.ips[i]); + insert_into_local_host_ip(multi_ip.ips[i].address); } else if (result != EEXIST) { @@ -2145,7 +2484,7 @@ int storage_set_tracker_client_ips(ConnectionInfo *conn, "my ip: %s not consistent with client ips: %s " "of other tracker client. program exit!", __LINE__, conn->ip_addr, conn->port, - multi_ip.ips[i], ip_str); + multi_ip.ips[i].address, ip_str); return result; } @@ -2155,6 +2494,29 @@ int storage_set_tracker_client_ips(ConnectionInfo *conn, return 0; } +int storage_logic_to_local_full_filename(const char *logic_filename, + const int logic_filename_len, int *store_path_index, + char *full_filename, const int filename_size) +{ + int result; + int filename_len; + char true_filename[128]; + + filename_len = logic_filename_len; + if ((result=storage_split_filename_ex(logic_filename, + &filename_len, true_filename, store_path_index)) != 0) + { + return result; + } + if ((result=fdfs_check_data_filename(true_filename, filename_len)) != 0) + { + return result; + } + + snprintf(full_filename, filename_size, "%s/data/%s", + g_fdfs_store_paths.paths[*store_path_index].path, true_filename); + return 0; +} /* int write_serialized(int fd, const char *buff, size_t count, const bool bSync) diff --git a/storage/storage_func.h b/storage/storage_func.h index 1208498..8eb4c9e 100644 --- a/storage/storage_func.h +++ b/storage/storage_func.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //storage_func.h @@ -37,6 +37,12 @@ bool storage_id_is_myself(const char *storage_id); int storage_set_tracker_client_ips(ConnectionInfo *conn, const int tracker_index); +int storage_check_and_make_global_data_path(); + +int storage_logic_to_local_full_filename(const char *logic_filename, + const int logic_filename_len, int *store_path_index, + char *full_filename, const int filename_size); + #define STORAGE_CHOWN(path, current_uid, current_gid) \ if (!(g_run_by_gid == current_gid && g_run_by_uid == current_uid)) \ { \ diff --git a/storage/storage_global.c b/storage/storage_global.c index 9be4a42..74e2232 100644 --- a/storage/storage_global.c +++ b/storage/storage_global.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include @@ -15,7 +15,6 @@ #include "storage_global.h" volatile bool g_continue_flag = true; -FDFSStorePathInfo *g_path_space_list = NULL; int g_subdir_count_per_path = DEFAULT_DATA_DIR_COUNT_PER_PATH; int g_server_port = FDFS_STORAGE_SERVER_DEF_PORT; @@ -32,6 +31,7 @@ bool g_disk_rw_direct = false; bool g_disk_rw_separated = true; int g_disk_reader_threads = DEFAULT_DISK_READER_THREADS; int g_disk_writer_threads = DEFAULT_DISK_WRITER_THREADS; +int g_disk_recovery_threads = 1; int g_extra_open_file_flags = 0; int g_file_distribute_path_mode = FDFS_FILE_DIST_PATH_ROUND_ROBIN; @@ -80,6 +80,8 @@ in_addr_t g_server_id_in_filename = 0; bool g_use_access_log = false; //if log to access log bool g_rotate_access_log = false; //if rotate the access log every day bool g_rotate_error_log = false; //if rotate the error log every day +bool g_compress_old_access_log = false; //if compress the old access log +bool g_compress_old_error_log = false; //if compress the old error log bool g_use_storage_id = false; //identify storage by ID instead of IP address byte g_id_type_in_filename = FDFS_ID_TYPE_IP_ADDRESS; //id type of the storage server in the filename bool g_store_slave_file_use_link = false; //if store slave file use symbol link @@ -107,6 +109,10 @@ bool g_storage_ip_changed_auto_adjust = false; bool g_thread_kill_done = false; bool g_file_sync_skip_invalid_record = false; +bool g_check_store_path_mark = true; +bool g_compress_binlog = false; +TimeInfo g_compress_binlog_time = {0, 0}; + int g_thread_stack_size = 512 * 1024; int g_upload_priority = DEFAULT_UPLOAD_PRIORITY; time_t g_up_time = 0; @@ -121,6 +127,8 @@ char g_exe_name[256] = {0}; #endif int g_log_file_keep_days = 0; +int g_compress_access_log_days_before = 0; +int g_compress_error_log_days_before = 0; struct storage_nio_thread_data *g_nio_thread_data = NULL; struct storage_dio_thread_data *g_dio_thread_data = NULL; @@ -138,13 +146,14 @@ int storage_insert_ip_addr_to_multi_ips(FDFSMultiIP *multi_ip, if (multi_ip->count == 0) { multi_ip->count = 1; - strcpy(multi_ip->ips[0], ip_addr); + multi_ip->ips[0].type = fdfs_get_ip_type(ip_addr); + strcpy(multi_ip->ips[0].address, ip_addr); return 0; } for (i = 0; i < multi_ip->count; i++) { - if (strcmp(multi_ip->ips[i], ip_addr) == 0) + if (strcmp(multi_ip->ips[i].address, ip_addr) == 0) { return EEXIST; } @@ -155,7 +164,8 @@ int storage_insert_ip_addr_to_multi_ips(FDFSMultiIP *multi_ip, return ENOSPC; } - strcpy(multi_ip->ips[i], ip_addr); + multi_ip->ips[i].type = fdfs_get_ip_type(ip_addr); + strcpy(multi_ip->ips[i].address, ip_addr); multi_ip->count++; return 0; } diff --git a/storage/storage_global.h b/storage/storage_global.h index 0fc19ce..a79c649 100644 --- a/storage/storage_global.h +++ b/storage/storage_global.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //storage_global.h @@ -21,7 +21,6 @@ #include "client_global.h" #include "fdht_types.h" #include "fastcommon/local_ip_func.h" -#include "trunk_shared.h" #ifdef WITH_HTTPD #include "fdfs_http_shared.h" @@ -53,21 +52,15 @@ typedef struct typedef struct { - int total_mb; //total spaces - int free_mb; //free spaces -} FDFSStorePathInfo; - -typedef struct -{ - signed char my_status; - signed char src_storage_status; + signed char my_status; //my status from tracker server + signed char my_result; //my report result + signed char src_storage_result; //src storage report result bool get_my_ip_done; + bool report_my_status; } StorageStatusPerTracker; extern volatile bool g_continue_flag; -extern FDFSStorePathInfo *g_path_space_list; - /* subdirs under store path, g_subdir_count * g_subdir_count 2 level subdirs */ extern int g_subdir_count_per_path; @@ -85,6 +78,7 @@ extern bool g_disk_rw_direct; //if file read / write directly extern bool g_disk_rw_separated; //if disk read / write separated extern int g_disk_reader_threads; //disk reader thread count per store base path extern int g_disk_writer_threads; //disk writer thread count per store base path +extern int g_disk_recovery_threads; //disk recovery thread count extern int g_extra_open_file_flags; //extra open file flags extern int g_file_distribute_path_mode; @@ -135,6 +129,8 @@ extern byte g_id_type_in_filename; //id type of the storage server in the filena extern bool g_use_access_log; //if log to access log extern bool g_rotate_access_log; //if rotate the access log every day extern bool g_rotate_error_log; //if rotate the error log every day +extern bool g_compress_old_access_log; //if compress the old access log +extern bool g_compress_old_error_log; //if compress the old error log extern TimeInfo g_access_log_rotate_time; //rotate access log time base extern TimeInfo g_error_log_rotate_time; //rotate error log time base @@ -162,6 +158,10 @@ extern bool g_thread_kill_done; extern bool g_file_sync_skip_invalid_record; +extern bool g_check_store_path_mark; +extern bool g_compress_binlog; +extern TimeInfo g_compress_binlog_time; //compress binlog time base + extern int g_thread_stack_size; extern int g_upload_priority; extern time_t g_up_time; @@ -176,6 +176,8 @@ extern char g_exe_name[256]; #endif extern int g_log_file_keep_days; +extern int g_compress_access_log_days_before; +extern int g_compress_error_log_days_before; extern struct storage_nio_thread_data *g_nio_thread_data; //network io thread data extern struct storage_dio_thread_data *g_dio_thread_data; //disk io thread data diff --git a/storage/storage_ip_changed_dealer.c b/storage/storage_ip_changed_dealer.c index 12c1d99..e550314 100644 --- a/storage/storage_ip_changed_dealer.c +++ b/storage/storage_ip_changed_dealer.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ @@ -76,9 +76,9 @@ static int storage_report_ip_changed(ConnectionInfo *pTrackerServer) pHeader->cmd = TRACKER_PROTO_CMD_STORAGE_REPORT_IP_CHANGED; strcpy(out_buff + sizeof(TrackerHeader), g_group_name); strcpy(out_buff + sizeof(TrackerHeader) + FDFS_GROUP_NAME_MAX_LEN, \ - g_last_storage_ip.ips[0]); + g_last_storage_ip.ips[0].address); strcpy(out_buff + sizeof(TrackerHeader) + FDFS_GROUP_NAME_MAX_LEN + \ - IP_ADDRESS_SIZE, g_tracker_client_ip.ips[0]); + IP_ADDRESS_SIZE, g_tracker_client_ip.ips[0].address); if((result=tcpsenddata_nb(pTrackerServer->sock, out_buff, \ sizeof(out_buff), g_fdfs_network_timeout)) != 0) @@ -92,10 +92,11 @@ static int storage_report_ip_changed(ConnectionInfo *pTrackerServer) } pInBuff = in_buff; - result = fdfs_recv_response(pTrackerServer, \ + result = fdfs_recv_response(pTrackerServer, &pInBuff, 0, &in_bytes); - if (result == 0 || result == EALREADY || result == ENOENT) + if (result == 0 || result == EALREADY || result == ENOENT + || result == EEXIST) { if (result != 0) { @@ -107,11 +108,11 @@ static int storage_report_ip_changed(ConnectionInfo *pTrackerServer) } else { - logError("file: "__FILE__", line: %d, " \ - "tracker server %s:%d, recv data fail or " \ - "response status != 0, " \ - "errno: %d, error info: %s", \ - __LINE__, pTrackerServer->ip_addr, \ + logError("file: "__FILE__", line: %d, " + "tracker server %s:%d, recv data fail or " + "response status != 0, " + "errno: %d, error info: %s", + __LINE__, pTrackerServer->ip_addr, pTrackerServer->port, result, STRERROR(result)); return result == EBUSY ? 0 : result; } @@ -208,15 +209,15 @@ static int storage_report_storage_ip_addr() logDebug("file: "__FILE__", line: %d, " "last my ip is %s, current my ip is %s", - __LINE__, g_last_storage_ip.ips[0], - g_tracker_client_ip.ips[0]); + __LINE__, g_last_storage_ip.ips[0].address, + g_tracker_client_ip.ips[0].address); if (g_last_storage_ip.count == 0) { return storage_write_to_sync_ini_file(); } - else if (strcmp(g_tracker_client_ip.ips[0], - g_last_storage_ip.ips[0]) == 0) + else if (strcmp(g_tracker_client_ip.ips[0].address, + g_last_storage_ip.ips[0].address) == 0) { return 0; } diff --git a/storage/storage_ip_changed_dealer.h b/storage/storage_ip_changed_dealer.h index f5639ec..0947711 100644 --- a/storage/storage_ip_changed_dealer.h +++ b/storage/storage_ip_changed_dealer.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //storage_ip_changed_dealer.h diff --git a/storage/storage_nio.c b/storage/storage_nio.c index 466b4ad..df199cc 100644 --- a/storage/storage_nio.c +++ b/storage/storage_nio.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include @@ -38,13 +38,6 @@ static void client_sock_read(int sock, short event, void *arg); static void client_sock_write(int sock, short event, void *arg); static int storage_nio_init(struct fast_task_info *pTask); -void add_to_deleted_list(struct fast_task_info *pTask) -{ - ((StorageClientInfo *)pTask->arg)->canceled = true; - pTask->next = pTask->thread_data->deleted_list; - pTask->thread_data->deleted_list = pTask; -} - void task_finish_clean_up(struct fast_task_info *pTask) { StorageClientInfo *pClientInfo; @@ -66,6 +59,7 @@ void task_finish_clean_up(struct fast_task_info *pTask) pTask->event.timer.expires = 0; } + pTask->canceled = false; memset(pTask->arg, 0, sizeof(StorageClientInfo)); free_queue_push(pTask); @@ -87,7 +81,7 @@ static int set_recv_event(struct fast_task_info *pTask) pTask->event.fd, IOEVENT_READ, pTask) != 0) { result = errno != 0 ? errno : ENOENT; - add_to_deleted_list(pTask); + ioevent_add_to_deleted_list(pTask); logError("file: "__FILE__", line: %d, "\ "ioevent_modify fail, " \ @@ -112,7 +106,7 @@ static int set_send_event(struct fast_task_info *pTask) pTask->event.fd, IOEVENT_WRITE, pTask) != 0) { result = errno != 0 ? errno : ENOENT; - add_to_deleted_list(pTask); + ioevent_add_to_deleted_list(pTask); logError("file: "__FILE__", line: %d, "\ "ioevent_modify fail, " \ @@ -210,7 +204,7 @@ void storage_recv_notify_read(int sock, short event, void *arg) if (result != 0) { - add_to_deleted_list(pTask); + ioevent_add_to_deleted_list(pTask); } } } @@ -248,7 +242,7 @@ static void client_sock_read(int sock, short event, void *arg) pTask = (struct fast_task_info *)arg; pClientInfo = (StorageClientInfo *)pTask->arg; - if (pClientInfo->canceled) + if (pTask->canceled) { return; } @@ -267,23 +261,35 @@ static void client_sock_read(int sock, short event, void *arg) if (event & IOEVENT_TIMEOUT) { - if (pClientInfo->total_offset == 0 && pTask->req_count > 0) + if (pClientInfo->total_offset == 0) { - pTask->event.timer.expires = g_current_time + - g_fdfs_network_timeout; - fast_timer_add(&pTask->thread_data->timer, - &pTask->event.timer); + if (pTask->req_count > 0) + { + pTask->event.timer.expires = g_current_time + + g_fdfs_network_timeout; + fast_timer_add(&pTask->thread_data->timer, + &pTask->event.timer); + } + else + { + logWarning("file: "__FILE__", line: %d, " + "client ip: %s, recv timeout. " + "after the connection is established, " + "you must send a request before %ds timeout, " + "maybe connections leak in you application.", + __LINE__, pTask->client_ip, g_fdfs_network_timeout); + task_finish_clean_up(pTask); + } } else - { - logError("file: "__FILE__", line: %d, " \ - "client ip: %s, recv timeout, " \ - "recv offset: %d, expect length: %d", \ - __LINE__, pTask->client_ip, \ - pTask->offset, pTask->length); - - task_finish_clean_up(pTask); - } + { + logError("file: "__FILE__", line: %d, " + "client ip: %s, recv timeout, " + "recv offset: %d, expect length: %d, " + "req_count: %"PRId64, __LINE__, pTask->client_ip, + pTask->offset, pTask->length, pTask->req_count); + task_finish_clean_up(pTask); + } return; } @@ -425,15 +431,17 @@ static void client_sock_write(int sock, short event, void *arg) pTask = (struct fast_task_info *)arg; pClientInfo = (StorageClientInfo *)pTask->arg; - if (pClientInfo->canceled) + if (pTask->canceled) { return; } if (event & IOEVENT_TIMEOUT) { - logError("file: "__FILE__", line: %d, " \ - "send timeout", __LINE__); + logError("file: "__FILE__", line: %d, " + "client ip: %s, send timeout, offset: %d, " + "remain bytes: %d", __LINE__, pTask->client_ip, + pTask->offset, pTask->length - pTask->offset); task_finish_clean_up(pTask); return; @@ -441,7 +449,7 @@ static void client_sock_write(int sock, short event, void *arg) if (event & IOEVENT_ERROR) { - logDebug("file: "__FILE__", line: %d, " \ + logDebug("file: "__FILE__", line: %d, " "client ip: %s, recv error event: %d, " "close connection", __LINE__, pTask->client_ip, event); diff --git a/storage/storage_nio.h b/storage/storage_nio.h index 79094a5..3ace156 100644 --- a/storage/storage_nio.h +++ b/storage/storage_nio.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //tracker_nio.h @@ -46,6 +46,8 @@ typedef void (*DeleteFileLogCallback)(struct fast_task_info *pTask, \ typedef void (*FileDealDoneCallback)(struct fast_task_info *pTask, \ const int err_no); +typedef int (*FileDealContinueCallback)(struct fast_task_info *pTask); + typedef int (*FileBeforeOpenCallback)(struct fast_task_info *pTask); typedef int (*FileBeforeCloseCallback)(struct fast_task_info *pTask); @@ -109,6 +111,7 @@ typedef struct int64_t start; //the start offset of file int64_t end; //the end offset of file int64_t offset; //the current offset of file + FileDealContinueCallback continue_callback; FileDealDoneCallback done_callback; DeleteFileLogCallback log_callback; @@ -118,7 +121,6 @@ typedef struct typedef struct { int nio_thread_index; //nio thread index - bool canceled; char stage; //nio stage, send or recv char storage_server_id[FDFS_STORAGE_ID_MAX_SIZE]; @@ -149,7 +151,6 @@ void storage_recv_notify_read(int sock, short event, void *arg); int storage_send_add_event(struct fast_task_info *pTask); void task_finish_clean_up(struct fast_task_info *pTask); -void add_to_deleted_list(struct fast_task_info *pTask); #ifdef __cplusplus } diff --git a/storage/storage_param_getter.c b/storage/storage_param_getter.c index d4ffd17..ed05270 100644 --- a/storage/storage_param_getter.c +++ b/storage/storage_param_getter.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ @@ -74,30 +74,30 @@ int storage_get_params_from_tracker() char reserved_space_str[32]; char *pIdType; - if ((result=fdfs_get_ini_context_from_tracker(&g_tracker_group, \ - &iniContext, (bool * volatile)&g_continue_flag, \ + if ((result=fdfs_get_ini_context_from_tracker(&g_tracker_group, + &iniContext, (bool * volatile)&g_continue_flag, g_client_bind_addr, g_bind_addr)) != 0) { return result; } - g_storage_ip_changed_auto_adjust = iniGetBoolValue(NULL, \ - "storage_ip_changed_auto_adjust", \ + g_storage_ip_changed_auto_adjust = iniGetBoolValue(NULL, + "storage_ip_changed_auto_adjust", &iniContext, false); - g_store_path_mode = iniGetIntValue(NULL, "store_path", &iniContext, \ + g_store_path_mode = iniGetIntValue(NULL, "store_path", &iniContext, FDFS_STORE_PATH_ROUND_ROBIN); - if ((result=fdfs_parse_storage_reserved_space(&iniContext, \ + if ((result=fdfs_parse_storage_reserved_space(&iniContext, &g_storage_reserved_space)) != 0) { iniFreeContext(&iniContext); return result; } - if (g_storage_reserved_space.flag == \ + if (g_storage_reserved_space.flag == TRACKER_STORAGE_RESERVED_SPACE_FLAG_MB) { - g_avg_storage_reserved_mb = g_storage_reserved_space.rs.mb \ + g_avg_storage_reserved_mb = g_storage_reserved_space.rs.mb / g_fdfs_store_paths.count; } else @@ -105,41 +105,61 @@ int storage_get_params_from_tracker() g_avg_storage_reserved_mb = 0; } - g_use_storage_id = iniGetBoolValue(NULL, "use_storage_id", \ + g_use_storage_id = iniGetBoolValue(NULL, "use_storage_id", &iniContext, false); - use_trunk_file = iniGetBoolValue(NULL, "use_trunk_file", \ + use_trunk_file = iniGetBoolValue(NULL, "use_trunk_file", &iniContext, false); - g_slot_min_size = iniGetIntValue(NULL, "slot_min_size", \ + g_slot_min_size = iniGetIntValue(NULL, "slot_min_size", &iniContext, 256); - g_trunk_file_size = iniGetIntValue(NULL, "trunk_file_size", \ + g_trunk_file_size = iniGetIntValue(NULL, "trunk_file_size", &iniContext, 64 * 1024 * 1024); - g_slot_max_size = iniGetIntValue(NULL, "slot_max_size", \ - &iniContext, g_trunk_file_size / 2); + g_slot_max_size = iniGetIntValue(NULL, "slot_max_size", + &iniContext, g_trunk_file_size / 4); + g_trunk_alloc_alignment_size = iniGetIntValue(NULL, + "trunk_alloc_alignment_size", &iniContext, 0); + if (g_slot_min_size < g_trunk_alloc_alignment_size) + { + g_slot_min_size = g_trunk_alloc_alignment_size; + } - g_trunk_create_file_advance = iniGetBoolValue(NULL, \ + g_trunk_create_file_advance = iniGetBoolValue(NULL, "trunk_create_file_advance", &iniContext, false); - if ((result=get_time_item_from_conf(&iniContext, \ - "trunk_create_file_time_base", \ + if ((result=get_time_item_from_conf(&iniContext, + "trunk_create_file_time_base", &g_trunk_create_file_time_base, 2, 0)) != 0) { iniFreeContext(&iniContext); return result; } - g_trunk_create_file_interval = iniGetIntValue(NULL, \ - "trunk_create_file_interval", &iniContext, \ + g_trunk_create_file_interval = iniGetIntValue(NULL, + "trunk_create_file_interval", &iniContext, 86400); - g_trunk_create_file_space_threshold = iniGetInt64Value(NULL, \ - "trunk_create_file_space_threshold", \ + g_trunk_create_file_space_threshold = iniGetInt64Value(NULL, + "trunk_create_file_space_threshold", &iniContext, 0); - g_trunk_init_check_occupying = iniGetBoolValue(NULL, \ + g_trunk_init_check_occupying = iniGetBoolValue(NULL, "trunk_init_check_occupying", &iniContext, false); - g_trunk_init_reload_from_binlog = iniGetBoolValue(NULL, \ + g_trunk_init_reload_from_binlog = iniGetBoolValue(NULL, "trunk_init_reload_from_binlog", &iniContext, false); - g_trunk_compress_binlog_min_interval = iniGetIntValue(NULL, \ + g_trunk_free_space_merge = iniGetBoolValue(NULL, + "trunk_free_space_merge", &iniContext, false); + g_delete_unused_trunk_files = iniGetBoolValue(NULL, + "delete_unused_trunk_files", &iniContext, false); + g_trunk_compress_binlog_min_interval = iniGetIntValue(NULL, "trunk_compress_binlog_min_interval", &iniContext, 0); + g_trunk_compress_binlog_interval = iniGetIntValue(NULL, + "trunk_compress_binlog_interval", &iniContext, 0); + if ((result=get_time_item_from_conf(&iniContext, + "trunk_compress_binlog_time_base", + &g_trunk_compress_binlog_time_base, 3, 0)) != 0) + { + return result; + } - g_store_slave_file_use_link = iniGetBoolValue(NULL, \ + g_trunk_binlog_max_backups = iniGetIntValue(NULL, + "trunk_binlog_max_backups", &iniContext, 0); + g_store_slave_file_use_link = iniGetBoolValue(NULL, "store_slave_file_use_link", &iniContext, false); pIdType = iniGetStrValue(NULL, "id_type_in_filename", &iniContext); @@ -170,43 +190,56 @@ int storage_get_params_from_tracker() } g_if_use_trunk_file = use_trunk_file; - logInfo("file: "__FILE__", line: %d, " \ - "use_storage_id=%d, " \ - "id_type_in_filename=%s, " \ - "storage_ip_changed_auto_adjust=%d, " \ - "store_path=%d, " \ - "reserved_storage_space=%s, " \ - "use_trunk_file=%d, " \ - "slot_min_size=%d, " \ - "slot_max_size=%d MB, " \ - "trunk_file_size=%d MB, " \ - "trunk_create_file_advance=%d, " \ - "trunk_create_file_time_base=%02d:%02d, " \ - "trunk_create_file_interval=%d, " \ - "trunk_create_file_space_threshold=%d GB, " \ - "trunk_init_check_occupying=%d, " \ - "trunk_init_reload_from_binlog=%d, " \ - "trunk_compress_binlog_min_interval=%d, " \ - "store_slave_file_use_link=%d", \ - __LINE__, g_use_storage_id, \ - g_id_type_in_filename == FDFS_ID_TYPE_SERVER_ID ? "id" : "ip", \ - g_storage_ip_changed_auto_adjust, \ - g_store_path_mode, fdfs_storage_reserved_space_to_string( \ - &g_storage_reserved_space, reserved_space_str), \ - g_if_use_trunk_file, g_slot_min_size, \ - g_slot_max_size / FDFS_ONE_MB, \ - g_trunk_file_size / FDFS_ONE_MB, \ - g_trunk_create_file_advance, \ - g_trunk_create_file_time_base.hour, \ - g_trunk_create_file_time_base.minute, \ - g_trunk_create_file_interval, \ - (int)(g_trunk_create_file_space_threshold / \ - (FDFS_ONE_MB * 1024)), g_trunk_init_check_occupying, \ - g_trunk_init_reload_from_binlog, \ - g_trunk_compress_binlog_min_interval, \ + logInfo("file: "__FILE__", line: %d, " + "use_storage_id=%d, " + "id_type_in_filename=%s, " + "storage_ip_changed_auto_adjust=%d, " + "store_path=%d, " + "reserved_storage_space=%s, " + "use_trunk_file=%d, " + "slot_min_size=%d, " + "slot_max_size=%d KB, " + "trunk_alloc_alignment_size=%d, " + "trunk_file_size=%d MB, " + "trunk_create_file_advance=%d, " + "trunk_create_file_time_base=%02d:%02d, " + "trunk_create_file_interval=%d, " + "trunk_create_file_space_threshold=%d GB, " + "trunk_init_check_occupying=%d, " + "trunk_init_reload_from_binlog=%d, " + "trunk_free_space_merge=%d, " + "delete_unused_trunk_files=%d, " + "trunk_compress_binlog_min_interval=%d, " + "trunk_compress_binlog_interval=%d, " + "trunk_compress_binlog_time_base=%02d:%02d, " + "trunk_binlog_max_backups=%d, " + "store_slave_file_use_link=%d", + __LINE__, g_use_storage_id, + g_id_type_in_filename == FDFS_ID_TYPE_SERVER_ID ? "id" : "ip", + g_storage_ip_changed_auto_adjust, + g_store_path_mode, fdfs_storage_reserved_space_to_string( + &g_storage_reserved_space, reserved_space_str), + g_if_use_trunk_file, g_slot_min_size, + g_slot_max_size / 1024, + g_trunk_alloc_alignment_size, + g_trunk_file_size / FDFS_ONE_MB, + g_trunk_create_file_advance, + g_trunk_create_file_time_base.hour, + g_trunk_create_file_time_base.minute, + g_trunk_create_file_interval, + (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_delete_unused_trunk_files, + g_trunk_compress_binlog_min_interval, + g_trunk_compress_binlog_interval, + g_trunk_compress_binlog_time_base.hour, + g_trunk_compress_binlog_time_base.minute, + g_trunk_binlog_max_backups, g_store_slave_file_use_link); - if (g_use_storage_id && *g_sync_src_id != '\0' && \ + if (g_use_storage_id && *g_sync_src_id != '\0' && !fdfs_is_server_id_valid(g_sync_src_id)) { if ((result=storage_convert_src_server_id()) == 0) diff --git a/storage/storage_param_getter.h b/storage/storage_param_getter.h index 7d6e020..16dd480 100644 --- a/storage/storage_param_getter.h +++ b/storage/storage_param_getter.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //storage_param_getter.h diff --git a/storage/storage_service.c b/storage/storage_service.c index c6e7f47..50e50f3 100644 --- a/storage/storage_service.c +++ b/storage/storage_service.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //storage_service.c @@ -28,6 +28,7 @@ #include "fastcommon/shared_func.h" #include "fastcommon/pthread_func.h" #include "fastcommon/sched_thread.h" +#include "fastcommon/fast_mblock.h" #include "tracker_types.h" #include "tracker_proto.h" #include "storage_service.h" @@ -58,7 +59,14 @@ #define ACCESS_LOG_ACTION_APPEND_FILE "append" #define ACCESS_LOG_ACTION_TRUNCATE_FILE "truncate" #define ACCESS_LOG_ACTION_QUERY_FILE "status" +#define ACCESS_LOG_ACTION_RENAME_FILE "rename" +typedef struct +{ + int storage_id; + time_t mtime; + int64_t fsize; +} StorageFileInfoForCRC32; pthread_mutex_t g_storage_thread_lock; int g_storage_thread_count = 0; @@ -69,6 +77,8 @@ static int64_t temp_file_sequence = 0; static pthread_mutex_t path_index_thread_lock; static pthread_mutex_t stat_count_thread_lock; +static struct fast_mblock_man finfo_for_crc32_allocator; + static void *work_thread_entrance(void* arg); extern int storage_client_create_link(ConnectionInfo *pTrackerServer, \ @@ -479,32 +489,30 @@ static void storage_sync_truncate_file_done_callback( \ storage_nio_notify(pTask); } -static int storage_sync_copy_file_rename_filename( \ +static int storage_sync_copy_file_rename_filename( StorageFileContext *pFileContext) { char full_filename[MAX_PATH_SIZE + 256]; - char true_filename[128]; int filename_len; int result; int store_path_index; filename_len = strlen(pFileContext->fname2log); - if ((result=storage_split_filename_ex(pFileContext->fname2log, \ - &filename_len, true_filename, &store_path_index)) != 0) + if ((result=storage_logic_to_local_full_filename( + pFileContext->fname2log, filename_len, + &store_path_index, full_filename, + sizeof(full_filename))) != 0) { return result; } - snprintf(full_filename, sizeof(full_filename), \ - "%s/data/%s", g_fdfs_store_paths.paths[store_path_index], \ - true_filename); if (rename(pFileContext->filename, full_filename) != 0) { result = errno != 0 ? errno : EPERM; - logWarning("file: "__FILE__", line: %d, " \ - "rename %s to %s fail, " \ - "errno: %d, error info: %s", __LINE__, \ - pFileContext->filename, full_filename, \ + logWarning("file: "__FILE__", line: %d, " + "rename %s to %s fail, " + "errno: %d, error info: %s", __LINE__, + pFileContext->filename, full_filename, result, STRERROR(result)); return result; } @@ -781,7 +789,7 @@ static int storage_do_delete_meta_file(struct fast_task_info *pTask) } sprintf(meta_filename, "%s/data/%s"FDFS_STORAGE_META_FILE_EXT, \ - g_fdfs_store_paths.paths[store_path_index], true_filename); + g_fdfs_store_paths.paths[store_path_index].path, true_filename); } else { @@ -1014,7 +1022,7 @@ static int storage_do_delete_meta_file(struct fast_task_info *pTask) else { sprintf(pFileContext->filename, "%s/data/%s", \ - g_fdfs_store_paths.paths[store_path_index], \ + g_fdfs_store_paths.paths[store_path_index].path, \ true_filename); } @@ -1708,6 +1716,9 @@ int storage_service_init() return result; } + result = fast_mblock_init(&finfo_for_crc32_allocator, + sizeof(StorageFileInfoForCRC32), 1024); + return result; } @@ -1823,9 +1834,11 @@ static void *accept_thread_entrance(void* arg) pTask = free_queue_pop(); if (pTask == NULL) { - logError("file: "__FILE__", line: %d, " \ - "malloc task buff failed", \ - __LINE__); + logError("file: "__FILE__", line: %d, " + "malloc task buff fail, you should " + "increase the parameter \"max_connections\" " + "in storage.conf, or check your applications " + "for connection leaks", __LINE__); close(incomesock); continue; } @@ -1901,7 +1914,7 @@ void storage_accept_loop(int server_sock) accept_thread_entrance((void *)(long)server_sock); } -void storage_nio_notify(struct fast_task_info *pTask) +int storage_nio_notify(struct fast_task_info *pTask) { StorageClientInfo *pClientInfo; struct storage_nio_thread_data *pThreadData; @@ -1922,6 +1935,8 @@ void storage_nio_notify(struct fast_task_info *pTask) __LINE__, result, STRERROR(result)); abort(); } + + return 0; } static void *work_thread_entrance(void* arg) @@ -1999,15 +2014,15 @@ int storage_get_storage_path_index(int *store_path_index) *store_path_index = 0; } - if (!storage_check_reserved_space_path(g_path_space_list \ - [*store_path_index].total_mb, g_path_space_list \ + if (!storage_check_reserved_space_path(g_fdfs_store_paths.paths \ + [*store_path_index].total_mb, g_fdfs_store_paths.paths \ [*store_path_index].free_mb, g_avg_storage_reserved_mb)) { for (i=0; ipath.sub_path_high = sub_path_high; pTrunkInfo->path.sub_path_low = sub_path_low; - pClientInfo->file_context.extra_info.upload. \ + pClientInfo->file_context.extra_info.upload. if_sub_path_alloced = true; } - len = sprintf(filename, FDFS_STORAGE_DATA_DIR_FORMAT"/" \ - FDFS_STORAGE_DATA_DIR_FORMAT"/", \ + len = sprintf(filename, FDFS_STORAGE_DATA_DIR_FORMAT"/" + FDFS_STORAGE_DATA_DIR_FORMAT"/", pTrunkInfo->path.sub_path_high, pTrunkInfo->path.sub_path_low); memcpy(filename+len, encoded, *filename_len); @@ -2173,7 +2188,7 @@ static int storage_sort_metadata_buff(char *meta_buff, const int meta_size) return 0; } -static void storage_format_ext_name(const char *file_ext_name, \ +static void storage_format_ext_name(const char *file_ext_name, char *szFormattedExt) { int i; @@ -2206,9 +2221,9 @@ static void storage_format_ext_name(const char *file_ext_name, \ *p = '\0'; } -static int storage_get_filename(StorageClientInfo *pClientInfo, \ - const int start_time, const int64_t file_size, const int crc32, \ - const char *szFormattedExt, char *filename, \ +static int storage_get_filename(StorageClientInfo *pClientInfo, + const int start_time, const int64_t file_size, const int crc32, + const char *szFormattedExt, char *filename, int *filename_len, char *full_filename) { int i; @@ -2219,15 +2234,15 @@ static int storage_get_filename(StorageClientInfo *pClientInfo, \ trunk_info.path.store_path_index; for (i=0; i<10; i++) { - if ((result=storage_gen_filename(pClientInfo, file_size, \ - crc32, szFormattedExt, FDFS_FILE_EXT_NAME_MAX_LEN+1, \ + if ((result=storage_gen_filename(pClientInfo, file_size, + crc32, szFormattedExt, FDFS_FILE_EXT_NAME_MAX_LEN + 1, start_time, filename, filename_len)) != 0) { return result; } - sprintf(full_filename, "%s/data/%s", \ - g_fdfs_store_paths.paths[store_path_index], filename); + sprintf(full_filename, "%s/data/%s", + g_fdfs_store_paths.paths[store_path_index].path, filename); if (!fileExists(full_filename)) { break; @@ -2238,7 +2253,7 @@ static int storage_get_filename(StorageClientInfo *pClientInfo, \ if (*full_filename == '\0') { - logError("file: "__FILE__", line: %d, " \ + logError("file: "__FILE__", line: %d, " "Can't generate uniq filename", __LINE__); *filename = '\0'; *filename_len = 0; @@ -2486,7 +2501,7 @@ static int storage_service_upload_file_done(struct fast_task_info *pTask) } snprintf(pFileContext->filename, sizeof(pFileContext->filename), \ - "%s/data/%s", g_fdfs_store_paths.paths[master_store_path_index], \ + "%s/data/%s", g_fdfs_store_paths.paths[master_store_path_index].path, \ filename); sprintf(pFileContext->fname2log, \ "%c"FDFS_STORAGE_DATA_DIR_FORMAT"/%s", \ @@ -2775,6 +2790,7 @@ static int storage_trunk_do_create_link(struct fast_task_info *pTask, \ pTask, pFileContext->extra_info.upload.trunk_info.path. \ store_path_index, pFileContext->op); + pFileContext->continue_callback = storage_nio_notify; pFileContext->done_callback = done_callback; pClientInfo->clean_func = dio_trunk_write_finish_clean_up; @@ -2864,12 +2880,12 @@ static int storage_service_do_create_link(struct fast_task_info *pTask, \ else { sprintf(full_filename, "%s/data/%s", \ - g_fdfs_store_paths.paths[store_path_index], \ + g_fdfs_store_paths.paths[store_path_index].path, \ filename); } sprintf(src_full_filename, "%s/data/%s", \ - g_fdfs_store_paths.paths[store_path_index], \ + g_fdfs_store_paths.paths[store_path_index].path, \ pSrcFileInfo->src_true_filename); if (symlink(src_full_filename, full_filename) != 0) { @@ -3323,7 +3339,7 @@ static int storage_server_set_metadata(struct fast_task_info *pTask) pFileContext->timestamp2log = g_current_time; sprintf(pFileContext->filename, "%s/data/%s%s", \ - g_fdfs_store_paths.paths[store_path_index], true_filename, \ + g_fdfs_store_paths.paths[store_path_index].path, true_filename, \ FDFS_STORAGE_META_FILE_EXT); sprintf(pFileContext->fname2log,"%s%s", \ filename, FDFS_STORAGE_META_FILE_EXT); @@ -3432,6 +3448,170 @@ static int storage_server_trunk_sync_binlog(struct fast_task_info *pTask) return trunk_binlog_write_buffer(binlog_buff, nInPackLen); } +static int query_file_info_response(struct fast_task_info *pTask, + const StorageFileInfoForCRC32 *finfo, const int crc32) +{ + char *p; + + p = pTask->data + sizeof(TrackerHeader); + long2buff(finfo->fsize, p); + p += FDFS_PROTO_PKG_LEN_SIZE; + long2buff(finfo->mtime, p); + p += FDFS_PROTO_PKG_LEN_SIZE; + long2buff(crc32, p); + p += FDFS_PROTO_PKG_LEN_SIZE; + + memset(p, 0, IP_ADDRESS_SIZE); + if (fdfs_get_server_id_type(finfo->storage_id) == FDFS_ID_TYPE_SERVER_ID) + { + if (g_use_storage_id) + { + FDFSStorageIdInfo *pStorageIdInfo; + char id[16]; + + sprintf(id, "%d", finfo->storage_id); + pStorageIdInfo = fdfs_get_storage_by_id(id); + if (pStorageIdInfo != NULL) + { + strcpy(p, fdfs_get_ipaddr_by_peer_ip( + &pStorageIdInfo->ip_addrs, + pTask->client_ip)); + } + } + } + else + { + struct in_addr ip_addr; + memset(&ip_addr, 0, sizeof(ip_addr)); + ip_addr.s_addr = finfo->storage_id; + inet_ntop(AF_INET, &ip_addr, p, IP_ADDRESS_SIZE); + } + p += IP_ADDRESS_SIZE; + + ((StorageClientInfo *)pTask->arg)->total_length = p - pTask->data; + return 0; +} + +static void calc_crc32_done_callback_for_query_finfo( + struct fast_task_info *pTask, const int err_no) +{ + StorageClientInfo *pClientInfo; + StorageFileInfoForCRC32 *crc32_file_info; + StorageFileContext *pFileContext; + TrackerHeader *pHeader; + int result; + + pClientInfo = (StorageClientInfo *)pTask->arg; + pFileContext = &(pClientInfo->file_context); + crc32_file_info = (StorageFileInfoForCRC32 *)pClientInfo->extra_arg; + + if (err_no == 0) + { + result = query_file_info_response(pTask, crc32_file_info, + pFileContext->crc32); + } + else + { + result = err_no; + pClientInfo->total_length = sizeof(TrackerHeader); + } + + fast_mblock_free_object(&finfo_for_crc32_allocator, crc32_file_info); + + pClientInfo->total_offset = 0; + pTask->length = pClientInfo->total_length; + + pHeader = (TrackerHeader *)pTask->data; + pHeader->status = result; + pHeader->cmd = STORAGE_PROTO_CMD_RESP; + long2buff(pTask->length - sizeof(TrackerHeader), pHeader->pkg_len); + + STORAGE_ACCESS_LOG(pTask, ACCESS_LOG_ACTION_QUERY_FILE, result); + storage_nio_notify(pTask); +} + +static int calc_crc32_continue_callback(struct fast_task_info *pTask) +{ + pTask->length = 0; + return storage_dio_queue_push(pTask); +} + +static int push_calc_crc32_to_dio_queue(struct fast_task_info *pTask, + FileDealDoneCallback done_callback, const int store_path_index, + const struct stat *file_stat, const int storage_id) +{ + StorageClientInfo *pClientInfo; + StorageFileContext *pFileContext; + StorageFileInfoForCRC32 *crc32_file_info; + + pClientInfo = (StorageClientInfo *)pTask->arg; + pFileContext = &(pClientInfo->file_context); + + crc32_file_info = (StorageFileInfoForCRC32 *)fast_mblock_alloc_object( + &finfo_for_crc32_allocator); + if (crc32_file_info == NULL) + { + logError("file: "__FILE__", line: %d, " + "finfo_for_crc32_allocator %d bytes object fail", + __LINE__, (int)sizeof(StorageFileInfoForCRC32)); + return errno != 0 ? errno : ENOMEM; + } + + crc32_file_info->storage_id = storage_id; + crc32_file_info->fsize = file_stat->st_size; + crc32_file_info->mtime = file_stat->st_mtime; + pClientInfo->extra_arg = crc32_file_info; + + pFileContext->fd = -1; + pFileContext->calc_crc32 = true; + pFileContext->continue_callback = calc_crc32_continue_callback; + return storage_read_from_file(pTask, 0, file_stat->st_size, + done_callback, store_path_index); +} + +static int query_file_info_deal_response(struct fast_task_info *pTask, + const char *filename, const char *true_filename, + struct stat *file_stat, const int store_path_index) +{ + char decode_buff[64]; + int buff_len; + int storage_id; + int crc32; + int64_t file_size; + StorageFileInfoForCRC32 finfo; + + memset(decode_buff, 0, sizeof(decode_buff)); + base64_decode_auto(&g_fdfs_base64_context, filename + + FDFS_LOGIC_FILE_PATH_LEN, FDFS_FILENAME_BASE64_LENGTH, + decode_buff, &buff_len); + storage_id = ntohl(buff2int(decode_buff)); + file_size = buff2long(decode_buff + sizeof(int) * 2); + if (IS_APPENDER_FILE(file_size)) + { + StorageClientInfo *pClientInfo; + StorageFileContext *pFileContext; + + pClientInfo = (StorageClientInfo *)pTask->arg; + pFileContext = &(pClientInfo->file_context); + + snprintf(pFileContext->fname2log, sizeof(pFileContext->fname2log), + "%s", filename); + snprintf(pFileContext->filename, sizeof(pFileContext->filename), + "%s/data/%s", g_fdfs_store_paths.paths[store_path_index].path, + true_filename); + + return push_calc_crc32_to_dio_queue(pTask, + calc_crc32_done_callback_for_query_finfo, + store_path_index, file_stat, storage_id); + } + + finfo.storage_id = storage_id; + finfo.fsize = file_stat->st_size; + finfo.mtime = file_stat->st_mtime; + crc32 = buff2int(decode_buff + sizeof(int) * 4); + return query_file_info_response(pTask, &finfo, crc32); +} + /** FDFS_GROUP_NAME_MAX_LEN bytes: group_name filename @@ -3441,11 +3621,9 @@ static int storage_server_query_file_info(struct fast_task_info *pTask) StorageClientInfo *pClientInfo; char *in_buff; char *filename; - char *p; char group_name[FDFS_GROUP_NAME_MAX_LEN + 1]; char true_filename[128]; char src_filename[MAX_PATH_SIZE + 128]; - char decode_buff[64]; struct stat file_lstat; struct stat file_stat; FDFSTrunkFullInfo trunkInfo; @@ -3454,11 +3632,8 @@ static int storage_server_query_file_info(struct fast_task_info *pTask) int store_path_index; int filename_len; int true_filename_len; - int crc32; - int storage_id; int result; int len; - int buff_len; bool bSilence; pClientInfo = (StorageClientInfo *)pTask->arg; @@ -3597,10 +3772,9 @@ static int storage_server_query_file_info(struct fast_task_info *pTask) } else { - char full_filename[MAX_PATH_SIZE + 128]; - - sprintf(full_filename, "%s/data/%s", \ - g_fdfs_store_paths.paths[store_path_index], \ + char full_filename[MAX_PATH_SIZE + 128]; + sprintf(full_filename, "%s/data/%s", + g_fdfs_store_paths.paths[store_path_index].path, true_filename); if ((len=readlink(full_filename, src_filename, \ sizeof(src_filename))) < 0) @@ -3624,6 +3798,8 @@ static int storage_server_query_file_info(struct fast_task_info *pTask) return result; } } + + file_stat.st_mtime = file_lstat.st_mtime; } else { @@ -3641,50 +3817,8 @@ static int storage_server_query_file_info(struct fast_task_info *pTask) return EINVAL; } - memset(decode_buff, 0, sizeof(decode_buff)); - base64_decode_auto(&g_fdfs_base64_context, filename + \ - FDFS_LOGIC_FILE_PATH_LEN, FDFS_FILENAME_BASE64_LENGTH, \ - decode_buff, &buff_len); - storage_id = ntohl(buff2int(decode_buff)); - crc32 = buff2int(decode_buff + sizeof(int) * 4); - - p = pTask->data + sizeof(TrackerHeader); - long2buff(file_stat.st_size, p); - p += FDFS_PROTO_PKG_LEN_SIZE; - long2buff(file_lstat.st_mtime, p); - p += FDFS_PROTO_PKG_LEN_SIZE; - long2buff(crc32, p); - p += FDFS_PROTO_PKG_LEN_SIZE; - - memset(p, 0, IP_ADDRESS_SIZE); - if (fdfs_get_server_id_type(storage_id) == FDFS_ID_TYPE_SERVER_ID) - { - if (g_use_storage_id) - { - FDFSStorageIdInfo *pStorageIdInfo; - char id[16]; - - sprintf(id, "%d", storage_id); - pStorageIdInfo = fdfs_get_storage_by_id(id); - if (pStorageIdInfo != NULL) - { - strcpy(p, fdfs_get_ipaddr_by_peer_ip( - &pStorageIdInfo->ip_addrs, - pTask->client_ip)); - } - } - } - else - { - struct in_addr ip_addr; - memset(&ip_addr, 0, sizeof(ip_addr)); - ip_addr.s_addr = storage_id; - inet_ntop(AF_INET, &ip_addr, p, IP_ADDRESS_SIZE); - } - p += IP_ADDRESS_SIZE; - - pClientInfo->total_length = p - pTask->data; - return 0; + return query_file_info_deal_response(pTask, filename, + true_filename, &file_stat, store_path_index); } #define CHECK_TRUNK_SERVER(pTask) \ @@ -3925,7 +4059,7 @@ static int storage_server_trunk_delete_binlog_marks(struct fast_task_info *pTask } result = storage_delete_trunk_data_file(); - if (!(result == 0 || result == ENOENT)) + if (result != 0) { return result; } @@ -4012,7 +4146,7 @@ static int storage_server_trunk_confirm_or_free(struct fast_task_info *pTask) } } -static int storage_server_fetch_one_path_binlog_dealer( \ +static int storage_server_fetch_one_path_binlog_dealer( struct fast_task_info *pTask) { #define STORAGE_LAST_AHEAD_BYTES (2 * FDFS_PROTO_PKG_LEN_SIZE) @@ -4024,7 +4158,6 @@ static int storage_server_fetch_one_path_binlog_dealer( \ char *pBasePath; int result; int record_len; - int base_path_len; int len; int store_path_index; struct stat stat_buf; @@ -4036,7 +4169,7 @@ static int storage_server_fetch_one_path_binlog_dealer( \ int64_t pkg_len; pClientInfo = (StorageClientInfo *)pTask->arg; - if (pClientInfo->total_length - pClientInfo->total_offset <= \ + if (pClientInfo->total_length - pClientInfo->total_offset <= STORAGE_LAST_AHEAD_BYTES) //finished, close the connection { STORAGE_NIO_NOTIFY_CLOSE(pTask); @@ -4046,14 +4179,13 @@ static int storage_server_fetch_one_path_binlog_dealer( \ pFileContext = &(pClientInfo->file_context); pReader = (StorageBinLogReader *)pClientInfo->extra_arg; - store_path_index = pFileContext->extra_info.upload.trunk_info. \ + store_path_index = pFileContext->extra_info.upload.trunk_info. path.store_path_index; - pBasePath = g_fdfs_store_paths.paths[store_path_index]; - base_path_len = strlen(pBasePath); + pBasePath = g_fdfs_store_paths.paths[store_path_index].path; pOutBuff = pTask->data; bLast = false; - sprintf(diskLogicPath, "%c"FDFS_STORAGE_DATA_DIR_FORMAT, \ + sprintf(diskLogicPath, "%c"FDFS_STORAGE_DATA_DIR_FORMAT, FDFS_STORAGE_STORE_PATH_PREFIX_CHAR, store_path_index); do @@ -4070,7 +4202,8 @@ static int storage_server_fetch_one_path_binlog_dealer( \ break; } - if (g_fdfs_store_paths.paths[record.store_path_index] != pBasePath) + if (g_fdfs_store_paths.paths[record.store_path_index]. + path != pBasePath) { continue; } @@ -4078,7 +4211,9 @@ static int storage_server_fetch_one_path_binlog_dealer( \ if (!(record.op_type == STORAGE_OP_TYPE_SOURCE_CREATE_FILE || record.op_type == STORAGE_OP_TYPE_REPLICA_CREATE_FILE || record.op_type == STORAGE_OP_TYPE_SOURCE_CREATE_LINK - || record.op_type == STORAGE_OP_TYPE_REPLICA_CREATE_LINK)) + || record.op_type == STORAGE_OP_TYPE_REPLICA_CREATE_LINK + || record.op_type == STORAGE_OP_TYPE_SOURCE_RENAME_FILE + || record.op_type == STORAGE_OP_TYPE_REPLICA_RENAME_FILE)) { continue; } @@ -4096,8 +4231,8 @@ static int storage_server_fetch_one_path_binlog_dealer( \ } else { - snprintf(full_filename, sizeof(full_filename), "%s/data/%s", \ - g_fdfs_store_paths.paths[record.store_path_index], \ + snprintf(full_filename, sizeof(full_filename), "%s/data/%s", + g_fdfs_store_paths.paths[record.store_path_index].path, record.true_filename); if (lstat(full_filename, &stat_buf) != 0) { @@ -4107,10 +4242,10 @@ static int storage_server_fetch_one_path_binlog_dealer( \ } else { - logError("file: "__FILE__", line: %d, " \ - "call stat fail, file: %s, "\ - "error no: %d, error info: %s", \ - __LINE__, full_filename, \ + logError("file: "__FILE__", line: %d, " + "call stat fail, file: %s, " + "error no: %d, error info: %s", + __LINE__, full_filename, errno, STRERROR(errno)); result = errno != 0 ? errno : EPERM; break; @@ -4157,11 +4292,20 @@ static int storage_server_fetch_one_path_binlog_dealer( \ } } + if (record.op_type == STORAGE_OP_TYPE_SOURCE_RENAME_FILE) + { + record.op_type = STORAGE_OP_TYPE_SOURCE_CREATE_FILE; + } + else if (record.op_type == STORAGE_OP_TYPE_REPLICA_RENAME_FILE) + { + record.op_type = STORAGE_OP_TYPE_REPLICA_CREATE_FILE; + } + if (record.op_type == STORAGE_OP_TYPE_SOURCE_CREATE_FILE || record.op_type == STORAGE_OP_TYPE_REPLICA_CREATE_FILE) { - pOutBuff += sprintf(pOutBuff, "%d %c %s\n", \ - (int)record.timestamp, \ + pOutBuff += sprintf(pOutBuff, "%d %c %s\n", + (int)record.timestamp, record.op_type, record.filename); } else @@ -4183,7 +4327,7 @@ static int storage_server_fetch_one_path_binlog_dealer( \ break; } - if (len <= base_path_len) + if (len <= g_fdfs_store_paths.paths[store_path_index].path_len) { logWarning("file: "__FILE__", line: %d, " \ "invalid symbol link file: %s, " \ @@ -4203,19 +4347,27 @@ static int storage_server_fetch_one_path_binlog_dealer( \ } //full filename format: ${base_path}/data/filename - pOutBuff += sprintf(pOutBuff, "%d %c %s %s/%s\n", \ - (int)record.timestamp, \ - record.op_type, record.filename, \ - diskLogicPath, \ - src_filename + base_path_len + 6); + pOutBuff += sprintf(pOutBuff, "%d %c %s %s/%s\n", + (int)record.timestamp, + record.op_type, record.filename, + diskLogicPath, src_filename + g_fdfs_store_paths. + paths[store_path_index].path_len + 6); } - if (pTask->size - (pOutBuff - pTask->data) < \ + if (pTask->size - (pOutBuff - pTask->data) < STORAGE_BINLOG_LINE_SIZE + FDFS_PROTO_PKG_LEN_SIZE) { break; } - } while(1); + } while (g_continue_flag); + + if (!g_continue_flag) + { + if (result == 0) + { + result = EINTR; + } + } if (result != 0) //error occurs { @@ -4226,12 +4378,12 @@ static int storage_server_fetch_one_path_binlog_dealer( \ pTask->length = pOutBuff - pTask->data; if (bLast) { - pkg_len = pClientInfo->total_offset + pTask->length - \ + pkg_len = pClientInfo->total_offset + pTask->length - sizeof(TrackerHeader); long2buff(pkg_len, pOutBuff); pTask->length += FDFS_PROTO_PKG_LEN_SIZE; - pClientInfo->total_length = pkg_len + FDFS_PROTO_PKG_LEN_SIZE \ + pClientInfo->total_length = pkg_len + FDFS_PROTO_PKG_LEN_SIZE + STORAGE_LAST_AHEAD_BYTES; } @@ -4242,8 +4394,8 @@ static int storage_server_fetch_one_path_binlog_dealer( \ static void fetch_one_path_binlog_finish_clean_up(struct fast_task_info *pTask) { StorageClientInfo *pClientInfo; + StorageFileContext *pFileContext; StorageBinLogReader *pReader; - char full_filename[MAX_PATH_SIZE]; pClientInfo = (StorageClientInfo *)pTask->arg; pReader = (StorageBinLogReader *)pClientInfo->extra_arg; @@ -4254,17 +4406,24 @@ static void fetch_one_path_binlog_finish_clean_up(struct fast_task_info *pTask) pClientInfo->extra_arg = NULL; - storage_reader_destroy(pReader); - get_mark_filename_by_reader(pReader, full_filename); - if (fileExists(full_filename)) + storage_reader_remove_from_list(pReader); + get_mark_filename_by_reader(pReader); + if (fileExists(pReader->mark_filename)) { - unlink(full_filename); + unlink(pReader->mark_filename); } + pFileContext = &(pClientInfo->file_context); + logInfo("file: "__FILE__", line: %d, " + "client ip: %s, fetch binlog of store path #%d done", + __LINE__, pTask->client_ip, pFileContext->extra_info. + upload.trunk_info.path.store_path_index); + + storage_reader_destroy(pReader); free(pReader); } -static int storage_server_do_fetch_one_path_binlog( \ +static int storage_server_do_fetch_one_path_binlog( struct fast_task_info *pTask, const int store_path_index) { StorageClientInfo *pClientInfo; @@ -4283,6 +4442,10 @@ static int storage_server_do_fetch_one_path_binlog( \ return errno != 0 ? errno : ENOMEM; } + logInfo("file: "__FILE__", line: %d, " + "client ip: %s, fetch binlog of store path #%d ...", + __LINE__, pTask->client_ip, store_path_index); + pClientInfo = (StorageClientInfo *)pTask->arg; pFileContext = &(pClientInfo->file_context); @@ -4292,26 +4455,27 @@ static int storage_server_do_fetch_one_path_binlog( \ free(pReader); return result; } + storage_reader_add_to_list(pReader); pClientInfo->deal_func = storage_server_fetch_one_path_binlog_dealer; pClientInfo->clean_func = fetch_one_path_binlog_finish_clean_up; pFileContext->fd = -1; pFileContext->op = FDFS_STORAGE_FILE_OP_READ; - pFileContext->dio_thread_index = storage_dio_get_thread_index( \ + pFileContext->dio_thread_index = storage_dio_get_thread_index( pTask, store_path_index, pFileContext->op); pFileContext->extra_info.upload.trunk_info.path.store_path_index = store_path_index; pClientInfo->extra_arg = pReader; - pClientInfo->total_length = INFINITE_FILE_SIZE + \ + pClientInfo->total_length = INFINITE_FILE_SIZE + sizeof(TrackerHeader); pClientInfo->total_offset = 0; pTask->length = sizeof(TrackerHeader); pHeader = (TrackerHeader *)pTask->data; pHeader->status = 0; pHeader->cmd = STORAGE_PROTO_CMD_RESP; - long2buff(pClientInfo->total_length - sizeof(TrackerHeader), \ + long2buff(pClientInfo->total_length - sizeof(TrackerHeader), pHeader->pkg_len); storage_nio_notify(pTask); @@ -4369,7 +4533,7 @@ static int storage_server_fetch_one_path_binlog(struct fast_task_info *pTask) return EINVAL; } - return storage_server_do_fetch_one_path_binlog( \ + return storage_server_do_fetch_one_path_binlog( pTask, store_path_index); } @@ -4519,8 +4683,8 @@ static int storage_upload_file(struct fast_task_info *pTask, bool bAppenderFile) { char reserved_space_str[32]; - if (!storage_check_reserved_space_path(g_path_space_list \ - [store_path_index].total_mb, g_path_space_list \ + if (!storage_check_reserved_space_path(g_fdfs_store_paths.paths \ + [store_path_index].total_mb, g_fdfs_store_paths.paths \ [store_path_index].free_mb - (file_bytes/FDFS_ONE_MB), \ g_avg_storage_reserved_mb)) { @@ -4528,12 +4692,12 @@ static int storage_upload_file(struct fast_task_info *pTask, bool bAppenderFile) "no space to upload file, " "free space: %d MB is too small, file bytes: " \ "%"PRId64", reserved space: %s", \ - __LINE__, g_path_space_list[store_path_index].\ + __LINE__, g_fdfs_store_paths.paths[store_path_index].\ free_mb, file_bytes, \ fdfs_storage_reserved_space_to_string_ex( \ g_storage_reserved_space.flag, \ g_avg_storage_reserved_mb, \ - g_path_space_list[store_path_index]. \ + g_fdfs_store_paths.paths[store_path_index]. \ total_mb, g_storage_reserved_space.rs.ratio,\ reserved_space_str)); return ENOSPC; @@ -4561,8 +4725,9 @@ static int storage_upload_file(struct fast_task_info *pTask, bool bAppenderFile) | g_extra_open_file_flags; } - return storage_write_to_file(pTask, file_offset, file_bytes, \ - p - pTask->data, dio_write_file, \ + pFileContext->continue_callback = storage_nio_notify; + return storage_write_to_file(pTask, file_offset, file_bytes, \ + p - pTask->data, dio_write_file, \ storage_upload_file_done_callback, \ clean_func, store_path_index); } @@ -4589,6 +4754,258 @@ static int storage_deal_active_test(struct fast_task_info *pTask) return 0; } +static int storage_server_check_appender_file(struct fast_task_info *pTask, + char *appender_filename, const int appender_filename_len, + char *true_filename, struct stat *stat_buf, int *store_path_index) +{ + StorageFileContext *pFileContext; + char decode_buff[64]; + int result; + int filename_len; + int buff_len; + int64_t appender_file_size; + + pFileContext = &(((StorageClientInfo *)pTask->arg)->file_context); + filename_len = appender_filename_len; + if ((result=storage_split_filename_ex(appender_filename, + &filename_len, true_filename, store_path_index)) != 0) + { + return result; + } + if ((result=fdfs_check_data_filename(true_filename, filename_len)) != 0) + { + return result; + } + + snprintf(pFileContext->filename, sizeof(pFileContext->filename), + "%s/data/%s", g_fdfs_store_paths.paths[*store_path_index].path, + true_filename); + if (lstat(pFileContext->filename, stat_buf) == 0) + { + if (!S_ISREG(stat_buf->st_mode)) + { + logError("file: "__FILE__", line: %d, " + "client ip: %s, appender file: %s " + "is not a regular file", __LINE__, + pTask->client_ip, pFileContext->filename); + + return EINVAL; + } + } + else + { + result = errno != 0 ? errno : ENOENT; + if (result == ENOENT) + { + logWarning("file: "__FILE__", line: %d, " + "client ip: %s, appender file: %s " + "not exist", __LINE__, pTask->client_ip, + pFileContext->filename); + } + else + { + logError("file: "__FILE__", line: %d, " + "client ip: %s, stat appednder file %s fail, " + "errno: %d, error info: %s", + __LINE__, pTask->client_ip, + pFileContext->filename, result, STRERROR(result)); + } + + return result; + } + + strcpy(pFileContext->fname2log, appender_filename); + + memset(decode_buff, 0, sizeof(decode_buff)); + base64_decode_auto(&g_fdfs_base64_context, pFileContext->fname2log + + FDFS_LOGIC_FILE_PATH_LEN, FDFS_FILENAME_BASE64_LENGTH, + decode_buff, &buff_len); + + appender_file_size = buff2long(decode_buff + sizeof(int) * 2); + if (!IS_APPENDER_FILE(appender_file_size)) + { + logError("file: "__FILE__", line: %d, " + "client ip: %s, file: %s is not a valid " + "appender file, file size: %"PRId64, + __LINE__, pTask->client_ip, appender_filename, + appender_file_size); + + return EINVAL; + } + + return 0; +} + +static void calc_crc32_done_callback_for_regenerate( + struct fast_task_info *pTask, const int err_no) +{ + StorageClientInfo *pClientInfo; + StorageFileInfoForCRC32 *crc32_file_info; + StorageFileContext *pFileContext; + TrackerHeader *pHeader; + char full_filename[MAX_PATH_SIZE + 128]; + int result; + + pClientInfo = (StorageClientInfo *)pTask->arg; + pFileContext = &(pClientInfo->file_context); + crc32_file_info = (StorageFileInfoForCRC32 *)pClientInfo->extra_arg; + pHeader = (TrackerHeader *)pTask->data; + + if (err_no == 0) + { + char *formatted_ext_name; + char return_filename[128]; + char filename[128]; + int filename_len; + + *filename = '\0'; + filename_len = 0; + formatted_ext_name = pFileContext->filename + + (strlen(pFileContext->filename) - + (FDFS_FILE_EXT_NAME_MAX_LEN + 1)); + + pFileContext->timestamp2log = g_current_time; + if ((result=storage_get_filename(pClientInfo, + pFileContext->timestamp2log, + crc32_file_info->fsize, pFileContext->crc32, + formatted_ext_name, filename, &filename_len, + full_filename)) == 0) + { + if (*full_filename == '\0') + { + result = EBUSY; + logWarning("file: "__FILE__", line: %d, " + "Can't generate uniq filename", __LINE__); + } + else + { + if (rename(pFileContext->filename, full_filename) != 0) + { + result = errno != 0 ? errno : EPERM; + logWarning("file: "__FILE__", line: %d, " + "rename %s to %s fail, " + "errno: %d, error info: %s", __LINE__, + pFileContext->filename, full_filename, + result, STRERROR(result)); + } + else + { + char *p; + char binlog_msg[256]; + + filename_len = snprintf(return_filename, + sizeof(return_filename), + "%c"FDFS_STORAGE_DATA_DIR_FORMAT"/%s", + FDFS_STORAGE_STORE_PATH_PREFIX_CHAR, + pFileContext->extra_info.upload.trunk_info. + path.store_path_index, filename); + + sprintf(binlog_msg, "%s %s", + return_filename, pFileContext->fname2log); + result = storage_binlog_write( + pFileContext->timestamp2log, + STORAGE_OP_TYPE_SOURCE_RENAME_FILE, + binlog_msg); + + pClientInfo->total_length = sizeof(TrackerHeader) + + FDFS_GROUP_NAME_MAX_LEN + filename_len; + p = pTask->data + sizeof(TrackerHeader); + memcpy(p, g_group_name, FDFS_GROUP_NAME_MAX_LEN); + p += FDFS_GROUP_NAME_MAX_LEN; + memcpy(p, return_filename, filename_len); + + if (g_use_access_log) + { + snprintf(pFileContext->fname2log + + strlen(pFileContext->fname2log), + sizeof(pFileContext->fname2log), + "=>%s", return_filename); + } + } + } + } + } + else + { + result = err_no; + } + + fast_mblock_free_object(&finfo_for_crc32_allocator, crc32_file_info); + if (result != 0) + { + pClientInfo->total_length = sizeof(TrackerHeader); + } + + pClientInfo->total_offset = 0; + pTask->length = pClientInfo->total_length; + + pHeader->status = result; + pHeader->cmd = STORAGE_PROTO_CMD_RESP; + long2buff(pTask->length - sizeof(TrackerHeader), pHeader->pkg_len); + + STORAGE_ACCESS_LOG(pTask, ACCESS_LOG_ACTION_RENAME_FILE, result); + storage_nio_notify(pTask); +} + +/** +body length: appender filename +**/ +static int storage_server_regenerate_appender_filename(struct fast_task_info *pTask) +{ + StorageClientInfo *pClientInfo; + StorageFileContext *pFileContext; + FDFSTrunkFullInfo *pTrunkInfo; + char *p; + char appender_filename[128]; + char true_filename[128]; + struct stat stat_buf; + int appender_filename_len; + int64_t nInPackLen; + int result; + int store_path_index; + + pClientInfo = (StorageClientInfo *)pTask->arg; + pFileContext = &(pClientInfo->file_context); + + nInPackLen = pClientInfo->total_length - sizeof(TrackerHeader); + appender_filename_len = nInPackLen; + if ((nInPackLen < FDFS_LOGIC_FILE_PATH_LEN + FDFS_FILENAME_BASE64_LENGTH + + FDFS_FILE_EXT_NAME_MAX_LEN + 1) + || (appender_filename_len >= sizeof(appender_filename))) + { + logError("file: "__FILE__", line: %d, " + "client ip: %s, invalid package length: %"PRId64, + __LINE__, pTask->client_ip, nInPackLen); + return EINVAL; + } + + p = pTask->data + sizeof(TrackerHeader); + memcpy(appender_filename, p, appender_filename_len); + *(appender_filename + appender_filename_len) = '\0'; + + STORAGE_ACCESS_STRCPY_FNAME2LOG(appender_filename, + appender_filename_len, pClientInfo); + + if ((result=storage_server_check_appender_file(pTask, + appender_filename, appender_filename_len, + true_filename, &stat_buf, &store_path_index)) != 0) + { + return result; + } + + pTrunkInfo = &(pClientInfo->file_context.extra_info.upload.trunk_info); + pClientInfo->file_context.extra_info.upload.if_sub_path_alloced = true; + pFileContext->extra_info.upload.trunk_info.path.store_path_index = + store_path_index; + pTrunkInfo->path.sub_path_high = strtol(true_filename, NULL, 16); + pTrunkInfo->path.sub_path_low = strtol(true_filename + 3, NULL, 16); + + return push_calc_crc32_to_dio_queue(pTask, + calc_crc32_done_callback_for_regenerate, + store_path_index, &stat_buf, + g_server_id_in_filename); +} + /** 8 bytes: appender filename length 8 bytes: file size @@ -4602,16 +5019,12 @@ static int storage_append_file(struct fast_task_info *pTask) char *p; char appender_filename[128]; char true_filename[128]; - char decode_buff[64]; struct stat stat_buf; int appender_filename_len; int64_t nInPackLen; int64_t file_bytes; - int64_t appender_file_size; int result; int store_path_index; - int filename_len; - int buff_len; pClientInfo = (StorageClientInfo *)pTask->arg; pFileContext = &(pClientInfo->file_context); @@ -4659,76 +5072,16 @@ static int storage_append_file(struct fast_task_info *pTask) memcpy(appender_filename, p, appender_filename_len); *(appender_filename + appender_filename_len) = '\0'; p += appender_filename_len; - filename_len = appender_filename_len; - STORAGE_ACCESS_STRCPY_FNAME2LOG(appender_filename, \ + STORAGE_ACCESS_STRCPY_FNAME2LOG(appender_filename, appender_filename_len, pClientInfo); - if ((result=storage_split_filename_ex(appender_filename, \ - &filename_len, true_filename, &store_path_index)) != 0) - { - return result; - } - if ((result=fdfs_check_data_filename(true_filename, filename_len)) != 0) - { - return result; - } - - snprintf(pFileContext->filename, sizeof(pFileContext->filename), \ - "%s/data/%s", g_fdfs_store_paths.paths[store_path_index], true_filename); - if (lstat(pFileContext->filename, &stat_buf) == 0) - { - if (!S_ISREG(stat_buf.st_mode)) - { - logError("file: "__FILE__", line: %d, " \ - "client ip: %s, appender file: %s " \ - "is not a regular file", __LINE__, \ - pTask->client_ip, pFileContext->filename); - - return EINVAL; - } - } - else - { - result = errno != 0 ? errno : ENOENT; - if (result == ENOENT) - { - logWarning("file: "__FILE__", line: %d, " \ - "client ip: %s, appender file: %s " \ - "not exist", __LINE__, \ - pTask->client_ip, pFileContext->filename); - } - else - { - logError("file: "__FILE__", line: %d, " \ - "client ip: %s, stat appednder file %s fail" \ - ", errno: %d, error info: %s.", \ - __LINE__, pTask->client_ip, \ - pFileContext->filename, \ - result, STRERROR(result)); - } - - return result; - } - - strcpy(pFileContext->fname2log, appender_filename); - - memset(decode_buff, 0, sizeof(decode_buff)); - base64_decode_auto(&g_fdfs_base64_context, pFileContext->fname2log + \ - FDFS_LOGIC_FILE_PATH_LEN, FDFS_FILENAME_BASE64_LENGTH, \ - decode_buff, &buff_len); - - appender_file_size = buff2long(decode_buff + sizeof(int) * 2); - if (!IS_APPENDER_FILE(appender_file_size)) - { - logError("file: "__FILE__", line: %d, " \ - "client ip: %s, file: %s is not a valid " \ - "appender file, file size: %"PRId64, \ - __LINE__, pTask->client_ip, appender_filename, \ - appender_file_size); - - return EINVAL; - } + if ((result=storage_server_check_appender_file(pTask, + appender_filename, appender_filename_len, + true_filename, &stat_buf, &store_path_index)) != 0) + { + return result; + } if (file_bytes == 0) { @@ -4741,23 +5094,20 @@ static int storage_append_file(struct fast_task_info *pTask) pFileContext->calc_crc32 = false; pFileContext->calc_file_hash = false; - snprintf(pFileContext->filename, sizeof(pFileContext->filename), \ - "%s/data/%s", g_fdfs_store_paths.paths[store_path_index], \ - true_filename); - pFileContext->sync_flag = STORAGE_OP_TYPE_SOURCE_APPEND_FILE; pFileContext->timestamp2log = pFileContext->extra_info.upload.start_time; pFileContext->extra_info.upload.file_type = _FILE_TYPE_APPENDER; pFileContext->extra_info.upload.before_open_callback = NULL; pFileContext->extra_info.upload.before_close_callback = NULL; - pFileContext->extra_info.upload.trunk_info.path.store_path_index = \ + pFileContext->extra_info.upload.trunk_info.path.store_path_index = store_path_index; pFileContext->op = FDFS_STORAGE_FILE_OP_APPEND; pFileContext->open_flags = O_WRONLY | O_APPEND | g_extra_open_file_flags; + pFileContext->continue_callback = storage_nio_notify; - return storage_write_to_file(pTask, stat_buf.st_size, file_bytes, \ - p - pTask->data, dio_write_file, \ - storage_append_file_done_callback, \ + return storage_write_to_file(pTask, stat_buf.st_size, file_bytes, + p - pTask->data, dio_write_file, + storage_append_file_done_callback, dio_append_finish_clean_up, store_path_index); } @@ -4775,17 +5125,13 @@ static int storage_modify_file(struct fast_task_info *pTask) char *p; char appender_filename[128]; char true_filename[128]; - char decode_buff[64]; struct stat stat_buf; int appender_filename_len; int64_t nInPackLen; int64_t file_offset; int64_t file_bytes; - int64_t appender_file_size; int result; int store_path_index; - int filename_len; - int buff_len; pClientInfo = (StorageClientInfo *)pTask->arg; pFileContext = &(pClientInfo->file_context); @@ -4844,83 +5190,23 @@ static int storage_modify_file(struct fast_task_info *pTask) memcpy(appender_filename, p, appender_filename_len); *(appender_filename + appender_filename_len) = '\0'; p += appender_filename_len; - filename_len = appender_filename_len; STORAGE_ACCESS_STRCPY_FNAME2LOG(appender_filename, \ appender_filename_len, pClientInfo); - if ((result=storage_split_filename_ex(appender_filename, \ - &filename_len, true_filename, &store_path_index)) != 0) - { - return result; - } - if ((result=fdfs_check_data_filename(true_filename, filename_len)) != 0) - { - return result; - } - - snprintf(pFileContext->filename, sizeof(pFileContext->filename), \ - "%s/data/%s", g_fdfs_store_paths.paths[store_path_index], true_filename); - if (lstat(pFileContext->filename, &stat_buf) == 0) - { - if (!S_ISREG(stat_buf.st_mode)) - { - logError("file: "__FILE__", line: %d, " \ - "client ip: %s, appender file: %s " \ - "is not a regular file", __LINE__, \ - pTask->client_ip, pFileContext->filename); - - return EINVAL; - } - } - else - { - result = errno != 0 ? errno : ENOENT; - if (result == ENOENT) - { - logWarning("file: "__FILE__", line: %d, " \ - "client ip: %s, appender file: %s " \ - "not exist", __LINE__, \ - pTask->client_ip, pFileContext->filename); - } - else - { - logError("file: "__FILE__", line: %d, " \ - "client ip: %s, stat appednder file %s fail" \ - ", errno: %d, error info: %s.", \ - __LINE__, pTask->client_ip, \ - pFileContext->filename, \ - result, STRERROR(result)); - } - - return result; - } - - strcpy(pFileContext->fname2log, appender_filename); - - memset(decode_buff, 0, sizeof(decode_buff)); - base64_decode_auto(&g_fdfs_base64_context, pFileContext->fname2log + \ - FDFS_LOGIC_FILE_PATH_LEN, FDFS_FILENAME_BASE64_LENGTH, \ - decode_buff, &buff_len); - - appender_file_size = buff2long(decode_buff + sizeof(int) * 2); - if (!IS_APPENDER_FILE(appender_file_size)) - { - logError("file: "__FILE__", line: %d, " \ - "client ip: %s, file: %s is not a valid " \ - "appender file, file size: %"PRId64, \ - __LINE__, pTask->client_ip, appender_filename, \ - appender_file_size); - - return EINVAL; - } + if ((result=storage_server_check_appender_file(pTask, + appender_filename, appender_filename_len, + true_filename, &stat_buf, &store_path_index)) != 0) + { + return result; + } if (file_offset > stat_buf.st_size) { - logError("file: "__FILE__", line: %d, " \ - "client ip: %s, file offset: %"PRId64 \ - " is invalid, which > appender file size: %" \ - PRId64, __LINE__, pTask->client_ip, \ + logError("file: "__FILE__", line: %d, " + "client ip: %s, file offset: %"PRId64 + " is invalid, which > appender file size: %" + PRId64, __LINE__, pTask->client_ip, file_offset, (int64_t)stat_buf.st_size); return EINVAL; @@ -4937,22 +5223,20 @@ static int storage_modify_file(struct fast_task_info *pTask) pFileContext->calc_crc32 = false; pFileContext->calc_file_hash = false; - snprintf(pFileContext->filename, sizeof(pFileContext->filename), \ - "%s/data/%s", g_fdfs_store_paths.paths[store_path_index], true_filename); - pFileContext->sync_flag = STORAGE_OP_TYPE_SOURCE_MODIFY_FILE; pFileContext->timestamp2log = pFileContext->extra_info.upload.start_time; pFileContext->extra_info.upload.file_type = _FILE_TYPE_APPENDER; pFileContext->extra_info.upload.before_open_callback = NULL; pFileContext->extra_info.upload.before_close_callback = NULL; - pFileContext->extra_info.upload.trunk_info.path.store_path_index = \ + pFileContext->extra_info.upload.trunk_info.path.store_path_index = store_path_index; pFileContext->op = FDFS_STORAGE_FILE_OP_WRITE; pFileContext->open_flags = O_WRONLY | g_extra_open_file_flags; + pFileContext->continue_callback = storage_nio_notify; - return storage_write_to_file(pTask, file_offset, file_bytes, \ - p - pTask->data, dio_write_file, \ - storage_modify_file_done_callback, \ + return storage_write_to_file(pTask, file_offset, file_bytes, + p - pTask->data, dio_write_file, + storage_modify_file_done_callback, dio_modify_finish_clean_up, store_path_index); } @@ -4967,7 +5251,6 @@ static int storage_do_truncate_file(struct fast_task_info *pTask) StorageFileContext *pFileContext; char *p; char appender_filename[128]; - char true_filename[128]; char decode_buff[64]; struct stat stat_buf; int appender_filename_len; @@ -5029,18 +5312,14 @@ static int storage_do_truncate_file(struct fast_task_info *pTask) STORAGE_ACCESS_STRCPY_FNAME2LOG(appender_filename, \ appender_filename_len, pClientInfo); - if ((result=storage_split_filename_ex(appender_filename, \ - &filename_len, true_filename, &store_path_index)) != 0) - { - return result; - } - if ((result=fdfs_check_data_filename(true_filename, filename_len)) != 0) + if ((result=storage_logic_to_local_full_filename( + appender_filename, filename_len, + &store_path_index, pFileContext->filename, + sizeof(pFileContext->filename))) != 0) { return result; } - snprintf(pFileContext->filename, sizeof(pFileContext->filename), \ - "%s/data/%s", g_fdfs_store_paths.paths[store_path_index], true_filename); if (lstat(pFileContext->filename, &stat_buf) == 0) { if (!S_ISREG(stat_buf.st_mode)) @@ -5120,9 +5399,6 @@ static int storage_do_truncate_file(struct fast_task_info *pTask) pFileContext->calc_crc32 = false; pFileContext->calc_file_hash = false; - snprintf(pFileContext->filename, sizeof(pFileContext->filename), \ - "%s/data/%s", g_fdfs_store_paths.paths[store_path_index], true_filename); - pFileContext->sync_flag = STORAGE_OP_TYPE_SOURCE_TRUNCATE_FILE; pFileContext->timestamp2log = pFileContext->extra_info.upload.start_time; pFileContext->extra_info.upload.file_type = _FILE_TYPE_APPENDER; @@ -5132,6 +5408,7 @@ static int storage_do_truncate_file(struct fast_task_info *pTask) store_path_index; pFileContext->op = FDFS_STORAGE_FILE_OP_WRITE; pFileContext->open_flags = O_WRONLY | g_extra_open_file_flags; + pFileContext->continue_callback = storage_nio_notify; return storage_write_to_file(pTask, remain_bytes, \ stat_buf.st_size, 0, dio_truncate_file, \ @@ -5260,8 +5537,8 @@ static int storage_upload_slave_file(struct fast_task_info *pTask) return result; } - if (!storage_check_reserved_space_path(g_path_space_list \ - [store_path_index].total_mb, g_path_space_list \ + if (!storage_check_reserved_space_path(g_fdfs_store_paths.paths \ + [store_path_index].total_mb, g_fdfs_store_paths.paths \ [store_path_index].free_mb - (file_bytes / FDFS_ONE_MB), \ g_avg_storage_reserved_mb)) { @@ -5269,11 +5546,11 @@ static int storage_upload_slave_file(struct fast_task_info *pTask) "no space to upload file, " "free space: %d MB is too small, file bytes: " \ "%"PRId64", reserved space: %s", __LINE__,\ - g_path_space_list[store_path_index].free_mb, \ + g_fdfs_store_paths.paths[store_path_index].free_mb, \ file_bytes, fdfs_storage_reserved_space_to_string_ex(\ g_storage_reserved_space.flag, \ g_avg_storage_reserved_mb, \ - g_path_space_list[store_path_index].total_mb, \ + g_fdfs_store_paths.paths[store_path_index].total_mb, \ g_storage_reserved_space.rs.ratio, \ reserved_space_str)); return ENOSPC; @@ -5316,7 +5593,7 @@ static int storage_upload_slave_file(struct fast_task_info *pTask) } snprintf(pFileContext->filename, sizeof(pFileContext->filename), \ - "%s/data/%s", g_fdfs_store_paths.paths[store_path_index], filename); + "%s/data/%s", g_fdfs_store_paths.paths[store_path_index].path, filename); if (fileExists(pFileContext->filename)) { logError("file: "__FILE__", line: %d, " \ @@ -5366,6 +5643,7 @@ static int storage_upload_slave_file(struct fast_task_info *pTask) pFileContext->op = FDFS_STORAGE_FILE_OP_WRITE; pFileContext->open_flags = O_WRONLY | O_CREAT | O_TRUNC \ | g_extra_open_file_flags; + pFileContext->continue_callback = storage_nio_notify; return storage_write_to_file(pTask, 0, file_bytes, p - pTask->data, \ dio_write_file, storage_upload_file_done_callback, \ @@ -5613,7 +5891,7 @@ static int storage_sync_copy_file(struct fast_task_info *pTask, \ sprintf(pFileContext->filename, "%s/data/.cp" \ "%"PRId64".tmp", \ - g_fdfs_store_paths.paths[store_path_index], \ + g_fdfs_store_paths.paths[store_path_index].path, \ temp_file_sequence++); pthread_mutex_unlock(&g_storage_thread_lock); @@ -5678,6 +5956,7 @@ static int storage_sync_copy_file(struct fast_task_info *pTask, \ pFileContext->calc_crc32 = false; pFileContext->calc_file_hash = false; strcpy(pFileContext->fname2log, filename); + pFileContext->continue_callback = storage_nio_notify; if (have_file_content) { @@ -5709,7 +5988,6 @@ static int storage_sync_append_file(struct fast_task_info *pTask) TaskDealFunc deal_func; char *p; char group_name[FDFS_GROUP_NAME_MAX_LEN + 1]; - char true_filename[128]; char filename[128]; bool need_write_file; int filename_len; @@ -5805,19 +6083,13 @@ static int storage_sync_append_file(struct fast_task_info *pTask) *(filename + filename_len) = '\0'; p += filename_len; - if ((result=storage_split_filename_ex(filename, \ - &filename_len, true_filename, &store_path_index)) != 0) + if ((result=storage_logic_to_local_full_filename( + filename, filename_len, + &store_path_index, pFileContext->filename, + sizeof(pFileContext->filename))) != 0) { return result; } - if ((result=fdfs_check_data_filename(true_filename, filename_len)) != 0) - { - return result; - } - - snprintf(pFileContext->filename, sizeof(pFileContext->filename), \ - "%s/data/%s", g_fdfs_store_paths.paths[store_path_index], \ - true_filename); if (lstat(pFileContext->filename, &stat_buf) != 0) { @@ -5913,6 +6185,7 @@ static int storage_sync_append_file(struct fast_task_info *pTask) pFileContext->calc_file_hash = false; pFileContext->extra_info.upload.before_open_callback = NULL; pFileContext->extra_info.upload.before_close_callback = NULL; + pFileContext->continue_callback = storage_nio_notify; return storage_write_to_file(pTask, start_offset, append_bytes, \ p - pTask->data, deal_func, \ @@ -5936,7 +6209,6 @@ static int storage_sync_modify_file(struct fast_task_info *pTask) TaskDealFunc deal_func; char *p; char group_name[FDFS_GROUP_NAME_MAX_LEN + 1]; - char true_filename[128]; char filename[128]; bool need_write_file; int filename_len; @@ -6033,19 +6305,13 @@ static int storage_sync_modify_file(struct fast_task_info *pTask) *(filename + filename_len) = '\0'; p += filename_len; - if ((result=storage_split_filename_ex(filename, \ - &filename_len, true_filename, &store_path_index)) != 0) + if ((result=storage_logic_to_local_full_filename( + filename, filename_len, + &store_path_index, pFileContext->filename, + sizeof(pFileContext->filename))) != 0) { return result; } - if ((result=fdfs_check_data_filename(true_filename, filename_len)) != 0) - { - return result; - } - - snprintf(pFileContext->filename, sizeof(pFileContext->filename), \ - "%s/data/%s", g_fdfs_store_paths.paths[store_path_index], \ - true_filename); if (lstat(pFileContext->filename, &stat_buf) != 0) { @@ -6114,6 +6380,7 @@ static int storage_sync_modify_file(struct fast_task_info *pTask) pFileContext->calc_file_hash = false; pFileContext->extra_info.upload.before_open_callback = NULL; pFileContext->extra_info.upload.before_close_callback = NULL; + pFileContext->continue_callback = storage_nio_notify; return storage_write_to_file(pTask, start_offset, modify_bytes, \ p - pTask->data, deal_func, \ @@ -6135,7 +6402,6 @@ static int storage_sync_truncate_file(struct fast_task_info *pTask) StorageFileContext *pFileContext; char *p; char group_name[FDFS_GROUP_NAME_MAX_LEN + 1]; - char true_filename[128]; char filename[128]; int filename_len; int64_t nInPackLen; @@ -6233,19 +6499,13 @@ static int storage_sync_truncate_file(struct fast_task_info *pTask) *(filename + filename_len) = '\0'; p += filename_len; - if ((result=storage_split_filename_ex(filename, \ - &filename_len, true_filename, &store_path_index)) != 0) + if ((result=storage_logic_to_local_full_filename( + filename, filename_len, + &store_path_index, pFileContext->filename, + sizeof(pFileContext->filename))) != 0) { return result; } - if ((result=fdfs_check_data_filename(true_filename, filename_len)) != 0) - { - return result; - } - - snprintf(pFileContext->filename, sizeof(pFileContext->filename), \ - "%s/data/%s", g_fdfs_store_paths.paths[store_path_index], \ - true_filename); if (lstat(pFileContext->filename, &stat_buf) != 0) { @@ -6299,6 +6559,7 @@ static int storage_sync_truncate_file(struct fast_task_info *pTask) pFileContext->calc_file_hash = false; pFileContext->extra_info.upload.before_open_callback = NULL; pFileContext->extra_info.upload.before_close_callback = NULL; + pFileContext->continue_callback = storage_nio_notify; return storage_write_to_file(pTask, new_file_size, \ old_file_size, 0, dio_truncate_file, \ @@ -6491,11 +6752,11 @@ static int storage_do_sync_link_file(struct fast_task_info *pTask) else { snprintf(pFileContext->filename, sizeof(pFileContext->filename), \ - "%s/data/%s", g_fdfs_store_paths.paths[dest_store_path_index], \ + "%s/data/%s", g_fdfs_store_paths.paths[dest_store_path_index].path, \ dest_true_filename); snprintf(src_full_filename, sizeof(src_full_filename), \ - "%s/data/%s", g_fdfs_store_paths.paths[src_store_path_index], \ + "%s/data/%s", g_fdfs_store_paths.paths[src_store_path_index].path, \ src_true_filename); if (symlink(src_full_filename, pFileContext->filename) != 0) { @@ -6643,6 +6904,135 @@ static int storage_sync_link_file(struct fast_task_info *pTask) return STORAGE_STATUE_DEAL_FILE; } +static int storage_sync_rename_file(struct fast_task_info *pTask) +{ + StorageClientInfo *pClientInfo; + StorageFileContext *pFileContext; + char *p; + char group_name[FDFS_GROUP_NAME_MAX_LEN + 1]; + char dest_filename[128]; + char dest_full_filename[MAX_PATH_SIZE]; + char src_full_filename[MAX_PATH_SIZE]; + char src_filename[128]; + int64_t nInPackLen; + int dest_filename_len; + int src_filename_len; + int result; + int dest_store_path_index; + int src_store_path_index; + + pClientInfo = (StorageClientInfo *)pTask->arg; + pFileContext = &(pClientInfo->file_context); + + nInPackLen = pClientInfo->total_length - sizeof(TrackerHeader); + if (nInPackLen <= 2 * FDFS_PROTO_PKG_LEN_SIZE + + 4 + FDFS_GROUP_NAME_MAX_LEN) + { + logError("file: "__FILE__", line: %d, " + "client ip: %s, package size " + "%"PRId64" is not correct, " + "expect length > %d", __LINE__, + pTask->client_ip, nInPackLen, + 2 * FDFS_PROTO_PKG_LEN_SIZE + + 4 + FDFS_GROUP_NAME_MAX_LEN); + return EINVAL; + } + + p = pTask->data + sizeof(TrackerHeader); + + dest_filename_len = buff2long(p); + p += FDFS_PROTO_PKG_LEN_SIZE; + + src_filename_len = buff2long(p); + p += FDFS_PROTO_PKG_LEN_SIZE; + + if (dest_filename_len < 0 || dest_filename_len >= sizeof(dest_filename)) + { + logError("file: "__FILE__", line: %d, " + "client ip: %s, in request pkg, " + "filename length: %d is invalid, " + "which < 0 or >= %d", __LINE__, pTask->client_ip, + dest_filename_len, (int)sizeof(dest_filename)); + return EINVAL; + } + + pFileContext->timestamp2log = buff2int(p); + p += 4; + + memcpy(group_name, p, FDFS_GROUP_NAME_MAX_LEN); + *(group_name + FDFS_GROUP_NAME_MAX_LEN) = '\0'; + p += FDFS_GROUP_NAME_MAX_LEN; + if (strcmp(group_name, g_group_name) != 0) + { + logError("file: "__FILE__", line: %d, " + "client ip:%s, group_name: %s " + "not correct, should be: %s", + __LINE__, pTask->client_ip, + group_name, g_group_name); + return EINVAL; + } + + if (nInPackLen != 2 * FDFS_PROTO_PKG_LEN_SIZE + 4 + + FDFS_GROUP_NAME_MAX_LEN + dest_filename_len + src_filename_len) + { + logError("file: "__FILE__", line: %d, " + "client ip: %s, in request pkg, " + "pgk length: %"PRId64" != bytes: %d", + __LINE__, pTask->client_ip, + nInPackLen, 2 * FDFS_PROTO_PKG_LEN_SIZE + + FDFS_GROUP_NAME_MAX_LEN + dest_filename_len + + src_filename_len); + return EINVAL; + } + + memcpy(dest_filename, p, dest_filename_len); + *(dest_filename + dest_filename_len) = '\0'; + p += dest_filename_len; + + memcpy(src_filename, p, src_filename_len); + *(src_filename + src_filename_len) = '\0'; + + if ((result=storage_logic_to_local_full_filename( + dest_filename, dest_filename_len, + &dest_store_path_index, dest_full_filename, + sizeof(dest_full_filename))) != 0) + { + return result; + } + + if (access(dest_full_filename, F_OK) == 0) + { + logDebug("file: "__FILE__", line: %d, " + "client ip: %s, dest file: %s " + "already exist", __LINE__, + pTask->client_ip, dest_full_filename); + return EEXIST; + } + + if ((result=storage_logic_to_local_full_filename( + src_filename, src_filename_len, + &src_store_path_index, src_full_filename, + sizeof(src_full_filename))) != 0) + { + return result; + } + + if (rename(src_full_filename, dest_full_filename) != 0) + { + result = errno != 0 ? errno : EPERM; + logWarning("file: "__FILE__", line: %d, " + "client ip: %s, rename %s to %s fail, " + "errno: %d, error info: %s", __LINE__, + pTask->client_ip, src_full_filename, + dest_full_filename, result, STRERROR(result)); + return result; + } + + return storage_binlog_write_ex(pFileContext->timestamp2log, + STORAGE_OP_TYPE_REPLICA_RENAME_FILE, + dest_filename, src_filename); +} + /** pkg format: Header @@ -6736,7 +7126,7 @@ static int storage_server_get_metadata(struct fast_task_info *pTask) } sprintf(pFileContext->filename, "%s/data/%s%s", \ - g_fdfs_store_paths.paths[store_path_index], \ + g_fdfs_store_paths.paths[store_path_index].path, \ true_filename, FDFS_STORAGE_META_FILE_EXT); if (lstat(pFileContext->filename, &stat_buf) == 0) { @@ -6759,6 +7149,8 @@ static int storage_server_get_metadata(struct fast_task_info *pTask) } pFileContext->fd = -1; + pFileContext->calc_crc32 = false; + pFileContext->continue_callback = storage_nio_notify; return storage_read_from_file(pTask, 0, file_bytes, \ storage_get_metadata_done_callback, store_path_index); } @@ -6936,9 +7328,11 @@ static int storage_server_download_file(struct fast_task_info *pTask) else { sprintf(pFileContext->filename, "%s/data/%s", \ - g_fdfs_store_paths.paths[store_path_index], true_filename); + g_fdfs_store_paths.paths[store_path_index].path, true_filename); } + pFileContext->calc_crc32 = false; + pFileContext->continue_callback = storage_nio_notify; return storage_read_from_file(pTask, file_offset, download_bytes, \ storage_download_file_done_callback, store_path_index); } @@ -7004,6 +7398,10 @@ static int storage_read_from_file(struct fast_task_info *pTask, \ pHeader->cmd = STORAGE_PROTO_CMD_RESP; long2buff(download_bytes, pHeader->pkg_len); + if (pFileContext->calc_crc32) + { + pFileContext->crc32 = CRC32_XINIT; + } if ((result=storage_dio_queue_push(pTask)) != 0) { if (pFileContext->fd >= 0) @@ -7182,7 +7580,7 @@ static int storage_sync_delete_file(struct fast_task_info *pTask) { pClientInfo->deal_func = dio_delete_normal_file; sprintf(pFileContext->filename, "%s/data/%s", \ - g_fdfs_store_paths.paths[store_path_index], true_filename); + g_fdfs_store_paths.paths[store_path_index].path, true_filename); } strcpy(pFileContext->fname2log, filename); @@ -7317,7 +7715,7 @@ static int storage_server_delete_file(struct fast_task_info *pTask) { pClientInfo->deal_func = dio_delete_normal_file; sprintf(pFileContext->filename, "%s/data/%s", \ - g_fdfs_store_paths.paths[store_path_index], true_filename); + g_fdfs_store_paths.paths[store_path_index].path, true_filename); } if ((pFileContext->extra_info.upload.file_type & _FILE_TYPE_LINK) && \ @@ -7328,12 +7726,11 @@ static int storage_server_delete_file(struct fast_task_info *pTask) char src_fname2log[128]; char *src_true_filename; int src_filename_len; - int base_path_len; int src_store_path_index; int i; sprintf(full_filename, "%s/data/%s", \ - g_fdfs_store_paths.paths[store_path_index], true_filename); + g_fdfs_store_paths.paths[store_path_index].path, true_filename); do { if ((src_filename_len=readlink(full_filename, \ @@ -7364,11 +7761,11 @@ static int storage_server_delete_file(struct fast_task_info *pTask) return result; } - base_path_len = strlen(g_fdfs_store_paths.paths \ - [store_path_index]); - if (src_filename_len > base_path_len && memcmp( \ - src_filename, g_fdfs_store_paths.paths \ - [store_path_index], base_path_len) == 0) + if (src_filename_len > g_fdfs_store_paths.paths + [store_path_index].path_len && memcmp( + src_filename, g_fdfs_store_paths.paths + [store_path_index].path, g_fdfs_store_paths. + paths[store_path_index].path_len) == 0) { src_store_path_index = store_path_index; } @@ -7377,10 +7774,9 @@ static int storage_server_delete_file(struct fast_task_info *pTask) src_store_path_index = -1; for (i=0; i base_path_len && \ - memcmp(src_filename, g_fdfs_store_paths.paths\ - [i], base_path_len) == 0) + if (src_filename_len > g_fdfs_store_paths.paths[i].path_len && + memcmp(src_filename, g_fdfs_store_paths.paths + [i].path, g_fdfs_store_paths.paths[i].path_len) == 0) { src_store_path_index = i; break; @@ -7396,8 +7792,9 @@ static int storage_server_delete_file(struct fast_task_info *pTask) } } - src_true_filename = src_filename + (base_path_len + \ - (sizeof("/data/") -1)); + src_true_filename = src_filename + (g_fdfs_store_paths. + paths[src_store_path_index].path_len + + (sizeof("/data/") -1)); snprintf(src_fname2log, sizeof(src_fname2log), \ "%c"FDFS_STORAGE_DATA_DIR_FORMAT"/%s", \ FDFS_STORAGE_STORE_PATH_PREFIX_CHAR, \ @@ -7538,7 +7935,7 @@ static int storage_create_link_core(struct fast_task_info *pTask, \ } snprintf(full_filename, sizeof(full_filename), \ - "%s/data/%s", g_fdfs_store_paths.paths[store_path_index], \ + "%s/data/%s", g_fdfs_store_paths.paths[store_path_index].path, \ filename); if (fileExists(full_filename)) { @@ -8002,8 +8399,8 @@ int storage_deal_task(struct fast_task_info *pTask) case STORAGE_PROTO_CMD_QUERY_FILE_INFO: ACCESS_LOG_INIT_FIELDS(); result = storage_server_query_file_info(pTask); - STORAGE_ACCESS_LOG(pTask, \ - ACCESS_LOG_ACTION_QUERY_FILE, \ + STORAGE_ACCESS_LOG(pTask, + ACCESS_LOG_ACTION_QUERY_FILE, result); break; case STORAGE_PROTO_CMD_CREATE_LINK: @@ -8027,6 +8424,9 @@ int storage_deal_task(struct fast_task_info *pTask) case STORAGE_PROTO_CMD_SYNC_TRUNCATE_FILE: result = storage_sync_truncate_file(pTask); break; + case STORAGE_PROTO_CMD_SYNC_RENAME_FILE: + result = storage_sync_rename_file(pTask); + break; case STORAGE_PROTO_CMD_SYNC_CREATE_LINK: result = storage_sync_link_file(pTask); break; @@ -8034,7 +8434,7 @@ int storage_deal_task(struct fast_task_info *pTask) result = storage_server_fetch_one_path_binlog(pTask); break; case FDFS_PROTO_CMD_QUIT: - add_to_deleted_list(pTask); + ioevent_add_to_deleted_list(pTask); return 0; case FDFS_PROTO_CMD_ACTIVE_TEST: result = storage_deal_active_test(pTask); @@ -8063,6 +8463,13 @@ int storage_deal_task(struct fast_task_info *pTask) case STORAGE_PROTO_CMD_TRUNK_TRUNCATE_BINLOG_FILE: result = storage_server_trunk_truncate_binlog_file(pTask); break; + case STORAGE_PROTO_CMD_REGENERATE_APPENDER_FILENAME: + ACCESS_LOG_INIT_FIELDS(); + result = storage_server_regenerate_appender_filename(pTask); + STORAGE_ACCESS_LOG(pTask, + ACCESS_LOG_ACTION_RENAME_FILE, + result); + break; default: logError("file: "__FILE__", line: %d, " \ "client ip: %s, unkown cmd: %d", \ diff --git a/storage/storage_service.h b/storage/storage_service.h index fb896b0..f24a2d2 100644 --- a/storage/storage_service.h +++ b/storage/storage_service.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //storage_service.h @@ -36,7 +36,7 @@ void storage_service_destroy(); int fdfs_stat_file_sync_func(void *args); int storage_deal_task(struct fast_task_info *pTask); -void storage_nio_notify(struct fast_task_info *pTask); +int storage_nio_notify(struct fast_task_info *pTask); void storage_accept_loop(int server_sock); int storage_terminate_threads(); diff --git a/storage/storage_sync.c b/storage/storage_sync.c index 20e1633..6aaf6e0 100644 --- a/storage/storage_sync.c +++ b/storage/storage_sync.c @@ -2,7 +2,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //storage_sync.c @@ -40,7 +40,8 @@ #define SYNC_BINLOG_FILE_MAX_SIZE 1024 * 1024 * 1024 #define SYNC_BINLOG_FILE_PREFIX "binlog" -#define SYNC_BINLOG_INDEX_FILENAME SYNC_BINLOG_FILE_PREFIX".index" +#define SYNC_BINLOG_INDEX_FILENAME_OLD SYNC_BINLOG_FILE_PREFIX".index" +#define SYNC_BINLOG_INDEX_FILENAME SYNC_BINLOG_FILE_PREFIX"_index.dat" #define SYNC_MARK_FILE_EXT ".mark" #define SYNC_BINLOG_FILE_EXT_FMT ".%03d" #define SYNC_DIR_NAME "sync" @@ -53,9 +54,13 @@ #define MARK_ITEM_SYNC_ROW_COUNT "sync_row_count" #define SYNC_BINLOG_WRITE_BUFF_SIZE (16 * 1024) +#define BINLOG_INDEX_ITEM_CURRENT_WRITE "current_write" +#define BINLOG_INDEX_ITEM_CURRENT_COMPRESS "current_compress" + int g_binlog_fd = -1; int g_binlog_index = 0; static int64_t binlog_file_size = 0; +static int binlog_compress_index = 0; int g_storage_sync_thread_count = 0; static pthread_mutex_t sync_thread_lock; @@ -66,6 +71,8 @@ static int binlog_write_version = 1; /* save sync thread ids */ static pthread_t *sync_tids = NULL; +static struct fc_list_head reader_head; + static int storage_write_to_mark_file(StorageBinLogReader *pReader); static int storage_binlog_reader_skip(StorageBinLogReader *pReader); static int storage_binlog_fsync(const bool bNeedLock); @@ -98,8 +105,8 @@ static int storage_sync_copy_file(ConnectionInfo *pStorageServer, \ int result; bool need_sync_file; - if ((result=trunk_file_stat(pRecord->store_path_index, \ - pRecord->true_filename, pRecord->true_filename_len, \ + if ((result=trunk_file_stat(pRecord->store_path_index, + pRecord->true_filename, pRecord->true_filename_len, &stat_buf, &trunkInfo, &trunkHeader)) != 0) { if (result == ENOENT) @@ -131,7 +138,7 @@ static int storage_sync_copy_file(ConnectionInfo *pStorageServer, \ { FDFSFileInfo file_info; result = storage_query_file_info_ex(NULL, \ - pStorageServer, g_group_name, \ + pStorageServer, g_group_name, \ pRecord->filename, &file_info, true); if (result == 0) { @@ -178,7 +185,7 @@ static int storage_sync_copy_file(ConnectionInfo *pStorageServer, \ { file_offset = 0; sprintf(full_filename, "%s/data/%s", \ - g_fdfs_store_paths.paths[pRecord->store_path_index], \ + g_fdfs_store_paths.paths[pRecord->store_path_index].path, \ pRecord->true_filename); } @@ -305,11 +312,11 @@ static int storage_sync_modify_file(ConnectionInfo *pStorageServer, \ StorageBinLogReader *pReader, StorageBinLogRecord *pRecord, \ const char cmd) { -#define FIELD_COUNT 3 +#define SYNC_MODIFY_FIELD_COUNT 3 TrackerHeader *pHeader; char *p; char *pBuff; - char *fields[FIELD_COUNT]; + char *fields[SYNC_MODIFY_FIELD_COUNT]; char full_filename[MAX_PATH_SIZE]; char out_buff[sizeof(TrackerHeader)+FDFS_GROUP_NAME_MAX_LEN+256]; char in_buff[1]; @@ -321,8 +328,8 @@ static int storage_sync_modify_file(ConnectionInfo *pStorageServer, \ int result; int count; - if ((count=splitEx(pRecord->filename, ' ', fields, FIELD_COUNT)) \ - != FIELD_COUNT) + if ((count=splitEx(pRecord->filename, ' ', fields, SYNC_MODIFY_FIELD_COUNT)) + != SYNC_MODIFY_FIELD_COUNT) { logError("file: "__FILE__", line: %d, " \ "the format of binlog not correct, filename: %s", \ @@ -343,7 +350,7 @@ static int storage_sync_modify_file(ConnectionInfo *pStorageServer, \ } snprintf(full_filename, sizeof(full_filename), \ - "%s/data/%s", g_fdfs_store_paths.paths[pRecord->store_path_index], \ + "%s/data/%s", g_fdfs_store_paths.paths[pRecord->store_path_index].path, \ pRecord->true_filename); if (lstat(full_filename, &stat_buf) != 0) { @@ -476,11 +483,11 @@ filename bytes : filename static int storage_sync_truncate_file(ConnectionInfo *pStorageServer, \ StorageBinLogReader *pReader, StorageBinLogRecord *pRecord) { -#define FIELD_COUNT 3 +#define SYNC_TRUNCATE_FIELD_COUNT 3 TrackerHeader *pHeader; char *p; char *pBuff; - char *fields[FIELD_COUNT]; + char *fields[SYNC_TRUNCATE_FIELD_COUNT]; char full_filename[MAX_PATH_SIZE]; char out_buff[sizeof(TrackerHeader)+FDFS_GROUP_NAME_MAX_LEN+256]; char in_buff[1]; @@ -491,8 +498,8 @@ static int storage_sync_truncate_file(ConnectionInfo *pStorageServer, \ int result; int count; - if ((count=splitEx(pRecord->filename, ' ', fields, FIELD_COUNT)) \ - != FIELD_COUNT) + if ((count=splitEx(pRecord->filename, ' ', fields, + SYNC_TRUNCATE_FIELD_COUNT)) != SYNC_TRUNCATE_FIELD_COUNT) { logError("file: "__FILE__", line: %d, " \ "the format of binlog not correct, filename: %s", \ @@ -513,7 +520,7 @@ static int storage_sync_truncate_file(ConnectionInfo *pStorageServer, \ } snprintf(full_filename, sizeof(full_filename), \ - "%s/data/%s", g_fdfs_store_paths.paths[pRecord->store_path_index], \ + "%s/data/%s", g_fdfs_store_paths.paths[pRecord->store_path_index].path, \ pRecord->true_filename); if (lstat(full_filename, &stat_buf) != 0) { @@ -834,7 +841,7 @@ static int storage_sync_link_file(ConnectionInfo *pStorageServer, \ int src_filename_len; snprintf(full_filename, sizeof(full_filename), \ - "%s/data/%s", g_fdfs_store_paths.paths[pRecord->store_path_index], \ + "%s/data/%s", g_fdfs_store_paths.paths[pRecord->store_path_index].path, \ pRecord->true_filename); src_filename_len = readlink(full_filename, src_full_filename, \ sizeof(src_full_filename) - 1); @@ -877,7 +884,7 @@ static int storage_sync_link_file(ConnectionInfo *pStorageServer, \ src_path_index++) { if (strcmp(src_full_filename, \ - g_fdfs_store_paths.paths[src_path_index]) == 0) + g_fdfs_store_paths.paths[src_path_index].path) == 0) { break; } @@ -961,6 +968,123 @@ static int storage_sync_link_file(ConnectionInfo *pStorageServer, \ return result; } +/** +8 bytes: dest filename length +8 bytes: source filename length +4 bytes: source op timestamp +FDFS_GROUP_NAME_MAX_LEN bytes: group_name +dest filename length: dest filename +source filename length: source filename +**/ +static int storage_sync_rename_file(ConnectionInfo *pStorageServer, + StorageBinLogReader *pReader, StorageBinLogRecord *pRecord) +{ + TrackerHeader *pHeader; + int result; + char out_buff[sizeof(TrackerHeader) + 2 * FDFS_PROTO_PKG_LEN_SIZE + + 4 + FDFS_GROUP_NAME_MAX_LEN + 256]; + char in_buff[1]; + int out_body_len; + int64_t in_bytes; + char *pBuff; + char full_filename[MAX_PATH_SIZE]; + struct stat stat_buf; + + if (pRecord->op_type == STORAGE_OP_TYPE_REPLICA_RENAME_FILE) + { + return storage_sync_copy_file(pStorageServer, + pReader, pRecord, + STORAGE_PROTO_CMD_SYNC_CREATE_FILE); + } + + snprintf(full_filename, sizeof(full_filename), "%s/data/%s", + g_fdfs_store_paths.paths[pRecord->store_path_index].path, + pRecord->true_filename); + if (lstat(full_filename, &stat_buf) != 0) + { + if (errno == ENOENT) + { + logWarning("file: "__FILE__", line: %d, " + "sync file rename, file: %s not exists, " + "maybe deleted later?", __LINE__, full_filename); + + return 0; + } + else + { + result = errno != 0 ? errno : EPERM; + logError("file: "__FILE__", line: %d, " + "call stat fail, file: %s, " + "error no: %d, error info: %s", + __LINE__, full_filename, + result, STRERROR(result)); + return result; + } + } + + pHeader = (TrackerHeader *)out_buff; + memset(out_buff, 0, sizeof(out_buff)); + long2buff(pRecord->filename_len, out_buff + sizeof(TrackerHeader)); + long2buff(pRecord->src_filename_len, out_buff + sizeof(TrackerHeader) + + FDFS_PROTO_PKG_LEN_SIZE); + int2buff(pRecord->timestamp, out_buff + sizeof(TrackerHeader) + + 2 * FDFS_PROTO_PKG_LEN_SIZE); + sprintf(out_buff + sizeof(TrackerHeader) + 2 * FDFS_PROTO_PKG_LEN_SIZE + + 4, "%s", g_group_name); + memcpy(out_buff + sizeof(TrackerHeader) + 2 * FDFS_PROTO_PKG_LEN_SIZE + + 4 + FDFS_GROUP_NAME_MAX_LEN, + pRecord->filename, pRecord->filename_len); + memcpy(out_buff + sizeof(TrackerHeader) + 2 * FDFS_PROTO_PKG_LEN_SIZE + + 4 + FDFS_GROUP_NAME_MAX_LEN + pRecord->filename_len, + pRecord->src_filename, pRecord->src_filename_len); + + out_body_len = 2 * FDFS_PROTO_PKG_LEN_SIZE + 4 + + FDFS_GROUP_NAME_MAX_LEN + pRecord->filename_len + + pRecord->src_filename_len; + long2buff(out_body_len, pHeader->pkg_len); + pHeader->cmd = STORAGE_PROTO_CMD_SYNC_RENAME_FILE; + + if ((result=tcpsenddata_nb(pStorageServer->sock, out_buff, + sizeof(TrackerHeader) + out_body_len, + g_fdfs_network_timeout)) != 0) + { + logError("FILE: "__FILE__", line: %d, " + "send data to storage server %s:%d fail, " + "errno: %d, error info: %s", + __LINE__, pStorageServer->ip_addr, + pStorageServer->port, result, STRERROR(result)); + return result; + } + + pBuff = in_buff; + result = fdfs_recv_response(pStorageServer, &pBuff, 0, &in_bytes); + if (result != 0) + { + if (result == ENOENT) + { + return storage_sync_copy_file(pStorageServer, + pReader, pRecord, + STORAGE_PROTO_CMD_SYNC_CREATE_FILE); + } + else if (result == EEXIST) + { + logDebug("file: "__FILE__", line: %d, " + "storage server ip: %s:%d, data file: %s " + "already exists", __LINE__, pStorageServer->ip_addr, + pStorageServer->port, pRecord->filename); + return 0; + } + else + { + logError("file: "__FILE__", line: %d, " + "fdfs_recv_response fail, result: %d", + __LINE__, result); + } + } + + return result; +} + #define STARAGE_CHECK_IF_NEED_SYNC_OLD(pReader, pRecord) \ if ((!pReader->need_sync_old) || pReader->sync_old_done || \ (pRecord->timestamp > pReader->until_timestamp)) \ @@ -1015,6 +1139,10 @@ static int storage_sync_data(StorageBinLogReader *pReader, \ result = storage_sync_truncate_file(pStorageServer, \ pReader, pRecord); break; + case STORAGE_OP_TYPE_SOURCE_RENAME_FILE: + result = storage_sync_rename_file(pStorageServer, + pReader, pRecord); + break; case STORAGE_OP_TYPE_SOURCE_CREATE_LINK: result = storage_sync_link_file(pStorageServer, \ pRecord); @@ -1041,6 +1169,11 @@ static int storage_sync_data(StorageBinLogReader *pReader, \ result = storage_sync_link_file(pStorageServer, \ pRecord); break; + case STORAGE_OP_TYPE_REPLICA_RENAME_FILE: + STARAGE_CHECK_IF_NEED_SYNC_OLD(pReader, pRecord) + result = storage_sync_rename_file(pStorageServer, + pReader, pRecord); + break; case STORAGE_OP_TYPE_REPLICA_APPEND_FILE: return 0; case STORAGE_OP_TYPE_REPLICA_MODIFY_FILE: @@ -1078,30 +1211,33 @@ static int storage_sync_data(StorageBinLogReader *pReader, \ static int write_to_binlog_index(const int binlog_index) { char full_filename[MAX_PATH_SIZE]; - char buff[16]; + char buff[256]; int fd; int len; - snprintf(full_filename, sizeof(full_filename), \ - "%s/data/"SYNC_DIR_NAME"/%s", g_fdfs_base_path, \ + snprintf(full_filename, sizeof(full_filename), + "%s/data/"SYNC_DIR_NAME"/%s", g_fdfs_base_path, SYNC_BINLOG_INDEX_FILENAME); if ((fd=open(full_filename, O_WRONLY | O_CREAT | O_TRUNC, 0644)) < 0) { - logError("file: "__FILE__", line: %d, " \ - "open file \"%s\" fail, " \ - "errno: %d, error info: %s", \ - __LINE__, full_filename, \ + logError("file: "__FILE__", line: %d, " + "open file \"%s\" fail, " + "errno: %d, error info: %s", + __LINE__, full_filename, errno, STRERROR(errno)); return errno != 0 ? errno : ENOENT; } - len = sprintf(buff, "%d", binlog_index); + len = sprintf(buff, "%s=%d\n" + "%s=%d\n", + BINLOG_INDEX_ITEM_CURRENT_WRITE, binlog_index, + BINLOG_INDEX_ITEM_CURRENT_COMPRESS, binlog_compress_index); if (fc_safe_write(fd, buff, len) != len) { - logError("file: "__FILE__", line: %d, " \ - "write to file \"%s\" fail, " \ - "errno: %d, error info: %s", \ - __LINE__, full_filename, \ + logError("file: "__FILE__", line: %d, " + "write to file \"%s\" fail, " + "errno: %d, error info: %s", + __LINE__, full_filename, errno, STRERROR(errno)); close(fd); return errno != 0 ? errno : EIO; @@ -1114,6 +1250,92 @@ static int write_to_binlog_index(const int binlog_index) return 0; } +static int get_binlog_index_from_file_old() +{ + char full_filename[MAX_PATH_SIZE]; + char file_buff[64]; + int fd; + int bytes; + + snprintf(full_filename, sizeof(full_filename), + "%s/data/"SYNC_DIR_NAME"/%s", g_fdfs_base_path, + SYNC_BINLOG_INDEX_FILENAME_OLD); + if ((fd=open(full_filename, O_RDONLY)) >= 0) + { + bytes = fc_safe_read(fd, file_buff, sizeof(file_buff) - 1); + close(fd); + if (bytes <= 0) + { + logError("file: "__FILE__", line: %d, " \ + "read file \"%s\" fail, bytes read: %d", \ + __LINE__, full_filename, bytes); + return errno != 0 ? errno : EIO; + } + + file_buff[bytes] = '\0'; + g_binlog_index = atoi(file_buff); + if (g_binlog_index < 0) + { + logError("file: "__FILE__", line: %d, " \ + "in file \"%s\", binlog_index: %d < 0", \ + __LINE__, full_filename, g_binlog_index); + return EINVAL; + } + } + else + { + g_binlog_index = 0; + } + + return 0; +} + +static int get_binlog_index_from_file() +{ + char full_filename[MAX_PATH_SIZE]; + IniContext iniContext; + int result; + + snprintf(full_filename, sizeof(full_filename), + "%s/data/"SYNC_DIR_NAME"/%s", g_fdfs_base_path, + SYNC_BINLOG_INDEX_FILENAME); + if (access(full_filename, F_OK) != 0) + { + if (errno == ENOENT) + { + if ((result=get_binlog_index_from_file_old()) == 0) + { + if ((result=write_to_binlog_index(g_binlog_index)) != 0) + { + return result; + } + } + + return result; + } + } + + memset(&iniContext, 0, sizeof(IniContext)); + if ((result=iniLoadFromFile(full_filename, &iniContext)) != 0) + { + logError("file: "__FILE__", line: %d, " + "load from file \"%s\" fail, " + "error code: %d", + __LINE__, full_filename, result); + return result; + } + + g_binlog_index = iniGetIntValue(NULL, + BINLOG_INDEX_ITEM_CURRENT_WRITE, + &iniContext, 0); + binlog_compress_index = iniGetIntValue(NULL, + BINLOG_INDEX_ITEM_CURRENT_COMPRESS, + &iniContext, 0); + + iniFreeContext(&iniContext); + return 0; +} + static char *get_writable_binlog_filename(char *full_filename) { static char buff[MAX_PATH_SIZE]; @@ -1189,10 +1411,7 @@ int storage_sync_init() char data_path[MAX_PATH_SIZE]; char sync_path[MAX_PATH_SIZE]; char full_filename[MAX_PATH_SIZE]; - char file_buff[64]; - int bytes; int result; - int fd; snprintf(data_path, sizeof(data_path), "%s/data", g_fdfs_base_path); if (!fileExists(data_path)) @@ -1238,38 +1457,10 @@ int storage_sync_init() return errno != 0 ? errno : ENOMEM; } - snprintf(full_filename, sizeof(full_filename), \ - "%s/%s", sync_path, SYNC_BINLOG_INDEX_FILENAME); - if ((fd=open(full_filename, O_RDONLY)) >= 0) - { - bytes = fc_safe_read(fd, file_buff, sizeof(file_buff) - 1); - close(fd); - if (bytes <= 0) - { - logError("file: "__FILE__", line: %d, " \ - "read file \"%s\" fail, bytes read: %d", \ - __LINE__, full_filename, bytes); - return errno != 0 ? errno : EIO; - } - - file_buff[bytes] = '\0'; - g_binlog_index = atoi(file_buff); - if (g_binlog_index < 0) - { - logError("file: "__FILE__", line: %d, " \ - "in file \"%s\", binlog_index: %d < 0", \ - __LINE__, full_filename, g_binlog_index); - return EINVAL; - } - } - else - { - g_binlog_index = 0; - if ((result=write_to_binlog_index(g_binlog_index)) != 0) - { - return result; - } - } + if ((result=get_binlog_index_from_file()) != 0) + { + return result; + } get_writable_binlog_filename(full_filename); g_binlog_fd = open(full_filename, O_WRONLY | O_CREAT | O_APPEND, 0644); @@ -1309,6 +1500,8 @@ int storage_sync_init() load_local_host_ip_addrs(); + FC_INIT_LIST_HEAD(&reader_head); + return 0; } @@ -1514,25 +1707,198 @@ int storage_binlog_write_ex(const int timestamp, const char op_type, \ return write_ret; } -static char *get_binlog_readable_filename(const void *pArg, \ - char *full_filename) +static char *get_binlog_readable_filename_ex( + const int binlog_index, char *full_filename) { - const StorageBinLogReader *pReader; static char buff[MAX_PATH_SIZE]; - pReader = (const StorageBinLogReader *)pArg; if (full_filename == NULL) { full_filename = buff; } - snprintf(full_filename, MAX_PATH_SIZE, \ - "%s/data/"SYNC_DIR_NAME"/"SYNC_BINLOG_FILE_PREFIX"" \ - SYNC_BINLOG_FILE_EXT_FMT, \ - g_fdfs_base_path, pReader->binlog_index); + snprintf(full_filename, MAX_PATH_SIZE, + "%s/data/"SYNC_DIR_NAME"/"SYNC_BINLOG_FILE_PREFIX"" + SYNC_BINLOG_FILE_EXT_FMT, + g_fdfs_base_path, binlog_index); return full_filename; } +static inline char *get_binlog_readable_filename(const void *pArg, + char *full_filename) +{ + return get_binlog_readable_filename_ex( + ((const StorageBinLogReader *)pArg)->binlog_index, + full_filename); +} + +static void get_binlog_flag_file(const char *filepath, + char *flag_filename, const int size) +{ + const char *filename; + + filename = strrchr(filepath, '/'); + if (filename == NULL) + { + snprintf(flag_filename, size, ".%s.flag", filepath); + } + else + { + snprintf(flag_filename, size, "%.*s.%s.flag", + (int)(filename - filepath + 1), filepath, filename + 1); + } +} + +static int uncompress_binlog_file(StorageBinLogReader *pReader, + const char *filename) +{ + char gzip_filename[MAX_PATH_SIZE]; + char flag_filename[MAX_PATH_SIZE]; + char command[MAX_PATH_SIZE]; + char output[256]; + struct stat flag_stat; + int result; + + snprintf(gzip_filename, sizeof(gzip_filename), + "%s.gz", filename); + if (access(gzip_filename, F_OK) != 0) + { + return errno != 0 ? errno : ENOENT; + } + + get_binlog_flag_file(filename, flag_filename, sizeof(flag_filename)); + if (stat(flag_filename, &flag_stat) == 0) + { + if (g_current_time - flag_stat.st_mtime > 3600) + { + logInfo("file: "__FILE__", line: %d, " + "flag file %s expired, continue to uncompress", + __LINE__, flag_filename); + } + else + { + logWarning("file: "__FILE__", line: %d, " + "uncompress %s already in progress", + __LINE__, gzip_filename); + return EINPROGRESS; + } + } + + if ((result=writeToFile(flag_filename, "unzip", 5)) != 0) + { + return result; + } + + logInfo("file: "__FILE__", line: %d, " + "try to uncompress binlog %s", + __LINE__, gzip_filename); + snprintf(command, sizeof(command), "%s -d %s 2>&1", + get_gzip_command_filename(), gzip_filename); + result = getExecResult(command, output, sizeof(output)); + unlink(flag_filename); + if (result != 0) + { + logError("file: "__FILE__", line: %d, " + "exec command \"%s\" fail, " + "errno: %d, error info: %s", + __LINE__, command, result, STRERROR(result)); + return result; + } + if (*output != '\0') + { + logWarning("file: "__FILE__", line: %d, " + "exec command \"%s\", output: %s", + __LINE__, command, output); + } + + if (access(filename, F_OK) == 0) + { + if (pReader->binlog_index < binlog_compress_index) + { + binlog_compress_index = pReader->binlog_index; + write_to_binlog_index(g_binlog_index); + } + } + + logInfo("file: "__FILE__", line: %d, " + "uncompress binlog %s done", + __LINE__, gzip_filename); + return 0; +} + +static int compress_binlog_file(const char *filename) +{ + char gzip_filename[MAX_PATH_SIZE]; + char flag_filename[MAX_PATH_SIZE]; + char command[MAX_PATH_SIZE]; + char output[256]; + struct stat flag_stat; + int result; + + snprintf(gzip_filename, sizeof(gzip_filename), + "%s.gz", filename); + if (access(gzip_filename, F_OK) == 0) + { + return 0; + } + + if (access(filename, F_OK) != 0) + { + return errno != 0 ? errno : ENOENT; + } + + get_binlog_flag_file(filename, flag_filename, sizeof(flag_filename)); + if (stat(flag_filename, &flag_stat) == 0) + { + if (g_current_time - flag_stat.st_mtime > 3600) + { + logInfo("file: "__FILE__", line: %d, " + "flag file %s expired, continue to compress", + __LINE__, flag_filename); + } + else + { + logWarning("file: "__FILE__", line: %d, " + "compress %s already in progress", + __LINE__, filename); + return EINPROGRESS; + } + } + + if ((result=writeToFile(flag_filename, "zip", 3)) != 0) + { + return result; + } + + logInfo("file: "__FILE__", line: %d, " + "try to compress binlog %s", + __LINE__, filename); + + snprintf(command, sizeof(command), "%s %s 2>&1", + get_gzip_command_filename(), filename); + result = getExecResult(command, output, sizeof(output)); + unlink(flag_filename); + if (result != 0) + { + logError("file: "__FILE__", line: %d, " + "exec command \"%s\" fail, " + "errno: %d, error info: %s", + __LINE__, command, result, STRERROR(result)); + return result; + } + if (*output != '\0') + { + logWarning("file: "__FILE__", line: %d, " + "exec command \"%s\", output: %s", + __LINE__, command, output); + } + + logInfo("file: "__FILE__", line: %d, " + "compress binlog %s done", + __LINE__, filename); + return 0; +} + int storage_open_readable_binlog(StorageBinLogReader *pReader, \ get_filename_func filename_func, const void *pArg) { @@ -1544,6 +1910,14 @@ int storage_open_readable_binlog(StorageBinLogReader *pReader, \ } filename_func(pArg, full_filename); + if (access(full_filename, F_OK) != 0) + { + if (errno == ENOENT) + { + uncompress_binlog_file(pReader, full_filename); + } + } + pReader->binlog_fd = open(full_filename, O_RDONLY); if (pReader->binlog_fd < 0) { @@ -1572,53 +1946,45 @@ int storage_open_readable_binlog(StorageBinLogReader *pReader, \ return 0; } -static char *get_mark_filename_by_id_and_port(const char *storage_id, \ +static char *get_mark_filename_by_id_and_port(const char *storage_id, const int port, char *full_filename, const int filename_size) { if (g_use_storage_id) { - snprintf(full_filename, filename_size, \ - "%s/data/"SYNC_DIR_NAME"/%s%s", g_fdfs_base_path, \ + snprintf(full_filename, filename_size, + "%s/data/"SYNC_DIR_NAME"/%s%s", g_fdfs_base_path, storage_id, SYNC_MARK_FILE_EXT); } else { - snprintf(full_filename, filename_size, \ - "%s/data/"SYNC_DIR_NAME"/%s_%d%s", g_fdfs_base_path, \ + snprintf(full_filename, filename_size, + "%s/data/"SYNC_DIR_NAME"/%s_%d%s", g_fdfs_base_path, storage_id, port, SYNC_MARK_FILE_EXT); } return full_filename; } -static char *get_mark_filename_by_ip_and_port(const char *ip_addr, \ +static char *get_mark_filename_by_ip_and_port(const char *ip_addr, const int port, char *full_filename, const int filename_size) { - snprintf(full_filename, filename_size, \ - "%s/data/"SYNC_DIR_NAME"/%s_%d%s", g_fdfs_base_path, \ + snprintf(full_filename, filename_size, + "%s/data/"SYNC_DIR_NAME"/%s_%d%s", g_fdfs_base_path, ip_addr, port, SYNC_MARK_FILE_EXT); return full_filename; } -char *get_mark_filename_by_reader(const void *pArg, char *full_filename) +char *get_mark_filename_by_reader(StorageBinLogReader *pReader) { - const StorageBinLogReader *pReader; - static char buff[MAX_PATH_SIZE]; - - pReader = (const StorageBinLogReader *)pArg; - if (full_filename == NULL) - { - full_filename = buff; - } - - return get_mark_filename_by_id_and_port(pReader->storage_id, \ - g_server_port, full_filename, MAX_PATH_SIZE); + return get_mark_filename_by_id_and_port(pReader->storage_id, + g_server_port, pReader->mark_filename, + sizeof(pReader->mark_filename)); } -static char *get_mark_filename_by_id(const char *storage_id, \ +static char *get_mark_filename_by_id(const char *storage_id, char *full_filename, const int filename_size) { - return get_mark_filename_by_id_and_port(storage_id, g_server_port, \ - full_filename, filename_size); + return get_mark_filename_by_id_and_port(storage_id, + g_server_port, full_filename, filename_size); } int storage_report_storage_status(const char *storage_id, \ @@ -1774,6 +2140,7 @@ static int storage_reader_sync_init_req(StorageBinLogReader *pReader) } do { + conn = NULL; while (g_continue_flag) { conn = tracker_connect_server_no_pool_ex(pTServer, @@ -1826,24 +2193,22 @@ static int storage_reader_sync_init_req(StorageBinLogReader *pReader) int storage_reader_init(FDFSStorageBrief *pStorage, StorageBinLogReader *pReader) { - char full_filename[MAX_PATH_SIZE]; IniContext iniContext; int result; bool bFileExist; bool bNeedSyncOld; - memset(pReader, 0, sizeof(StorageBinLogReader)); - pReader->mark_fd = -1; - pReader->binlog_fd = -1; + memset(pReader, 0, sizeof(StorageBinLogReader)); + pReader->binlog_fd = -1; - pReader->binlog_buff.buffer = (char *)malloc( \ + pReader->binlog_buff.buffer = (char *)malloc( STORAGE_BINLOG_BUFFER_SIZE); if (pReader->binlog_buff.buffer == NULL) { - logError("file: "__FILE__", line: %d, " \ - "malloc %d bytes fail, " \ - "errno: %d, error info: %s", \ - __LINE__, STORAGE_BINLOG_BUFFER_SIZE, \ + logError("file: "__FILE__", line: %d, " + "malloc %d bytes fail, " + "errno: %d, error info: %s", + __LINE__, STORAGE_BINLOG_BUFFER_SIZE, errno, STRERROR(errno)); return errno != 0 ? errno : ENOMEM; } @@ -1857,7 +2222,7 @@ int storage_reader_init(FDFSStorageBrief *pStorage, StorageBinLogReader *pReader { strcpy(pReader->storage_id, pStorage->id); } - get_mark_filename_by_reader(pReader, full_filename); + get_mark_filename_by_reader(pReader); if (pStorage == NULL) { @@ -1869,22 +2234,23 @@ int storage_reader_init(FDFSStorageBrief *pStorage, StorageBinLogReader *pReader } else { - bFileExist = fileExists(full_filename); + bFileExist = fileExists(pReader->mark_filename); if (!bFileExist && (g_use_storage_id && pStorage != NULL)) { char old_mark_filename[MAX_PATH_SIZE]; - get_mark_filename_by_ip_and_port(pStorage->ip_addr, \ - g_server_port, old_mark_filename, \ + get_mark_filename_by_ip_and_port(pStorage->ip_addr, + g_server_port, old_mark_filename, sizeof(old_mark_filename)); if (fileExists(old_mark_filename)) { - if (rename(old_mark_filename, full_filename)!=0) + if (rename(old_mark_filename, + pReader->mark_filename) !=0 ) { - logError("file: "__FILE__", line: %d, "\ - "rename file %s to %s fail" \ - ", errno: %d, error info: %s", \ - __LINE__, old_mark_filename, \ - full_filename, errno, \ + logError("file: "__FILE__", line: %d, " + "rename file %s to %s fail" + ", errno: %d, error info: %s", + __LINE__, old_mark_filename, + pReader->mark_filename, errno, STRERROR(errno)); return errno != 0 ? errno : EACCES; } @@ -1904,29 +2270,30 @@ int storage_reader_init(FDFSStorageBrief *pStorage, StorageBinLogReader *pReader if (bFileExist) { memset(&iniContext, 0, sizeof(IniContext)); - if ((result=iniLoadFromFile(full_filename, &iniContext)) \ - != 0) + if ((result=iniLoadFromFile(pReader->mark_filename, + &iniContext)) != 0) { - logError("file: "__FILE__", line: %d, " \ - "load from mark file \"%s\" fail, " \ - "error code: %d", \ - __LINE__, full_filename, result); + logError("file: "__FILE__", line: %d, " + "load from mark file \"%s\" fail, " + "error code: %d", __LINE__, + pReader->mark_filename, result); return result; } if (iniContext.global.count < 7) { iniFreeContext(&iniContext); - logError("file: "__FILE__", line: %d, " \ - "in mark file \"%s\", item count: %d < 7", \ - __LINE__, full_filename, iniContext.global.count); + logError("file: "__FILE__", line: %d, " + "in mark file \"%s\", item count: %d < 7", + __LINE__, pReader->mark_filename, + iniContext.global.count); return ENOENT; } - bNeedSyncOld = iniGetBoolValue(NULL, \ - MARK_ITEM_NEED_SYNC_OLD, \ + bNeedSyncOld = iniGetBoolValue(NULL, + MARK_ITEM_NEED_SYNC_OLD, &iniContext, false); - if (pStorage != NULL && pStorage->status == \ + if (pStorage != NULL && pStorage->status == FDFS_STORAGE_STATUS_SYNCING) { if ((result=storage_reader_sync_init_req(pReader)) != 0) @@ -1976,17 +2343,17 @@ int storage_reader_init(FDFSStorageBrief *pStorage, StorageBinLogReader *pReader logError("file: "__FILE__", line: %d, " \ "in mark file \"%s\", " \ "binlog_index: %d < 0", \ - __LINE__, full_filename, \ + __LINE__, pReader->mark_filename, \ pReader->binlog_index); return EINVAL; } if (pReader->binlog_offset < 0) { iniFreeContext(&iniContext); - logError("file: "__FILE__", line: %d, " \ - "in mark file \"%s\", binlog_offset: "\ - "%"PRId64" < 0", \ - __LINE__, full_filename, \ + logError("file: "__FILE__", line: %d, " + "in mark file \"%s\", binlog_offset: " + "%"PRId64" < 0", __LINE__, + pReader->mark_filename, pReader->binlog_offset); return EINVAL; } @@ -1998,19 +2365,7 @@ int storage_reader_init(FDFSStorageBrief *pStorage, StorageBinLogReader *pReader pReader->last_scan_rows = pReader->scan_row_count; pReader->last_sync_rows = pReader->sync_row_count; - pReader->mark_fd = open(full_filename, O_WRONLY | O_CREAT, 0644); - if (pReader->mark_fd < 0) - { - logError("file: "__FILE__", line: %d, " \ - "open mark file \"%s\" fail, " \ - "error no: %d, error info: %s", \ - __LINE__, full_filename, \ - errno, STRERROR(errno)); - return errno != 0 ? errno : ENOENT; - } - STORAGE_FCHOWN(pReader->mark_fd, full_filename, geteuid(), getegid()) - - if ((result=storage_open_readable_binlog(pReader, \ + if ((result=storage_open_readable_binlog(pReader, get_binlog_readable_filename, pReader)) != 0) { return result; @@ -2043,12 +2398,6 @@ int storage_reader_init(FDFSStorageBrief *pStorage, StorageBinLogReader *pReader void storage_reader_destroy(StorageBinLogReader *pReader) { - if (pReader->mark_fd >= 0) - { - close(pReader->mark_fd); - pReader->mark_fd = -1; - } - if (pReader->binlog_fd >= 0) { close(pReader->binlog_fd); @@ -2070,25 +2419,25 @@ static int storage_write_to_mark_file(StorageBinLogReader *pReader) int len; int result; - len = sprintf(buff, \ - "%s=%d\n" \ - "%s=%"PRId64"\n" \ - "%s=%d\n" \ - "%s=%d\n" \ - "%s=%d\n" \ - "%s=%"PRId64"\n" \ - "%s=%"PRId64"\n", \ - MARK_ITEM_BINLOG_FILE_INDEX, pReader->binlog_index, \ - MARK_ITEM_BINLOG_FILE_OFFSET, pReader->binlog_offset, \ - MARK_ITEM_NEED_SYNC_OLD, pReader->need_sync_old, \ - MARK_ITEM_SYNC_OLD_DONE, pReader->sync_old_done, \ - MARK_ITEM_UNTIL_TIMESTAMP, (int)pReader->until_timestamp, \ - MARK_ITEM_SCAN_ROW_COUNT, pReader->scan_row_count, \ + len = sprintf(buff, + "%s=%d\n" + "%s=%"PRId64"\n" + "%s=%d\n" + "%s=%d\n" + "%s=%d\n" + "%s=%"PRId64"\n" + "%s=%"PRId64"\n", + MARK_ITEM_BINLOG_FILE_INDEX, pReader->binlog_index, + MARK_ITEM_BINLOG_FILE_OFFSET, pReader->binlog_offset, + MARK_ITEM_NEED_SYNC_OLD, pReader->need_sync_old, + MARK_ITEM_SYNC_OLD_DONE, pReader->sync_old_done, + MARK_ITEM_UNTIL_TIMESTAMP, (int)pReader->until_timestamp, + MARK_ITEM_SCAN_ROW_COUNT, pReader->scan_row_count, MARK_ITEM_SYNC_ROW_COUNT, pReader->sync_row_count); - if ((result=storage_write_to_fd(pReader->mark_fd, \ - get_mark_filename_by_reader, pReader, buff, len)) == 0) + if ((result=safeWriteToFile(pReader->mark_filename, buff, len)) == 0) { + STORAGE_CHOWN(pReader->mark_filename, geteuid(), getegid()) pReader->last_scan_rows = pReader->scan_row_count; pReader->last_sync_rows = pReader->sync_row_count; } @@ -2121,7 +2470,7 @@ static int storage_binlog_preread(StorageBinLogReader *pReader) int bytes_read; int saved_binlog_write_version; - if (pReader->binlog_buff.version == binlog_write_version && \ + if (pReader->binlog_buff.version == binlog_write_version && pReader->binlog_buff.length == 0) { return ENOENT; @@ -2306,8 +2655,10 @@ int storage_binlog_read(StorageBinLogReader *pReader, \ memcpy(pRecord->filename, cols[2], pRecord->filename_len); *(pRecord->filename + pRecord->filename_len) = '\0'; - if (pRecord->op_type == STORAGE_OP_TYPE_SOURCE_CREATE_LINK || \ - pRecord->op_type == STORAGE_OP_TYPE_REPLICA_CREATE_LINK) + if (pRecord->op_type == STORAGE_OP_TYPE_SOURCE_CREATE_LINK || + pRecord->op_type == STORAGE_OP_TYPE_REPLICA_CREATE_LINK || + pRecord->op_type == STORAGE_OP_TYPE_SOURCE_RENAME_FILE || + pRecord->op_type == STORAGE_OP_TYPE_REPLICA_RENAME_FILE) { char *p; @@ -2319,14 +2670,14 @@ int storage_binlog_read(StorageBinLogReader *pReader, \ } else { - pRecord->src_filename_len = pRecord->filename_len - \ + pRecord->src_filename_len = pRecord->filename_len - (p - pRecord->filename) - 1; pRecord->filename_len = p - pRecord->filename; *p = '\0'; - memcpy(pRecord->src_filename, p + 1, \ + memcpy(pRecord->src_filename, p + 1, pRecord->src_filename_len); - *(pRecord->src_filename + \ + *(pRecord->src_filename + pRecord->src_filename_len) = '\0'; } } @@ -2337,8 +2688,8 @@ int storage_binlog_read(StorageBinLogReader *pReader, \ } pRecord->true_filename_len = pRecord->filename_len; - if ((result=storage_split_filename_ex(pRecord->filename, \ - &pRecord->true_filename_len, pRecord->true_filename, \ + if ((result=storage_split_filename_ex(pRecord->filename, + &pRecord->true_filename_len, pRecord->true_filename, &pRecord->store_path_index)) != 0) { return result; @@ -2545,7 +2896,7 @@ static void storage_sync_thread_exit(ConnectionInfo *pStorage) static void* storage_sync_thread_entrance(void* arg) { FDFSStorageBrief *pStorage; - StorageBinLogReader reader; + StorageBinLogReader *pReader; StorageBinLogRecord record; ConnectionInfo storage_server; char local_ip_addr[IP_ADDRESS_SIZE]; @@ -2558,26 +2909,38 @@ static void* storage_sync_thread_entrance(void* arg) time_t end_time; time_t last_keep_alive_time; + pStorage = (FDFSStorageBrief *)arg; + strcpy(storage_server.ip_addr, pStorage->ip_addr); + storage_server.port = g_server_port; + storage_server.sock = -1; + memset(local_ip_addr, 0, sizeof(local_ip_addr)); - memset(&reader, 0, sizeof(reader)); - reader.mark_fd = -1; - reader.binlog_fd = -1; + pReader = (StorageBinLogReader *)malloc(sizeof(StorageBinLogReader)); + if (pReader == NULL) + { + logCrit("file: "__FILE__", line: %d, " + "malloc %d bytes fail, " + "fail, program exit!", + __LINE__, (int)sizeof(StorageBinLogReader)); + g_continue_flag = false; + storage_sync_thread_exit(&storage_server); + return NULL; + } + + memset(pReader, 0, sizeof(StorageBinLogReader)); + pReader->binlog_fd = -1; + + storage_reader_add_to_list(pReader); current_time = g_current_time; last_keep_alive_time = 0; start_time = 0; end_time = 0; - pStorage = (FDFSStorageBrief *)arg; - - strcpy(storage_server.ip_addr, pStorage->ip_addr); - storage_server.port = g_server_port; - storage_server.sock = -1; - logDebug("file: "__FILE__", line: %d, " \ "sync thread to storage server %s:%d started", \ __LINE__, storage_server.ip_addr, storage_server.port); - + while (g_continue_flag && \ pStorage->status != FDFS_STORAGE_STATUS_DELETED && \ pStorage->status != FDFS_STORAGE_STATUS_IP_CHANGED && \ @@ -2634,7 +2997,10 @@ static void* storage_sync_thread_entrance(void* arg) continue; } - if ((result=storage_reader_init(pStorage, &reader)) != 0) + storage_reader_remove_from_list(pReader); + result = storage_reader_init(pStorage, pReader); + storage_reader_add_to_list(pReader); + if (result != 0) { logCrit("file: "__FILE__", line: %d, " \ "storage_reader_init fail, errno=%d, " \ @@ -2644,7 +3010,7 @@ static void* storage_sync_thread_entrance(void* arg) break; } - if (!reader.need_sync_old) + if (!pReader->need_sync_old) { while (g_continue_flag && \ (pStorage->status != FDFS_STORAGE_STATUS_ACTIVE && \ @@ -2658,7 +3024,7 @@ static void* storage_sync_thread_entrance(void* arg) if (pStorage->status != FDFS_STORAGE_STATUS_ACTIVE) { close(storage_server.sock); - storage_reader_destroy(&reader); + storage_reader_destroy(pReader); continue; } } @@ -2674,7 +3040,8 @@ static void* storage_sync_thread_entrance(void* arg) __LINE__, pStorage->ip_addr, local_ip_addr); */ - if (is_local_host_ip(pStorage->ip_addr)) + if (strcmp(pStorage->id, g_my_server_id_str) == 0 || + is_local_host_ip(pStorage->ip_addr)) { //can't self sync to self logError("file: "__FILE__", line: %d, " \ "ip_addr %s belong to the local host," \ @@ -2688,7 +3055,7 @@ static void* storage_sync_thread_entrance(void* arg) if (storage_report_my_server_id(&storage_server) != 0) { close(storage_server.sock); - storage_reader_destroy(&reader); + storage_reader_destroy(pReader); sleep(1); continue; } @@ -2702,7 +3069,7 @@ static void* storage_sync_thread_entrance(void* arg) if (pStorage->status == FDFS_STORAGE_STATUS_SYNCING) { - if (reader.need_sync_old && reader.sync_old_done) + if (pReader->need_sync_old && pReader->sync_old_done) { pStorage->status = FDFS_STORAGE_STATUS_OFFLINE; storage_report_storage_status(pStorage->id, \ @@ -2726,15 +3093,15 @@ static void* storage_sync_thread_entrance(void* arg) (pStorage->status == FDFS_STORAGE_STATUS_ACTIVE || \ pStorage->status == FDFS_STORAGE_STATUS_SYNCING)) { - read_result = storage_binlog_read(&reader, \ + read_result = storage_binlog_read(pReader, \ &record, &record_len); if (read_result == ENOENT) { - if (reader.need_sync_old && \ - !reader.sync_old_done) + if (pReader->need_sync_old && \ + !pReader->sync_old_done) { - reader.sync_old_done = true; - if (storage_write_to_mark_file(&reader) != 0) + pReader->sync_old_done = true; + if (storage_write_to_mark_file(pReader) != 0) { logCrit("file: "__FILE__", line: %d, " \ "storage_write_to_mark_file " \ @@ -2757,9 +3124,9 @@ static void* storage_sync_thread_entrance(void* arg) } - if (reader.last_scan_rows!=reader.scan_row_count) + if (pReader->last_scan_rows!=pReader->scan_row_count) { - if (storage_write_to_mark_file(&reader)!=0) + if (storage_write_to_mark_file(pReader)!=0) { logCrit("file: "__FILE__", line: %d, " \ "storage_write_to_mark_file fail, " \ @@ -2798,8 +3165,8 @@ static void* storage_sync_thread_entrance(void* arg) logWarning("file: "__FILE__", line: %d, " \ "skip invalid record, binlog index: " \ "%d, offset: %"PRId64, \ - __LINE__, reader.binlog_index, \ - reader.binlog_offset); + __LINE__, pReader->binlog_index, \ + pReader->binlog_offset); } else { @@ -2807,17 +3174,17 @@ static void* storage_sync_thread_entrance(void* arg) break; } } - else if ((sync_result=storage_sync_data(&reader, \ + else if ((sync_result=storage_sync_data(pReader, \ &storage_server, &record)) != 0) { logDebug("file: "__FILE__", line: %d, " \ "binlog index: %d, current record " \ "offset: %"PRId64", next " \ "record offset: %"PRId64, \ - __LINE__, reader.binlog_index, \ - reader.binlog_offset, \ - reader.binlog_offset + record_len); - if (rewind_to_prev_rec_end(&reader) != 0) + __LINE__, pReader->binlog_index, \ + pReader->binlog_offset, \ + pReader->binlog_offset + record_len); + if (rewind_to_prev_rec_end(pReader) != 0) { logCrit("file: "__FILE__", line: %d, " \ "rewind_to_prev_rec_end fail, "\ @@ -2828,8 +3195,8 @@ static void* storage_sync_thread_entrance(void* arg) break; } - reader.binlog_offset += record_len; - reader.scan_row_count++; + pReader->binlog_offset += record_len; + pReader->scan_row_count++; if (g_sync_interval > 0) { @@ -2837,9 +3204,9 @@ static void* storage_sync_thread_entrance(void* arg) } } - if (reader.last_scan_rows != reader.scan_row_count) + if (pReader->last_scan_rows != pReader->scan_row_count) { - if (storage_write_to_mark_file(&reader) != 0) + if (storage_write_to_mark_file(pReader) != 0) { logCrit("file: "__FILE__", line: %d, " \ "storage_write_to_mark_file fail, " \ @@ -2851,7 +3218,7 @@ static void* storage_sync_thread_entrance(void* arg) close(storage_server.sock); storage_server.sock = -1; - storage_reader_destroy(&reader); + storage_reader_destroy(pReader); if (!g_continue_flag) { @@ -2868,7 +3235,8 @@ static void* storage_sync_thread_entrance(void* arg) { close(storage_server.sock); } - storage_reader_destroy(&reader); + storage_reader_remove_from_list(pReader); + storage_reader_destroy(pReader); if (pStorage->status == FDFS_STORAGE_STATUS_DELETED || pStorage->status == FDFS_STORAGE_STATUS_IP_CHANGED) @@ -2879,7 +3247,6 @@ static void* storage_sync_thread_entrance(void* arg) } storage_sync_thread_exit(&storage_server); - return NULL; } @@ -2900,11 +3267,11 @@ int storage_sync_thread_start(const FDFSStorageBrief *pStorage) return 0; } - if (storage_server_is_myself(pStorage) || \ + if (strcmp(pStorage->id, g_my_server_id_str) == 0 || is_local_host_ip(pStorage->ip_addr)) //can't self sync to self { - logWarning("file: "__FILE__", line: %d, " \ - "storage id: %s is myself, can't start sync thread!", \ + logWarning("file: "__FILE__", line: %d, " + "storage id: %s is myself, can't start sync thread!", __LINE__, pStorage->id); return 0; } @@ -2969,3 +3336,68 @@ int storage_sync_thread_start(const FDFSStorageBrief *pStorage) return 0; } + +void storage_reader_add_to_list(StorageBinLogReader *pReader) +{ + pthread_mutex_lock(&sync_thread_lock); + fc_list_add_tail(&pReader->link, &reader_head); + pthread_mutex_unlock(&sync_thread_lock); +} + +void storage_reader_remove_from_list(StorageBinLogReader *pReader) +{ + pthread_mutex_lock(&sync_thread_lock); + fc_list_del_init(&pReader->link); + pthread_mutex_unlock(&sync_thread_lock); +} + +static int calc_compress_until_binlog_index() +{ + StorageBinLogReader *pReader; + int min_index; + + pthread_mutex_lock(&sync_thread_lock); + + min_index = g_binlog_index; + fc_list_for_each_entry(pReader, &reader_head, link) + { + if (pReader->binlog_fd >= 0 && pReader->binlog_index >= 0 && + pReader->binlog_index < min_index) + { + min_index = pReader->binlog_index; + } + } + pthread_mutex_unlock(&sync_thread_lock); + + return min_index; +} + +int fdfs_binlog_compress_func(void *args) +{ + char full_filename[MAX_PATH_SIZE]; + int until_index; + int bindex; + int result; + + if (binlog_compress_index >= g_binlog_index) + { + return 0; + } + + until_index = calc_compress_until_binlog_index(); + for (bindex = binlog_compress_index; bindex < until_index; + bindex++) + { + get_binlog_readable_filename_ex(bindex, full_filename); + result = compress_binlog_file(full_filename); + if (!(result == 0 || result == ENOENT)) + { + break; + } + + binlog_compress_index = bindex + 1; + write_to_binlog_index(g_binlog_index); + } + + return 0; +} diff --git a/storage/storage_sync.h b/storage/storage_sync.h index 6ca73f8..7dfa99d 100644 --- a/storage/storage_sync.h +++ b/storage/storage_sync.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //storage_sync.h @@ -11,22 +11,25 @@ #ifndef _STORAGE_SYNC_H_ #define _STORAGE_SYNC_H_ +#include "fastcommon/fc_list.h" #include "storage_func.h" -#define STORAGE_OP_TYPE_SOURCE_CREATE_FILE 'C' //upload file -#define STORAGE_OP_TYPE_SOURCE_APPEND_FILE 'A' //append file -#define STORAGE_OP_TYPE_SOURCE_DELETE_FILE 'D' //delete file -#define STORAGE_OP_TYPE_SOURCE_UPDATE_FILE 'U' //for whole file update such as metadata file -#define STORAGE_OP_TYPE_SOURCE_MODIFY_FILE 'M' //for part modify -#define STORAGE_OP_TYPE_SOURCE_TRUNCATE_FILE 'T' //truncate file -#define STORAGE_OP_TYPE_SOURCE_CREATE_LINK 'L' //create symbol link -#define STORAGE_OP_TYPE_REPLICA_CREATE_FILE 'c' -#define STORAGE_OP_TYPE_REPLICA_APPEND_FILE 'a' -#define STORAGE_OP_TYPE_REPLICA_DELETE_FILE 'd' -#define STORAGE_OP_TYPE_REPLICA_UPDATE_FILE 'u' -#define STORAGE_OP_TYPE_REPLICA_MODIFY_FILE 'm' -#define STORAGE_OP_TYPE_REPLICA_TRUNCATE_FILE 't' -#define STORAGE_OP_TYPE_REPLICA_CREATE_LINK 'l' +#define STORAGE_OP_TYPE_SOURCE_CREATE_FILE 'C' //upload file +#define STORAGE_OP_TYPE_SOURCE_APPEND_FILE 'A' //append file +#define STORAGE_OP_TYPE_SOURCE_DELETE_FILE 'D' //delete file +#define STORAGE_OP_TYPE_SOURCE_UPDATE_FILE 'U' //for whole file update such as metadata file +#define STORAGE_OP_TYPE_SOURCE_MODIFY_FILE 'M' //for part modify +#define STORAGE_OP_TYPE_SOURCE_TRUNCATE_FILE 'T' //truncate file +#define STORAGE_OP_TYPE_SOURCE_CREATE_LINK 'L' //create symbol link +#define STORAGE_OP_TYPE_SOURCE_RENAME_FILE 'R' //rename appender file to normal file +#define STORAGE_OP_TYPE_REPLICA_CREATE_FILE 'c' +#define STORAGE_OP_TYPE_REPLICA_APPEND_FILE 'a' +#define STORAGE_OP_TYPE_REPLICA_DELETE_FILE 'd' +#define STORAGE_OP_TYPE_REPLICA_UPDATE_FILE 'u' +#define STORAGE_OP_TYPE_REPLICA_MODIFY_FILE 'm' +#define STORAGE_OP_TYPE_REPLICA_TRUNCATE_FILE 't' +#define STORAGE_OP_TYPE_REPLICA_CREATE_LINK 'l' +#define STORAGE_OP_TYPE_REPLICA_RENAME_FILE 'r' #define STORAGE_BINLOG_BUFFER_SIZE 64 * 1024 #define STORAGE_BINLOG_LINE_SIZE 256 @@ -37,13 +40,14 @@ extern "C" { typedef struct { + struct fc_list_head link; char storage_id[FDFS_STORAGE_ID_MAX_SIZE]; + char mark_filename[MAX_PATH_SIZE]; bool need_sync_old; bool sync_old_done; bool last_file_exist; //if the last file exist on the dest server BinLogBuffer binlog_buff; time_t until_timestamp; - int mark_fd; int binlog_index; int binlog_fd; int64_t binlog_offset; @@ -88,7 +92,7 @@ int storage_sync_thread_start(const FDFSStorageBrief *pStorage); int kill_storage_sync_threads(); int fdfs_binlog_sync_func(void *args); -char *get_mark_filename_by_reader(const void *pArg, char *full_filename); +char *get_mark_filename_by_reader(StorageBinLogReader *pReader); int storage_unlink_mark_file(const char *storage_id); int storage_rename_mark_file(const char *old_ip_addr, const int old_port, \ const char *new_ip_addr, const int new_port); @@ -99,9 +103,15 @@ int storage_open_readable_binlog(StorageBinLogReader *pReader, \ int storage_reader_init(FDFSStorageBrief *pStorage, StorageBinLogReader *pReader); void storage_reader_destroy(StorageBinLogReader *pReader); -int storage_report_storage_status(const char *storage_id, \ +int storage_report_storage_status(const char *storage_id, const char *ip_addr, const char status); +int fdfs_binlog_compress_func(void *args); + +void storage_reader_add_to_list(StorageBinLogReader *pReader); + +void storage_reader_remove_from_list(StorageBinLogReader *pReader); + #ifdef __cplusplus } #endif diff --git a/storage/storage_sync_func.c b/storage/storage_sync_func.c index ec8b9d3..40fba44 100644 --- a/storage/storage_sync_func.c +++ b/storage/storage_sync_func.c @@ -2,7 +2,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //storage_sync_func.c @@ -29,7 +29,7 @@ #include "storage_func.h" #include "storage_sync_func.h" -void storage_sync_connect_storage_server_ex(FDFSStorageBrief *pStorage, +void storage_sync_connect_storage_server_ex(const FDFSStorageBrief *pStorage, ConnectionInfo *conn, bool *check_flag) { int nContinuousFail; @@ -67,7 +67,8 @@ void storage_sync_connect_storage_server_ex(FDFSStorageBrief *pStorage, { ip_addrs.count = 1; ip_addrs.index = 0; - strcpy(ip_addrs.ips[0], pStorage->ip_addr); + ip_addrs.ips[0].type = fdfs_get_ip_type(pStorage->ip_addr); + strcpy(ip_addrs.ips[0].address, pStorage->ip_addr); } conn->sock = -1; @@ -81,10 +82,10 @@ void storage_sync_connect_storage_server_ex(FDFSStorageBrief *pStorage, { for (i=0; iip_addr, ip_addrs.ips[i]); + strcpy(conn->ip_addr, ip_addrs.ips[i].address); conn->sock = socketCreateExAuto(conn->ip_addr, - g_fdfs_connect_timeout, O_NONBLOCK, - g_client_bind_addr ? g_bind_addr : NULL, &result); + O_NONBLOCK, g_client_bind_addr ? + g_bind_addr : NULL, &result); if (conn->sock < 0) { logCrit("file: "__FILE__", line: %d, " @@ -148,7 +149,7 @@ void storage_sync_connect_storage_server_ex(FDFSStorageBrief *pStorage, logError("file: "__FILE__", line: %d, " "connect to storage server %s:%d fail, " "try count: %d, errno: %d, error info: %s", - __LINE__, ip_addrs.ips[i], g_server_port, avg_fails, + __LINE__, ip_addrs.ips[i].address, g_server_port, avg_fails, conn_results[i], STRERROR(conn_results[i])); } } diff --git a/storage/storage_sync_func.h b/storage/storage_sync_func.h index 70cdb1b..94b2b08 100644 --- a/storage/storage_sync_func.h +++ b/storage/storage_sync_func.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //storage_sync_func.h @@ -17,11 +17,11 @@ extern "C" { #endif -void storage_sync_connect_storage_server_ex(FDFSStorageBrief *pStorage, +void storage_sync_connect_storage_server_ex(const FDFSStorageBrief *pStorage, ConnectionInfo *conn, bool *check_flag); static inline void storage_sync_connect_storage_server( - FDFSStorageBrief *pStorage, ConnectionInfo *conn) + const FDFSStorageBrief *pStorage, ConnectionInfo *conn) { bool check_flag = true; storage_sync_connect_storage_server_ex(pStorage, diff --git a/storage/tracker_client_thread.c b/storage/tracker_client_thread.c index 05861e3..68abe42 100644 --- a/storage/tracker_client_thread.c +++ b/storage/tracker_client_thread.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ @@ -37,7 +37,8 @@ #include "trunk_sync.h" #include "storage_param_getter.h" -#define TRUNK_FILE_CREATOR_TASK_ID 88 +#define TRUNK_FILE_CREATOR_TASK_ID 88 +#define TRUNK_BINLOG_COMPRESS_TASK_ID 89 static pthread_mutex_t reporter_thread_lock; @@ -45,12 +46,16 @@ static pthread_mutex_t reporter_thread_lock; static pthread_t *report_tids = NULL; static bool need_rejoin_tracker = false; -static int tracker_heart_beat(ConnectionInfo *pTrackerServer, \ - int *pstat_chg_sync_count, bool *bServerPortChanged); -static int tracker_report_df_stat(ConnectionInfo *pTrackerServer, \ - bool *bServerPortChanged); -static int tracker_report_sync_timestamp(ConnectionInfo *pTrackerServer, \ - bool *bServerPortChanged); +static int tracker_heart_beat(ConnectionInfo *pTrackerServer, + const int tracker_index, int *pstat_chg_sync_count, + bool *bServerPortChanged); +static int tracker_report_df_stat(ConnectionInfo *pTrackerServer, + const int tracker_index, bool *bServerPortChanged); +static int tracker_report_sync_timestamp(ConnectionInfo *pTrackerServer, + const int tracker_index, bool *bServerPortChanged); + +static int tracker_storage_change_status(ConnectionInfo *pTrackerServer, + const int tracker_index); static int tracker_sync_dest_req(ConnectionInfo *pTrackerServer); static int tracker_sync_dest_query(ConnectionInfo *pTrackerServer); @@ -390,14 +395,14 @@ static void *tracker_report_thread_entrance(void *arg) sync_old_done = true; } - g_my_report_status[tracker_index].src_storage_status = + g_my_report_status[tracker_index].src_storage_result = tracker_sync_notify(conn, tracker_index); - if (g_my_report_status[tracker_index].src_storage_status != 0) + if (g_my_report_status[tracker_index].src_storage_result != 0) { int k; for (k=0; k= \ + if (current_time - last_beat_time >= g_heart_beat_interval) { - if (tracker_heart_beat(conn, &stat_chg_sync_count, - &bServerPortChanged) != 0) + if (tracker_heart_beat(conn, tracker_index, + &stat_chg_sync_count, + &bServerPortChanged) != 0) { break; } @@ -464,8 +468,9 @@ static void *tracker_report_thread_entrance(void *arg) current_time - last_sync_report_time >= g_heart_beat_interval) { - if (tracker_report_sync_timestamp( - conn, &bServerPortChanged)!=0) + if (tracker_report_sync_timestamp(conn, + tracker_index, + &bServerPortChanged) != 0) { break; } @@ -478,7 +483,8 @@ static void *tracker_report_thread_entrance(void *arg) g_stat_report_interval) { if (tracker_report_df_stat(conn, - &bServerPortChanged) != 0) + tracker_index, + &bServerPortChanged) != 0) { break; } @@ -486,6 +492,16 @@ static void *tracker_report_thread_entrance(void *arg) last_df_report_time = current_time; } + if (g_my_report_status[tracker_index].report_my_status) + { + if (tracker_storage_change_status(conn, tracker_index) == 0) + { + g_my_report_status[tracker_index].report_my_status = false; + } + + break; + } + if (g_if_trunker_self) { if (last_trunk_file_id < g_current_trunk_file_id) @@ -717,8 +733,48 @@ static int tracker_start_sync_threads(const FDFSStorageBrief *pStorage) return result; } -static int tracker_merge_servers(ConnectionInfo *pTrackerServer, \ - FDFSStorageBrief *briefServers, const int server_count) +static void tracker_check_my_status(const int tracker_index) +{ + int my_status; + int leader_index; + int leader_status; + + leader_index = g_tracker_group.leader_index; + if ((leader_index < 0) || (tracker_index == leader_index)) + { + return; + } + + my_status = g_my_report_status[tracker_index].my_status; + leader_status = g_my_report_status[leader_index].my_status; + if (my_status < 0 || leader_status < 0) //NOT inited + { + return; + } + if (my_status == leader_status) + { + return; + } + + if (FDFS_IS_AVAILABLE_STATUS(my_status) && + FDFS_IS_AVAILABLE_STATUS(leader_status)) + { + return; + } + + g_my_report_status[tracker_index].report_my_status = true; + + logInfo("file: "__FILE__", line: %d, " + "my status: %d (%s) from tracker #%d != my status: %d (%s) " + "from leader tracker #%d, set report_my_status to true", + __LINE__, my_status, get_storage_status_caption( + my_status), tracker_index, leader_status, + get_storage_status_caption(leader_status), leader_index); +} + +static int tracker_merge_servers(ConnectionInfo *pTrackerServer, + const int tracker_index, FDFSStorageBrief *briefServers, + const int server_count) { FDFSStorageBrief *pServer; FDFSStorageBrief *pEnd; @@ -744,8 +800,14 @@ static int tracker_merge_servers(ConnectionInfo *pTrackerServer, \ { memcpy(&(targetServer.server),pServer,sizeof(FDFSStorageBrief)); - ppFound = (FDFSStorageServer **)bsearch(&pTargetServer, \ - g_sorted_storages, g_storage_count, \ + if (strcmp(pServer->id, g_my_server_id_str) == 0) + { + g_my_report_status[tracker_index].my_status = pServer->status; + tracker_check_my_status(tracker_index); + } + + ppFound = (FDFSStorageServer **)bsearch(&pTargetServer, + g_sorted_storages, g_storage_count, sizeof(FDFSStorageServer *), storage_cmp_by_server_id); if (ppFound != NULL) { @@ -815,9 +877,11 @@ static int tracker_merge_servers(ConnectionInfo *pTrackerServer, \ FDFS_STORAGE_STATUS_SYNCING)) && \ ((*ppFound)->server.status > pServer->status)) { + pServer->id[FDFS_STORAGE_ID_MAX_SIZE - 1] = '\0'; *(pServer->ip_addr + IP_ADDRESS_SIZE - 1) = '\0'; - if (is_local_host_ip(pServer->ip_addr) && \ - buff2int(pServer->port) == g_server_port) + if ((strcmp(pServer->id, g_my_server_id_str) == 0) || + (is_local_host_ip(pServer->ip_addr) && + buff2int(pServer->port) == g_server_port)) { need_rejoin_tracker = true; logWarning("file: "__FILE__", line: %d, " \ @@ -1031,6 +1095,21 @@ static int notify_reselect_tracker_leader(TrackerServerInfo *pTrackerServer) return result; } +static void check_my_status_for_all_trackers() +{ + int tracker_index; + + if (g_tracker_group.leader_index < 0) + { + return; + } + for (tracker_index=0; tracker_index 0) + { + INIT_SCHEDULE_ENTRY_EX(*entry, TRUNK_FILE_CREATOR_TASK_ID, + g_trunk_create_file_time_base, + g_trunk_create_file_interval, + trunk_create_trunk_file_advance, NULL); + entry->new_thread = true; + entry++; + } + + if (g_trunk_compress_binlog_interval > 0) + { + INIT_SCHEDULE_ENTRY_EX(*entry, TRUNK_BINLOG_COMPRESS_TASK_ID, + g_trunk_compress_binlog_time_base, + g_trunk_compress_binlog_interval, + trunk_binlog_compress_func, NULL); + entry->new_thread = true; + entry++; + } + + scheduleArray.count = entry - entries; + if (scheduleArray.count > 0) + { + sched_add_entries(&scheduleArray); + } + + trunk_sync_thread_start_all(); + return 0; +} + +static void do_unset_trunk_server_myself(ConnectionInfo *pTrackerServer) +{ + tracker_report_trunk_fid(pTrackerServer); + g_if_trunker_self = false; + + trunk_waiting_sync_thread_exit(); + + storage_trunk_destroy_ex(true, true); + if (g_trunk_create_file_advance && + g_trunk_create_file_interval > 0) + { + sched_del_entry(TRUNK_FILE_CREATOR_TASK_ID); + } + + if (g_trunk_compress_binlog_interval > 0) + { + sched_del_entry(TRUNK_BINLOG_COMPRESS_TASK_ID); + } +} + +static int tracker_check_response(ConnectionInfo *pTrackerServer, + const int tracker_index, bool *bServerPortChanged) { int64_t nInPackLen; TrackerHeader resp; @@ -1301,11 +1455,13 @@ static int tracker_check_response(ConnectionInfo *pTrackerServer, \ { int port; + pBriefServers->id[FDFS_STORAGE_ID_MAX_SIZE - 1] = '\0'; pBriefServers->ip_addr[IP_ADDRESS_SIZE - 1] = '\0'; port = buff2int(pBriefServers->port); set_trunk_server(pBriefServers->ip_addr, port); - if (is_local_host_ip(pBriefServers->ip_addr) && - port == g_server_port) + if ((strcmp(pBriefServers->id, g_my_server_id_str) == 0) || + (is_local_host_ip(pBriefServers->ip_addr) && + port == g_server_port)) { if (g_if_trunker_self) { @@ -1320,32 +1476,10 @@ static int tracker_check_response(ConnectionInfo *pTrackerServer, \ "I am the the trunk server %s:%d", __LINE__, pBriefServers->ip_addr, port); - tracker_fetch_trunk_fid(pTrackerServer); - g_if_trunker_self = true; - - if ((result=storage_trunk_init()) != 0) - { - return result; - } - - if (g_trunk_create_file_advance && - g_trunk_create_file_interval > 0) - { - ScheduleArray scheduleArray; - ScheduleEntry entries[1]; - - entries[0].id = TRUNK_FILE_CREATOR_TASK_ID; - entries[0].time_base = g_trunk_create_file_time_base; - entries[0].interval = g_trunk_create_file_interval; - entries[0].task_func = trunk_create_trunk_file_advance; - entries[0].func_args = NULL; - - scheduleArray.count = 1; - scheduleArray.entries = entries; - sched_add_entries(&scheduleArray); - } - - trunk_sync_thread_start_all(); + if ((result=do_set_trunk_server_myself(pTrackerServer)) != 0) + { + return result; + } } } else @@ -1357,46 +1491,13 @@ static int tracker_check_response(ConnectionInfo *pTrackerServer, \ if (g_if_trunker_self) { - int saved_trunk_sync_thread_count; - logWarning("file: "__FILE__", line: %d, " \ "I am the old trunk server, " \ "the new trunk server is %s:%d", \ __LINE__, g_trunk_server.connections[0].ip_addr, \ g_trunk_server.connections[0].port); - tracker_report_trunk_fid(pTrackerServer); - g_if_trunker_self = false; - - saved_trunk_sync_thread_count = \ - g_trunk_sync_thread_count; - if (saved_trunk_sync_thread_count > 0) - { - logInfo("file: "__FILE__", line: %d, "\ - "waiting %d trunk sync " \ - "threads exit ...", __LINE__, \ - saved_trunk_sync_thread_count); - } - - while (g_trunk_sync_thread_count > 0) - { - usleep(50000); - } - - if (saved_trunk_sync_thread_count > 0) - { - logInfo("file: "__FILE__", line: %d, " \ - "%d trunk sync threads exited",\ - __LINE__, \ - saved_trunk_sync_thread_count); - } - - storage_trunk_destroy_ex(true); - if (g_trunk_create_file_advance && \ - g_trunk_create_file_interval > 0) - { - sched_del_entry(TRUNK_FILE_CREATOR_TASK_ID); - } + do_unset_trunk_server_myself(pTrackerServer); } } } @@ -1455,8 +1556,8 @@ static int tracker_check_response(ConnectionInfo *pTrackerServer, \ } } - return tracker_merge_servers(pTrackerServer, \ - pBriefServers, server_count); + return tracker_merge_servers(pTrackerServer, tracker_index, + pBriefServers, server_count); } int tracker_sync_src_req(ConnectionInfo *pTrackerServer, \ @@ -1922,9 +2023,10 @@ int tracker_report_join(ConnectionInfo *pTrackerServer, \ pTargetServer = &targetServer; strcpy(targetServer.server.id, g_my_server_id_str); - ppFound = (FDFSStorageServer **)bsearch(&pTargetServer, \ - g_sorted_storages, g_storage_count, \ - sizeof(FDFSStorageServer *), storage_cmp_by_server_id); + ppFound = (FDFSStorageServer **)bsearch(&pTargetServer, + g_sorted_storages, g_storage_count, + sizeof(FDFSStorageServer *), + storage_cmp_by_server_id); if (ppFound != NULL) { pReqBody->status = (*ppFound)->server.status; @@ -1935,14 +2037,14 @@ int tracker_report_join(ConnectionInfo *pTrackerServer, \ { for (i=0; iip_addr, \ pTrackerServer->port, \ (int)sizeof(respBody), in_bytes); - g_my_report_status[tracker_index].my_status = EINVAL; + g_my_report_status[tracker_index].my_result = EINVAL; return EINVAL; } + g_my_report_status[tracker_index].my_status = respBody.my_status; + tracker_check_my_status(tracker_index); + if (*(respBody.src_id) == '\0' && *g_sync_src_id != '\0') { return tracker_sync_notify(pTrackerServer, tracker_index); @@ -2022,8 +2127,8 @@ int tracker_report_join(ConnectionInfo *pTrackerServer, \ } } -static int tracker_report_sync_timestamp(ConnectionInfo *pTrackerServer, \ - bool *bServerPortChanged) +static int tracker_report_sync_timestamp(ConnectionInfo *pTrackerServer, + const int tracker_index, bool *bServerPortChanged) { char out_buff[sizeof(TrackerHeader) + (FDFS_STORAGE_ID_MAX_SIZE + 4) * \ FDFS_MAX_SERVERS_EACH_GROUP]; @@ -2068,11 +2173,12 @@ static int tracker_report_sync_timestamp(ConnectionInfo *pTrackerServer, \ return result; } - return tracker_check_response(pTrackerServer, bServerPortChanged); + return tracker_check_response(pTrackerServer, tracker_index, + bServerPortChanged); } -static int tracker_report_df_stat(ConnectionInfo *pTrackerServer, \ - bool *bServerPortChanged) +static int tracker_report_df_stat(ConnectionInfo *pTrackerServer, + const int tracker_index, bool *bServerPortChanged) { char out_buff[sizeof(TrackerHeader) + \ sizeof(TrackerStatReportReqBody) * 16]; @@ -2115,7 +2221,7 @@ static int tracker_report_df_stat(ConnectionInfo *pTrackerServer, \ for (i=0; isz_total_mb); - long2buff(g_path_space_list[i].free_mb, pStatBuff->sz_free_mb); + long2buff(g_fdfs_store_paths.paths[i].total_mb, pStatBuff->sz_total_mb); + long2buff(g_fdfs_store_paths.paths[i].free_mb, pStatBuff->sz_free_mb); pStatBuff++; } @@ -2147,12 +2253,12 @@ static int tracker_report_df_stat(ConnectionInfo *pTrackerServer, \ store_path_index = -1; for (i=0; i \ + if (g_fdfs_store_paths.paths[i].free_mb > \ g_avg_storage_reserved_mb \ - && g_path_space_list[i].free_mb > max_free_mb) + && g_fdfs_store_paths.paths[i].free_mb > max_free_mb) { store_path_index = i; - max_free_mb = g_path_space_list[i].free_mb; + max_free_mb = g_fdfs_store_paths.paths[i].free_mb; } } if (g_store_path_index != store_path_index) @@ -2178,11 +2284,13 @@ static int tracker_report_df_stat(ConnectionInfo *pTrackerServer, \ return result; } - return tracker_check_response(pTrackerServer, bServerPortChanged); + return tracker_check_response(pTrackerServer, tracker_index, + bServerPortChanged); } -static int tracker_heart_beat(ConnectionInfo *pTrackerServer, \ - int *pstat_chg_sync_count, bool *bServerPortChanged) +static int tracker_heart_beat(ConnectionInfo *pTrackerServer, + const int tracker_index, int *pstat_chg_sync_count, + bool *bServerPortChanged) { char out_buff[sizeof(TrackerHeader) + sizeof(FDFSStorageStatBuff)]; TrackerHeader *pHeader; @@ -2308,7 +2416,84 @@ static int tracker_heart_beat(ConnectionInfo *pTrackerServer, \ return result; } - return tracker_check_response(pTrackerServer, bServerPortChanged); + return tracker_check_response(pTrackerServer, tracker_index, + bServerPortChanged); +} + +static int tracker_storage_change_status(ConnectionInfo *pTrackerServer, + const int tracker_index) +{ + char out_buff[sizeof(TrackerHeader) + 8]; + char in_buff[8]; + TrackerHeader *pHeader; + char *pInBuff; + int result; + int leader_index; + int old_status; + int new_status; + int body_len; + int64_t nInPackLen; + + leader_index = g_tracker_group.leader_index; + if (leader_index < 0 || tracker_index == leader_index) + { + return 0; + } + + old_status = g_my_report_status[tracker_index].my_status; + new_status = g_my_report_status[leader_index].my_status; + if (new_status < 0 || new_status == old_status) + { + return 0; + } + + logInfo("file: "__FILE__", line: %d, " + "tracker server: %s:%d, try to set storage " + "status from %d (%s) to %d (%s)", __LINE__, + pTrackerServer->ip_addr, pTrackerServer->port, + old_status, get_storage_status_caption(old_status), + new_status, get_storage_status_caption(new_status)); + + body_len = 1; + memset(out_buff, 0, sizeof(out_buff)); + pHeader = (TrackerHeader *)out_buff; + long2buff(body_len, pHeader->pkg_len); + pHeader->cmd = TRACKER_PROTO_CMD_STORAGE_CHANGE_STATUS; + *(out_buff + sizeof(TrackerHeader)) = new_status; + + if((result=tcpsenddata_nb(pTrackerServer->sock, out_buff, + sizeof(TrackerHeader) + body_len, g_fdfs_network_timeout)) != 0) + { + logError("file: "__FILE__", line: %d, " + "tracker server %s:%d, send data fail, " + "errno: %d, error info: %s.", + __LINE__, pTrackerServer->ip_addr, + pTrackerServer->port, + result, STRERROR(result)); + return result; + } + + pInBuff = in_buff; + result = fdfs_recv_response(pTrackerServer, + &pInBuff, sizeof(in_buff), &nInPackLen); + if (result != 0) + { + logError("file: "__FILE__", line: %d, " + "fdfs_recv_response fail, result: %d", + __LINE__, result); + return result; + } + + if (nInPackLen != 0) + { + logError("file: "__FILE__", line: %d, " + "tracker server %s:%d, response body length: %d != 0", + __LINE__, pTrackerServer->ip_addr, pTrackerServer->port, + (int)nInPackLen); + return EINVAL; + } + + return 0; } static int tracker_storage_changelog_req(ConnectionInfo *pTrackerServer) diff --git a/storage/tracker_client_thread.h b/storage/tracker_client_thread.h index c6ce687..38704dc 100644 --- a/storage/tracker_client_thread.h +++ b/storage/tracker_client_thread.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //tracker_client_thread.h diff --git a/storage/trunk_mgr/trunk_client.c b/storage/trunk_mgr/trunk_client.c index 240ca1b..1ea60ff 100644 --- a/storage/trunk_mgr/trunk_client.c +++ b/storage/trunk_mgr/trunk_client.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //trunk_client.c diff --git a/storage/trunk_mgr/trunk_client.h b/storage/trunk_mgr/trunk_client.h index e094c8f..5b457e6 100644 --- a/storage/trunk_mgr/trunk_client.h +++ b/storage/trunk_mgr/trunk_client.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //trunk_client.h diff --git a/storage/trunk_mgr/trunk_free_block_checker.c b/storage/trunk_mgr/trunk_free_block_checker.c index 46ac87f..0b8a2d9 100644 --- a/storage/trunk_mgr/trunk_free_block_checker.c +++ b/storage/trunk_mgr/trunk_free_block_checker.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //trunk_free_block_checker.c diff --git a/storage/trunk_mgr/trunk_free_block_checker.h b/storage/trunk_mgr/trunk_free_block_checker.h index e539365..4f83b63 100644 --- a/storage/trunk_mgr/trunk_free_block_checker.h +++ b/storage/trunk_mgr/trunk_free_block_checker.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //trunk_free_block_checker.h diff --git a/storage/trunk_mgr/trunk_mem.c b/storage/trunk_mgr/trunk_mem.c index ce301a3..f54bff1 100644 --- a/storage/trunk_mgr/trunk_mem.c +++ b/storage/trunk_mgr/trunk_mem.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //trunk_mem.c @@ -26,6 +26,7 @@ #include "fastcommon/pthread_func.h" #include "fastcommon/sched_thread.h" #include "fastcommon/avl_tree.h" +#include "fastcommon/buffered_file_writer.h" #include "tracker_types.h" #include "tracker_proto.h" #include "storage_global.h" @@ -42,30 +43,38 @@ #define STORAGE_TRUNK_INIT_FLAG_DESTROYING 1 #define STORAGE_TRUNK_INIT_FLAG_DONE 2 -int g_slot_min_size; -int g_trunk_file_size; -int g_slot_max_size; +int g_slot_min_size = 0; +int g_slot_max_size = 0; +int g_trunk_alloc_alignment_size = 0; +int g_trunk_file_size = 0; int g_store_path_mode = FDFS_STORE_PATH_ROUND_ROBIN; FDFSStorageReservedSpace g_storage_reserved_space = { TRACKER_STORAGE_RESERVED_SPACE_FLAG_MB}; int g_avg_storage_reserved_mb = FDFS_DEF_STORAGE_RESERVED_MB; int g_store_path_index = 0; -int g_current_trunk_file_id = 0; +volatile int g_current_trunk_file_id = 0; TimeInfo g_trunk_create_file_time_base = {0, 0}; +TimeInfo g_trunk_compress_binlog_time_base = {0, 0}; int g_trunk_create_file_interval = 86400; int g_trunk_compress_binlog_min_interval = 0; +int g_trunk_compress_binlog_interval = 0; +int g_trunk_binlog_max_backups = 0; TrackerServerInfo g_trunk_server = {0, 0}; bool g_if_use_trunk_file = false; 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; -static byte trunk_init_flag = STORAGE_TRUNK_INIT_FLAG_NONE; -int64_t g_trunk_total_free_space = 0; +bool g_trunk_free_space_merge = false; +bool g_delete_unused_trunk_files = false; +int g_trunk_binlog_compress_stage = STORAGE_TRUNK_COMPRESS_STAGE_NONE; +volatile int64_t g_trunk_total_free_space = 0; int64_t g_trunk_create_file_space_threshold = 0; time_t g_trunk_last_compress_time = 0; -static pthread_mutex_t trunk_file_lock; +static byte trunk_init_flag = STORAGE_TRUNK_INIT_FLAG_NONE; +static volatile int trunk_binlog_compress_in_progress = 0; +static volatile int trunk_data_save_in_progress = 0; static pthread_mutex_t trunk_mem_lock; static struct fast_mblock_man free_blocks_man; static struct fast_mblock_man tree_nodes_man; @@ -73,28 +82,37 @@ static struct fast_mblock_man tree_nodes_man; static AVLTreeInfo *tree_info_by_sizes = NULL; //for block alloc static int trunk_create_next_file(FDFSTrunkFullInfo *pTrunkInfo); -static int trunk_add_free_block(FDFSTrunkNode *pNode, const bool bWriteBinLog); +static int trunk_add_free_block_ex(FDFSTrunkNode *pNode, + const bool bNeedLock, const bool bWriteBinLog); + +#define trunk_add_free_block(pNode, bWriteBinLog) \ + trunk_add_free_block_ex(pNode, true, bWriteBinLog) static int trunk_restore_node(const FDFSTrunkFullInfo *pTrunkInfo); -static int trunk_delete_space(const FDFSTrunkFullInfo *pTrunkInfo, \ - const bool bWriteBinLog); + +static int trunk_delete_space_ex(const FDFSTrunkFullInfo *pTrunkInfo, + const bool bNeedLock, const bool bWriteBinLog); +#define trunk_delete_space(pTrunkInfo, bWriteBinLog) \ + trunk_delete_space_ex(pTrunkInfo, true, bWriteBinLog) + +static FDFSTrunkFullInfo *free_space_by_trunk(const FDFSTrunkFullInfo + *pTrunkInfo, const bool bNeedLock, const bool bWriteBinLog, + int *result); static int storage_trunk_save(); static int storage_trunk_load(); -static int trunk_mem_binlog_write(const int timestamp, const char op_type, \ +static int trunk_mem_binlog_write(const int timestamp, const char op_type, const FDFSTrunkFullInfo *pTrunk) { - pthread_mutex_lock(&trunk_file_lock); if (op_type == TRUNK_OP_TYPE_ADD_SPACE) { - g_trunk_total_free_space += pTrunk->file.size; + __sync_add_and_fetch(&g_trunk_total_free_space, pTrunk->file.size); } else if (op_type == TRUNK_OP_TYPE_DEL_SPACE) { - g_trunk_total_free_space -= pTrunk->file.size; + __sync_sub_and_fetch(&g_trunk_total_free_space, pTrunk->file.size); } - pthread_mutex_unlock(&trunk_file_lock); return trunk_binlog_write(timestamp, op_type, pTrunk); } @@ -113,7 +131,7 @@ static int storage_trunk_node_compare_offset(void *p1, void *p2) pTrunkInfo1 = &(((FDFSTrunkNode *)p1)->trunk); pTrunkInfo2 = &(((FDFSTrunkNode *)p2)->trunk); - result = memcmp(&(pTrunkInfo1->path), &(pTrunkInfo2->path), \ + result = memcmp(&(pTrunkInfo1->path), &(pTrunkInfo2->path), sizeof(FDFSTrunkPathInfo)); if (result != 0) { @@ -131,7 +149,7 @@ static int storage_trunk_node_compare_offset(void *p1, void *p2) char *storage_trunk_get_data_filename(char *full_filename) { - snprintf(full_filename, MAX_PATH_SIZE, "%s/data/%s", \ + snprintf(full_filename, MAX_PATH_SIZE, "%s/data/%s", g_fdfs_base_path, STORAGE_TRUNK_DATA_FILENAME); return full_filename; } @@ -158,6 +176,7 @@ int storage_trunk_init() int result; int i; int count; + char comma_str[32]; if (!g_if_trunker_self) { @@ -177,15 +196,6 @@ int storage_trunk_init() "storage trunk init ...", __LINE__); memset(&g_trunk_server, 0, sizeof(g_trunk_server)); - if ((result=init_pthread_lock(&trunk_file_lock)) != 0) - { - logError("file: "__FILE__", line: %d, " \ - "init_pthread_lock fail, " \ - "errno: %d, error info: %s", \ - __LINE__, result, STRERROR(result)); - return result; - } - if ((result=init_pthread_lock(&trunk_mem_lock)) != 0) { logError("file: "__FILE__", line: %d, " \ @@ -248,13 +258,13 @@ int storage_trunk_init() count += avl_tree_count(tree_info_by_sizes + i); } - logInfo("file: "__FILE__", line: %d, " \ - "tree by space size node count: %d, tree by trunk file id " \ - "node count: %d, free block count: %d, " \ - "trunk_total_free_space: %"PRId64, __LINE__, \ - count, trunk_free_block_tree_node_count(), \ - trunk_free_block_total_count(), \ - g_trunk_total_free_space); + logInfo("file: "__FILE__", line: %d, " + "tree by space size node count: %d, tree by trunk file id " + "node count: %d, free block count: %d, " + "trunk_total_free_space: %s", __LINE__, + count, trunk_free_block_tree_node_count(), + trunk_free_block_total_count(), + long_to_comma_str(g_trunk_total_free_space, comma_str)); /* { @@ -268,14 +278,15 @@ int storage_trunk_init() return 0; } -int storage_trunk_destroy_ex(const bool bNeedSleep) +int storage_trunk_destroy_ex(const bool bNeedSleep, + const bool bSaveData) { int result; int i; if (trunk_init_flag != STORAGE_TRUNK_INIT_FLAG_DONE) { - logWarning("file: "__FILE__", line: %d, " \ + logWarning("file: "__FILE__", line: %d, " "trunk not inited!", __LINE__); return 0; } @@ -286,9 +297,24 @@ int storage_trunk_destroy_ex(const bool bNeedSleep) sleep(1); } - logDebug("file: "__FILE__", line: %d, " \ + logDebug("file: "__FILE__", line: %d, " "storage trunk destroy", __LINE__); - result = storage_trunk_save(); + if (bSaveData) + { + if (g_current_time - g_up_time >= 3600 && + g_trunk_compress_binlog_interval == 0) + { + result = storage_trunk_save(); + } + else + { + result = 0; + } + } + else + { + result = 0; + } for (i=0; ialloc == 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 inline int trunk_merge_add_to_array(struct trunk_info_array + *trunk_array, FDFSTrunkFullInfo *pTrunkInfo) +{ + int result; + if (trunk_array->count >= trunk_array->alloc) + { + if ((result=trunk_alloc_trunk_array(trunk_array)) != 0) + { + return result; + } + } + + trunk_array->trunks[trunk_array->count++] = pTrunkInfo; + return 0; +} + +static inline int save_one_trunk(struct walk_callback_args *pCallbackArgs, + FDFSTrunkFullInfo *pTrunkInfo) +{ + return buffered_file_writer_append(&pCallbackArgs->data_writer, + "%d %c %d %d %d %u %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); +} + +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; - } - - pCallbackArgs->pCurrent = pCallbackArgs->buff; - } + if ((result=save_one_trunk(pCallbackArgs, &pCurrent->trunk)) != 0) + { + return result; + } + pCallbackArgs->stats.trunk_count++; + pCallbackArgs->stats.total_size += pCurrent->trunk.file.size; pCurrent = pCurrent->next; } @@ -387,146 +467,657 @@ static int tree_walk_callback(void *data, void *args) return 0; } -static int storage_trunk_do_save() +static int tree_walk_callback_to_list(void *data, void *args) { - int64_t trunk_binlog_size; - char trunk_data_filename[MAX_PATH_SIZE]; - struct walk_callback_args callback_args; - int len; + struct walk_callback_args *pCallbackArgs; + FDFSTrunkNode *pCurrent; int result; - int i; - trunk_binlog_size = storage_trunk_get_binlog_size(); - if (trunk_binlog_size < 0) + pCallbackArgs = (struct walk_callback_args *)args; + pCurrent = ((FDFSTrunkSlot *)data)->head; + while (pCurrent != NULL) { - return errno != 0 ? errno : EPERM; + if ((result=trunk_merge_add_to_array(&pCallbackArgs->trunk_array, + &pCurrent->trunk)) != 0) + { + return result; + } + + pCallbackArgs->stats.trunk_count++; + pCallbackArgs->stats.total_size += pCurrent->trunk.file.size; + + pCurrent = pCurrent->next; } - memset(&callback_args, 0, sizeof(callback_args)); - callback_args.pCurrent = callback_args.buff; + return 0; +} - sprintf(callback_args.temp_trunk_filename, "%s/data/.%s.tmp", \ - g_fdfs_base_path, STORAGE_TRUNK_DATA_FILENAME); - callback_args.fd = open(callback_args.temp_trunk_filename, \ - O_WRONLY | O_CREAT | O_TRUNC, 0644); - if (callback_args.fd < 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) { - result = errno != 0 ? errno : EIO; - logError("file: "__FILE__", line: %d, " \ - "open file %s fail, " \ - "errno: %d, error info: %s", \ - __LINE__, callback_args.temp_trunk_filename, \ - result, STRERROR(result)); return result; } - len = sprintf(callback_args.pCurrent, "%"PRId64"\n", \ - trunk_binlog_size); - callback_args.pCurrent += len; + 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; +} + +typedef struct trunk_merge_stat +{ + int merge_count; + int merged_trunk_count; + int deleted_file_count; + int64_t merged_size; + int64_t deleted_file_size; +} TrunkMergeStat; + +static int trunk_merge_spaces(FDFSTrunkFullInfo **ppMergeFirst, + FDFSTrunkFullInfo **ppLast, TrunkMergeStat *merge_stat) +{ + int result; + int merged_size; + FDFSTrunkFullInfo **ppTrunkInfo; + char full_filename[MAX_PATH_SIZE]; + struct stat file_stat; + + merged_size = (*ppLast)->file.offset - (*ppMergeFirst)->file.offset + + (*ppLast)->file.size; + + merge_stat->merge_count++; + merge_stat->merged_trunk_count += (ppLast - ppMergeFirst) + 1; + merge_stat->merged_size += merged_size; + + for (ppTrunkInfo=ppMergeFirst + 1; ppTrunkInfo<=ppLast; ppTrunkInfo++) + { + trunk_delete_space_ex(*ppTrunkInfo, false, false); + } + + do + { + if (!g_delete_unused_trunk_files) + { + break; + } + + if (!((*ppMergeFirst)->file.offset == 0 && + merged_size >= g_trunk_file_size)) + { + break; + } + + trunk_get_full_filename(*ppMergeFirst, full_filename, + sizeof(full_filename)); + if (stat(full_filename, &file_stat) != 0) + { + logError("file: "__FILE__", line: %d, " + "stat trunk file %s fail, " + "errno: %d, error info: %s", __LINE__, + full_filename, errno, STRERROR(errno)); + break; + } + if (merged_size != file_stat.st_size) + { + break; + } + + if (unlink(full_filename) != 0) + { + if (errno != ENOENT) + { + logError("file: "__FILE__", line: %d, " + "unlink trunk file %s fail, " + "errno: %d, error info: %s", __LINE__, + full_filename, errno, STRERROR(errno)); + break; + } + } + + logInfo("file: "__FILE__", line: %d, " + "delete unused trunk file: %s", + __LINE__, full_filename); + + merge_stat->deleted_file_count++; + merge_stat->deleted_file_size += merged_size; + trunk_delete_space_ex(*ppMergeFirst, false, false); + *ppMergeFirst = NULL; + } while (0); + + result = 0; + if (*ppMergeFirst != NULL) + { + FDFSTrunkFullInfo trunkInfo; + + trunkInfo = **ppMergeFirst; + trunkInfo.file.size = merged_size; + + trunk_delete_space_ex(*ppMergeFirst, false, false); + *ppMergeFirst = free_space_by_trunk(&trunkInfo, + false, false, &result); + } + + return result; +} + +static int trunk_save_merged_spaces(struct walk_callback_args *pCallbackArgs) +{ + FDFSTrunkFullInfo **ppTrunkInfo; + FDFSTrunkFullInfo **ppEnd; + FDFSTrunkFullInfo **previous; + FDFSTrunkFullInfo **ppMergeFirst; + TrunkMergeStat merge_stat; + char merged_comma_buff[32]; + char deleted_comma_buff[32]; + char delete_file_prompt[256]; + 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_stat.merge_count = 0; + merge_stat.merged_trunk_count = 0; + merge_stat.merged_size = 0; + merge_stat.deleted_file_count = 0; + merge_stat.deleted_file_size = 0; + previous = NULL; + + ppEnd = pCallbackArgs->trunk_array.trunks + + pCallbackArgs->trunk_array.count; + ppTrunkInfo = pCallbackArgs->trunk_array.trunks; + ppMergeFirst = previous = ppTrunkInfo; + while (++ppTrunkInfo < ppEnd) + { + if (trunk_compare_path_and_id(*previous, *ppTrunkInfo) == 0 && + (*previous)->file.offset + (*previous)->file.size == + (*ppTrunkInfo)->file.offset) + { + previous = ppTrunkInfo; + continue; + } + + if (ppTrunkInfo - ppMergeFirst > 1) + { + trunk_merge_spaces(ppMergeFirst, previous, &merge_stat); + } + if (*ppMergeFirst != NULL) + { + if ((result=save_one_trunk(pCallbackArgs, *ppMergeFirst)) != 0) + { + return result; + } + } + + ppMergeFirst = previous = ppTrunkInfo; + } + + if (ppEnd - ppMergeFirst > 1) + { + trunk_merge_spaces(ppMergeFirst, previous, &merge_stat); + } + if (*ppMergeFirst != NULL) + { + if ((result=save_one_trunk(pCallbackArgs, *ppMergeFirst)) != 0) + { + return result; + } + } + + if (g_delete_unused_trunk_files) + { + sprintf(delete_file_prompt, ", deleted file count: %d, " + "deleted file size: %s", merge_stat.deleted_file_count, + long_to_comma_str(merge_stat.deleted_file_size, + deleted_comma_buff)); + } + else + { + *delete_file_prompt = '\0'; + } + + logInfo("file: "__FILE__", line: %d, " + "merge free trunk spaces, merge count: %d, " + "merged trunk count: %d, merged size: %s%s", + __LINE__, merge_stat.merge_count, + merge_stat.merged_trunk_count, + long_to_comma_str(merge_stat.merged_size, merged_comma_buff), + delete_file_prompt); + + return 0; +} + +static int trunk_open_file_writers(struct walk_callback_args *pCallbackArgs) +{ + int result; + char temp_trunk_filename[MAX_PATH_SIZE]; + + memset(pCallbackArgs, 0, sizeof(*pCallbackArgs)); + + snprintf(temp_trunk_filename, MAX_PATH_SIZE, "%s/data/.%s.tmp", + g_fdfs_base_path, STORAGE_TRUNK_DATA_FILENAME); + if ((result=buffered_file_writer_open(&pCallbackArgs->data_writer, + temp_trunk_filename)) != 0) + { + return result; + } + + return 0; +} + +static int trunk_rename_writers_filename(struct walk_callback_args *pCallbackArgs) +{ + char trunk_data_filename[MAX_PATH_SIZE]; + int result; + + storage_trunk_get_data_filename(trunk_data_filename); + if (rename(pCallbackArgs->data_writer.filename, + trunk_data_filename) != 0) + { + result = errno != 0 ? errno : EIO; + logError("file: "__FILE__", line: %d, " + "rename file %s to %s fail, " + "errno: %d, error info: %s", __LINE__, + pCallbackArgs->data_writer.filename, + trunk_data_filename, result, STRERROR(result)); + return result; + } + + return 0; +} + +static int do_save_trunk_data() +{ + int64_t trunk_binlog_size; + char comma_buff[32]; + struct walk_callback_args callback_args; + int result; + int close_res; + int i; + + if ((result=trunk_open_file_writers(&callback_args)) != 0) + { + return result; + } + + pthread_mutex_lock(&trunk_mem_lock); + trunk_binlog_flush(false); + trunk_binlog_size = storage_trunk_get_binlog_size(); + if (trunk_binlog_size < 0) + { + result = errno != 0 ? errno : EIO; + pthread_mutex_unlock(&trunk_mem_lock); + return result; + } + + if ((result=buffered_file_writer_append(&callback_args.data_writer, + "%"PRId64"\n", trunk_binlog_size)) != 0) + { + pthread_mutex_unlock(&trunk_mem_lock); + buffered_file_writer_close(&callback_args.data_writer); + return result; + } result = 0; - pthread_mutex_lock(&trunk_mem_lock); for (i=0; i 0 && result == 0) - { - if (fc_safe_write(callback_args.fd, callback_args.buff, len) != len) - { - result = errno != 0 ? errno : EIO; - logError("file: "__FILE__", line: %d, "\ - "write to file %s fail, " \ - "errno: %d, error info: %s", \ - __LINE__, callback_args.temp_trunk_filename, \ - result, STRERROR(result)); - } - } + logInfo("file: "__FILE__", line: %d, " + "free trunk stats, count: %d, size: %s", + __LINE__, callback_args.stats.trunk_count, + long_to_comma_str(callback_args.stats.total_size,comma_buff)); + if (g_trunk_free_space_merge && result == 0) + { + result = trunk_save_merged_spaces(&callback_args); + } - if (result == 0 && fsync(callback_args.fd) != 0) - { - result = errno != 0 ? errno : EIO; - logError("file: "__FILE__", line: %d, "\ - "fsync file %s fail, " \ - "errno: %d, error info: %s", \ - __LINE__, callback_args.temp_trunk_filename, \ - result, STRERROR(result)); - } + close_res = buffered_file_writer_close(&callback_args.data_writer); - if (close(callback_args.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__, callback_args.temp_trunk_filename, \ - errno, STRERROR(errno)); - } + if (result == 0) + { + if (close_res != 0) + { + result = close_res; + } + else + { + result = trunk_rename_writers_filename(&callback_args); + } + } pthread_mutex_unlock(&trunk_mem_lock); - if (result != 0) - { - return result; - } + if (callback_args.trunk_array.trunks != NULL) + { + free(callback_args.trunk_array.trunks); + } - storage_trunk_get_data_filename(trunk_data_filename); - if (rename(callback_args.temp_trunk_filename, trunk_data_filename) != 0) - { - result = errno != 0 ? errno : EIO; - logError("file: "__FILE__", line: %d, "\ - "rename file %s to %s fail, " \ - "errno: %d, error info: %s", __LINE__, \ - callback_args.temp_trunk_filename, trunk_data_filename, \ - result, STRERROR(result)); - } + return result; +} + +static int storage_trunk_do_save() +{ + int result; + if (__sync_add_and_fetch(&trunk_data_save_in_progress, 1) != 1) + { + __sync_sub_and_fetch(&trunk_data_save_in_progress, 1); + logError("file: "__FILE__", line: %d, " + "trunk binlog compress already in progress, " + "trunk_data_save_in_progress=%d", __LINE__, + trunk_data_save_in_progress); + return EINPROGRESS; + } + + result = do_save_trunk_data(); + __sync_sub_and_fetch(&trunk_data_save_in_progress, 1); + + return result; +} + +int storage_trunk_binlog_compress_check_recovery() +{ + int result; + char tmp_filename[MAX_PATH_SIZE]; + + if (g_trunk_binlog_compress_stage == + STORAGE_TRUNK_COMPRESS_STAGE_NONE || + g_trunk_binlog_compress_stage == + STORAGE_TRUNK_COMPRESS_STAGE_FINISHED) + { + return 0; + } + + result = 0; + do { + if (g_trunk_binlog_compress_stage == + STORAGE_TRUNK_COMPRESS_STAGE_COMMIT_MERGING) + { + get_trunk_binlog_tmp_filename(tmp_filename); + if (access(tmp_filename, F_OK) != 0) + { + if (errno == ENOENT) + { + g_trunk_binlog_compress_stage = + STORAGE_TRUNK_COMPRESS_STAGE_COMMIT_MERGE_DONE; + } + } + } + else if (g_trunk_binlog_compress_stage == + STORAGE_TRUNK_COMPRESS_STAGE_ROLLBACK_MERGING) + { + get_trunk_binlog_tmp_filename(tmp_filename); + if (access(tmp_filename, F_OK) != 0) + { + if (errno == ENOENT) + { + g_trunk_binlog_compress_stage = + STORAGE_TRUNK_COMPRESS_STAGE_ROLLBACK_MERGE_DONE; + } + } + } + + switch (g_trunk_binlog_compress_stage) + { + case STORAGE_TRUNK_COMPRESS_STAGE_COMPRESS_BEGIN: + case STORAGE_TRUNK_COMPRESS_STAGE_APPLY_DONE: + case STORAGE_TRUNK_COMPRESS_STAGE_SAVE_DONE: + case STORAGE_TRUNK_COMPRESS_STAGE_COMMIT_MERGING: + case STORAGE_TRUNK_COMPRESS_STAGE_ROLLBACK_MERGING: + result = trunk_binlog_compress_rollback(); + break; + case STORAGE_TRUNK_COMPRESS_STAGE_ROLLBACK_MERGE_DONE: + if ((result=trunk_binlog_compress_delete_binlog_rollback_file( + true)) == 0) + { + result = trunk_binlog_compress_rollback(); + } + break; + case STORAGE_TRUNK_COMPRESS_STAGE_COMMIT_MERGE_DONE: + if ((result=trunk_binlog_compress_delete_temp_files_after_commit()) != 0) + { + break; + } + case STORAGE_TRUNK_COMPRESS_STAGE_COMPRESS_SUCCESS: + /* unlink all mark files because the binlog file be compressed */ + result = trunk_unlink_all_mark_files(); + if (result == 0) + { + g_trunk_binlog_compress_stage = + STORAGE_TRUNK_COMPRESS_STAGE_FINISHED; + result = storage_write_to_sync_ini_file(); + } + break; + } + } while (0); + + return result; +} + +static int storage_trunk_compress() +{ + static int last_write_version = 0; + int current_write_version; + int result; + + if (!(g_trunk_binlog_compress_stage == + STORAGE_TRUNK_COMPRESS_STAGE_NONE || + g_trunk_binlog_compress_stage == + STORAGE_TRUNK_COMPRESS_STAGE_FINISHED)) + { + logWarning("file: "__FILE__", line: %d, " + "g_trunk_binlog_compress_stage = %d, " + "can't start trunk binglog compress!", + __LINE__, g_trunk_binlog_compress_stage); + return EAGAIN; + } + + if (g_current_time - g_up_time < 600) + { + logWarning("file: "__FILE__", line: %d, " + "too little time lapse: %ds afer startup, " + "skip trunk binlog compress", __LINE__, + (int)(g_current_time - g_up_time)); + return EAGAIN; + } + + current_write_version = trunk_binlog_get_write_version(); + if (current_write_version == last_write_version) + { + logInfo("file: "__FILE__", line: %d, " + "binlog NOT changed, do NOT need compress", + __LINE__); + return EALREADY; + } + + if (__sync_add_and_fetch(&trunk_binlog_compress_in_progress, 1) != 1) + { + __sync_sub_and_fetch(&trunk_binlog_compress_in_progress, 1); + logError("file: "__FILE__", line: %d, " + "trunk binlog compress already in progress, " + "trunk_binlog_compress_in_progress=%d", + __LINE__, trunk_binlog_compress_in_progress); + return EINPROGRESS; + } + + logInfo("file: "__FILE__", line: %d, " + "start compress trunk binlog ...", __LINE__); + do + { + if ((result=trunk_binlog_compress_delete_rollback_files(false)) != 0) + { + break; + } + + g_trunk_binlog_compress_stage = + STORAGE_TRUNK_COMPRESS_STAGE_COMPRESS_BEGIN; + storage_write_to_sync_ini_file(); + + if ((result=trunk_binlog_compress_apply()) != 0) + { + break; + } + + g_trunk_binlog_compress_stage = + STORAGE_TRUNK_COMPRESS_STAGE_APPLY_DONE; + storage_write_to_sync_ini_file(); + + if ((result=storage_trunk_do_save()) != 0) + { + trunk_binlog_compress_rollback(); + break; + } + + g_trunk_binlog_compress_stage = + STORAGE_TRUNK_COMPRESS_STAGE_SAVE_DONE; + storage_write_to_sync_ini_file(); + + if ((result=trunk_binlog_compress_commit()) != 0) + { + trunk_binlog_compress_rollback(); + break; + } + + g_trunk_last_compress_time = g_current_time; + last_write_version = current_write_version; + + /* unlink all mark files because the binlog file be compressed */ + result = trunk_unlink_all_mark_files(); + } while (0); + + __sync_sub_and_fetch(&trunk_binlog_compress_in_progress, 1); + + if (result == 0) + { + logInfo("file: "__FILE__", line: %d, " + "compress trunk binlog successfully.", __LINE__); + } + else + { + if (g_trunk_binlog_compress_stage != + STORAGE_TRUNK_COMPRESS_STAGE_FINISHED) + { + logCrit("file: "__FILE__", line: %d, " + "compress trunk binlog fail, " + "g_trunk_binlog_compress_stage = %d, " + "set g_if_trunker_self to false!", __LINE__, + g_trunk_binlog_compress_stage); + + g_if_trunker_self = false; + trunk_waiting_sync_thread_exit(); + storage_trunk_destroy_ex(true, false); + } + else + { + logError("file: "__FILE__", line: %d, " + "compress trunk binlog fail.", __LINE__); + } + } return result; } static int storage_trunk_save() { - int result; + int result; - if (!(g_trunk_compress_binlog_min_interval > 0 && \ + if (!(g_trunk_compress_binlog_min_interval > 0 && g_current_time - g_trunk_last_compress_time > g_trunk_compress_binlog_min_interval)) - { - return storage_trunk_do_save(); - } + { + if (__sync_add_and_fetch(&trunk_binlog_compress_in_progress, 0) == 0) + { + return storage_trunk_do_save(); + } + else + { + logWarning("file: "__FILE__", line: %d, " + "trunk binlog compress already in progress, " + "trunk_binlog_compress_in_progress=%d", + __LINE__, trunk_binlog_compress_in_progress); + return 0; + } + } + + if ((result=storage_trunk_compress()) == 0) + { + g_trunk_binlog_compress_stage = STORAGE_TRUNK_COMPRESS_STAGE_FINISHED; + return storage_write_to_sync_ini_file(); + } - logInfo("start compress trunk binlog ..."); - if ((result=trunk_binlog_compress_apply()) != 0) - { - return result; - } + return (result == EAGAIN || result == EALREADY || + result == EINPROGRESS) ? 0 : result; +} - if ((result=storage_trunk_do_save()) != 0) - { - trunk_binlog_compress_rollback(); - return result; - } +int trunk_binlog_compress_func(void *args) +{ + int result; - if ((result=trunk_binlog_compress_commit()) != 0) - { - trunk_binlog_compress_rollback(); - return result; - } + if (!g_if_trunker_self) + { + return 0; + } - g_trunk_last_compress_time = g_current_time; - storage_write_to_sync_ini_file(); + if ((result=storage_trunk_compress()) != 0) + { + return result; + } - logInfo("compress trunk binlog done."); - return trunk_unlink_all_mark_files(); //because the binlog file be compressed + if (!g_if_trunker_self) + { + g_trunk_binlog_compress_stage = STORAGE_TRUNK_COMPRESS_STAGE_FINISHED; + return storage_write_to_sync_ini_file(); + } + + trunk_sync_notify_thread_reset_offset(); + g_trunk_binlog_compress_stage = STORAGE_TRUNK_COMPRESS_STAGE_FINISHED; + return storage_write_to_sync_ini_file(); } static bool storage_trunk_is_space_occupied(const FDFSTrunkFullInfo *pTrunkInfo) @@ -679,9 +1270,9 @@ static int storage_trunk_restore(const int64_t restore_offset) if (restore_offset > trunk_binlog_size) { - logWarning("file: "__FILE__", line: %d, " \ - "restore_offset: %"PRId64 \ - " > trunk_binlog_size: %"PRId64, \ + logWarning("file: "__FILE__", line: %d, " + "restore_offset: %"PRId64 + " > trunk_binlog_size: %"PRId64, __LINE__, restore_offset, trunk_binlog_size); return storage_trunk_save(); } @@ -711,7 +1302,7 @@ static int storage_trunk_restore(const int64_t restore_offset) memset(&record, 0, sizeof(record)); memset(&reader, 0, sizeof(reader)); reader.binlog_offset = restore_offset; - if ((result=trunk_reader_init(NULL, &reader)) != 0) + if ((result=trunk_reader_init(NULL, &reader, false)) != 0) { return result; } @@ -833,7 +1424,7 @@ static int storage_trunk_restore(const int64_t restore_offset) line_count, buff); } } - else if ((result=trunk_delete_space( \ + else if ((result=trunk_delete_space( &record.trunk, false)) != 0) { if (result == ENOENT) @@ -860,10 +1451,13 @@ static int storage_trunk_restore(const int64_t restore_offset) trunk_mark_filename_by_reader(&reader, trunk_mark_filename); if (unlink(trunk_mark_filename) != 0) { - logError("file: "__FILE__", line: %d, " \ - "unlink file %s fail, " \ - "errno: %d, error info: %s", __LINE__, \ - trunk_mark_filename, errno, STRERROR(errno)); + if (errno != ENOENT) + { + logError("file: "__FILE__", line: %d, " + "unlink file %s fail, " + "errno: %d, error info: %s", __LINE__, + trunk_mark_filename, errno, STRERROR(errno)); + } } if (result != 0) @@ -873,19 +1467,19 @@ static int storage_trunk_restore(const int64_t restore_offset) avl_tree_destroy(&tree_info_by_offset); } - logError("file: "__FILE__", line: %d, " \ - "trunk load fail, errno: %d, error info: %s", \ + logError("file: "__FILE__", line: %d, " + "trunk load fail, errno: %d, error info: %s", __LINE__, result, STRERROR(result)); return result; } if (trunk_init_reload_from_binlog) { - logInfo("file: "__FILE__", line: %d, " \ - "free tree node count: %d", \ + logInfo("file: "__FILE__", line: %d, " + "free tree node count: %d", __LINE__, avl_tree_count(&tree_info_by_offset)); - result = avl_tree_walk(&tree_info_by_offset, \ + result = avl_tree_walk(&tree_info_by_offset, storage_trunk_add_free_blocks_callback, NULL); tree_info_by_offset.free_data_func = NULL; @@ -894,36 +1488,16 @@ static int storage_trunk_restore(const int64_t restore_offset) if (result == 0) { - logDebug("file: "__FILE__", line: %d, " \ - "trunk metadata recovery done. start offset: " \ - "%"PRId64", recovery file size: " \ - "%"PRId64, __LINE__, \ + logDebug("file: "__FILE__", line: %d, " + "trunk metadata recovery done. start offset: " + "%"PRId64", recovery file size: " + "%"PRId64, __LINE__, restore_offset, trunk_binlog_size - restore_offset); - return storage_trunk_save(); - } - return result; -} - -int storage_delete_trunk_data_file() -{ - char trunk_data_filename[MAX_PATH_SIZE]; - int result; - - storage_trunk_get_data_filename(trunk_data_filename); - if (unlink(trunk_data_filename) == 0) - { - return 0; - } - - result = errno != 0 ? errno : ENOENT; - if (result != ENOENT) - { - logError("file: "__FILE__", line: %d, " \ - "unlink trunk data file: %s fail, " \ - "errno: %d, error info: %s", \ - __LINE__, trunk_data_filename, \ - result, STRERROR(result)); + if (g_trunk_compress_binlog_interval == 0) + { + return storage_trunk_save(); + } } return result; @@ -933,7 +1507,7 @@ static int storage_trunk_load() { #define TRUNK_DATA_NEW_FIELD_COUNT 8 // >= v5.01 #define TRUNK_DATA_OLD_FIELD_COUNT 6 // < V5.01 -#define TRUNK_LINE_MAX_LENGHT 64 +#define TRUNK_LINE_MAX_LENGTH 64 int64_t restore_offset; char trunk_data_filename[MAX_PATH_SIZE]; @@ -1027,24 +1601,24 @@ static int storage_trunk_load() } len = strlen(pLineStart); - if (len > TRUNK_LINE_MAX_LENGHT) + if (len > TRUNK_LINE_MAX_LENGTH) { - logError("file: "__FILE__", line: %d, " \ - "file %s, line length: %d too long", \ + logError("file: "__FILE__", line: %d, " + "file %s, line length: %d too long", __LINE__, trunk_data_filename, len); close(fd); return EINVAL; } memcpy(buff, pLineStart, len); - if ((bytes=fc_safe_read(fd, buff + len, sizeof(buff) \ + if ((bytes=fc_safe_read(fd, buff + len, sizeof(buff) - len - 1)) < 0) { result = errno != 0 ? errno : EIO; - logError("file: "__FILE__", line: %d, " \ - "read from file %s fail, " \ - "errno: %d, error info: %s", \ - __LINE__, trunk_data_filename, \ + logError("file: "__FILE__", line: %d, " + "read from file %s fail, " + "errno: %d, error info: %s", + __LINE__, trunk_data_filename, result, STRERROR(result)); close(fd); return result; @@ -1053,9 +1627,9 @@ static int storage_trunk_load() if (bytes == 0) { result = ENOENT; - logError("file: "__FILE__", line: %d, " \ - "file: %s, end of file, expect " \ - "end line", __LINE__, \ + logError("file: "__FILE__", line: %d, " + "file: %s, end of file, expect " + "end line", __LINE__, trunk_data_filename); close(fd); return result; @@ -1071,11 +1645,11 @@ static int storage_trunk_load() *pLineEnd = '\0'; col_count = splitEx(pLineStart, ' ', cols, TRUNK_DATA_NEW_FIELD_COUNT); - if (col_count != TRUNK_DATA_NEW_FIELD_COUNT && \ + if (col_count != TRUNK_DATA_NEW_FIELD_COUNT && col_count != TRUNK_DATA_OLD_FIELD_COUNT) { - logError("file: "__FILE__", line: %d, " \ - "file %s, line: %d is invalid", \ + logError("file: "__FILE__", line: %d, " + "file %s, line: %d is invalid", __LINE__, trunk_data_filename, line_count); close(fd); return EINVAL; @@ -1108,61 +1682,36 @@ static int storage_trunk_load() if (*pLineStart != '\0') { - logError("file: "__FILE__", line: %d, " \ - "file %s does not end correctly", \ + logError("file: "__FILE__", line: %d, " + "file %s does not end correctly", __LINE__, trunk_data_filename); return EINVAL; } - logDebug("file: "__FILE__", line: %d, " \ - "file %s, line count: %d", \ + logDebug("file: "__FILE__", line: %d, " + "file %s, line count: %d", __LINE__, trunk_data_filename, line_count); return storage_trunk_restore(restore_offset); } -int trunk_free_space(const FDFSTrunkFullInfo *pTrunkInfo, \ - const bool bWriteBinLog) +static FDFSTrunkFullInfo *free_space_by_trunk(const FDFSTrunkFullInfo + *pTrunkInfo, const bool bNeedLock, const bool bWriteBinLog, + int *result) { - int result; struct fast_mblock_node *pMblockNode; FDFSTrunkNode *pTrunkNode; - if (!g_if_trunker_self) - { - logError("file: "__FILE__", line: %d, " \ - "I am not trunk server!", __LINE__); - return EINVAL; - } - - if (trunk_init_flag != STORAGE_TRUNK_INIT_FLAG_DONE) - { - if (bWriteBinLog) - { - logError("file: "__FILE__", line: %d, " \ - "I am not inited!", __LINE__); - return EINVAL; - } - } - - if (pTrunkInfo->file.size < g_slot_min_size) - { - logDebug("file: "__FILE__", line: %d, " \ - "space: %d is too small, do not need recycle!", \ - __LINE__, pTrunkInfo->file.size); - return 0; - } - pMblockNode = fast_mblock_alloc(&free_blocks_man); if (pMblockNode == NULL) { - result = errno != 0 ? errno : EIO; - logError("file: "__FILE__", line: %d, " \ - "malloc %d bytes fail, " \ - "errno: %d, error info: %s", \ - __LINE__, (int)sizeof(FDFSTrunkNode), \ - result, STRERROR(result)); - return result; + *result = errno != 0 ? errno : EIO; + logError("file: "__FILE__", line: %d, " + "malloc %d bytes fail, " + "errno: %d, error info: %s", + __LINE__, (int)sizeof(FDFSTrunkNode), + *result, STRERROR(*result)); + return NULL; } pTrunkNode = (FDFSTrunkNode *)pMblockNode->data; @@ -1171,90 +1720,130 @@ int trunk_free_space(const FDFSTrunkFullInfo *pTrunkInfo, \ pTrunkNode->pMblockNode = pMblockNode; pTrunkNode->trunk.status = FDFS_TRUNK_STATUS_FREE; pTrunkNode->next = NULL; - return trunk_add_free_block(pTrunkNode, bWriteBinLog); + *result = trunk_add_free_block_ex(pTrunkNode, bNeedLock, bWriteBinLog); + return &pTrunkNode->trunk; } -static int trunk_add_free_block(FDFSTrunkNode *pNode, const bool bWriteBinLog) +int trunk_free_space(const FDFSTrunkFullInfo *pTrunkInfo, + const bool bWriteBinLog) +{ + int result; + if (!g_if_trunker_self) + { + logError("file: "__FILE__", line: %d, " + "I am not trunk server!", __LINE__); + return EINVAL; + } + + if (trunk_init_flag != STORAGE_TRUNK_INIT_FLAG_DONE) + { + if (bWriteBinLog) + { + logError("file: "__FILE__", line: %d, " + "I am not inited!", __LINE__); + return EINVAL; + } + } + + if (pTrunkInfo->file.size < g_slot_min_size) + { + logDebug("file: "__FILE__", line: %d, " + "space: %d is too small, do not need reclaim!", + __LINE__, pTrunkInfo->file.size); + return 0; + } + + free_space_by_trunk(pTrunkInfo, true, bWriteBinLog, &result); + return result; +} + +static int trunk_add_free_block_ex(FDFSTrunkNode *pNode, + const bool bNeedLock, const bool bWriteBinLog) { int result; struct fast_mblock_node *pMblockNode; FDFSTrunkSlot target_slot; FDFSTrunkSlot *chain; - pthread_mutex_lock(&trunk_mem_lock); + if (bNeedLock) + { + pthread_mutex_lock(&trunk_mem_lock); + } - if ((result=trunk_free_block_check_duplicate(&(pNode->trunk))) != 0) - { - pthread_mutex_unlock(&trunk_mem_lock); - return result; - } + do + { + if ((result=trunk_free_block_check_duplicate(&(pNode->trunk))) != 0) + { + break; + } - target_slot.size = pNode->trunk.file.size; - target_slot.head = NULL; - chain = (FDFSTrunkSlot *)avl_tree_find(tree_info_by_sizes + \ - pNode->trunk.path.store_path_index, &target_slot); - if (chain == NULL) - { - pMblockNode = fast_mblock_alloc(&tree_nodes_man); - if (pMblockNode == NULL) - { - result = errno != 0 ? errno : EIO; - logError("file: "__FILE__", line: %d, " \ - "malloc %d bytes fail, " \ - "errno: %d, error info: %s", \ - __LINE__, (int)sizeof(FDFSTrunkSlot), \ - result, STRERROR(result)); - pthread_mutex_unlock(&trunk_mem_lock); - return result; - } + target_slot.size = pNode->trunk.file.size; + target_slot.head = NULL; + chain = (FDFSTrunkSlot *)avl_tree_find(tree_info_by_sizes + + pNode->trunk.path.store_path_index, &target_slot); + if (chain == NULL) + { + pMblockNode = fast_mblock_alloc(&tree_nodes_man); + if (pMblockNode == NULL) + { + result = errno != 0 ? errno : EIO; + logError("file: "__FILE__", line: %d, " + "malloc %d bytes fail, " + "errno: %d, error info: %s", + __LINE__, (int)sizeof(FDFSTrunkSlot), + result, STRERROR(result)); + break; + } - chain = (FDFSTrunkSlot *)pMblockNode->data; - chain->pMblockNode = pMblockNode; - chain->size = pNode->trunk.file.size; - pNode->next = NULL; - chain->head = pNode; + chain = (FDFSTrunkSlot *)pMblockNode->data; + chain->pMblockNode = pMblockNode; + chain->size = pNode->trunk.file.size; + pNode->next = NULL; + chain->head = pNode; - if (avl_tree_insert(tree_info_by_sizes + pNode->trunk. \ - path.store_path_index, chain) != 1) - { - result = errno != 0 ? errno : ENOMEM; - logError("file: "__FILE__", line: %d, " \ - "avl_tree_insert fail, " \ - "errno: %d, error info: %s", \ - __LINE__, result, STRERROR(result)); - pthread_mutex_unlock(&trunk_mem_lock); - return result; - } - } - else - { - pNode->next = chain->head; - chain->head = pNode; - } + if (avl_tree_insert(tree_info_by_sizes + pNode->trunk. + path.store_path_index, chain) != 1) + { + result = errno != 0 ? errno : ENOMEM; + logError("file: "__FILE__", line: %d, " + "avl_tree_insert fail, " + "errno: %d, error info: %s", + __LINE__, result, STRERROR(result)); + break; + } + } + else + { + pNode->next = chain->head; + chain->head = pNode; + } - if (bWriteBinLog) - { - result = trunk_mem_binlog_write(g_current_time, \ - TRUNK_OP_TYPE_ADD_SPACE, &(pNode->trunk)); - } - else - { - pthread_mutex_lock(&trunk_file_lock); - g_trunk_total_free_space += pNode->trunk.file.size; - pthread_mutex_unlock(&trunk_file_lock); - result = 0; - } + if (bWriteBinLog) + { + result = trunk_mem_binlog_write(g_current_time, + TRUNK_OP_TYPE_ADD_SPACE, &(pNode->trunk)); + } + else + { + __sync_add_and_fetch(&g_trunk_total_free_space, + pNode->trunk.file.size); + result = 0; + } - if (result == 0) - { - result = trunk_free_block_insert(&(pNode->trunk)); - } - else - { - trunk_free_block_insert(&(pNode->trunk)); - } + if (result == 0) + { + result = trunk_free_block_insert(&(pNode->trunk)); + } + else + { + trunk_free_block_insert(&(pNode->trunk)); + } + } while (0); - pthread_mutex_unlock(&trunk_mem_lock); + if (bNeedLock) + { + pthread_mutex_unlock(&trunk_mem_lock); + } return result; } @@ -1275,8 +1864,8 @@ static void trunk_delete_size_tree_entry(const int store_path_index, \ } } -static int trunk_delete_space(const FDFSTrunkFullInfo *pTrunkInfo, \ - const bool bWriteBinLog) +static int trunk_delete_space_ex(const FDFSTrunkFullInfo *pTrunkInfo, + const bool bNeedLock, const bool bWriteBinLog) { int result; FDFSTrunkSlot target_slot; @@ -1287,64 +1876,79 @@ static int trunk_delete_space(const FDFSTrunkFullInfo *pTrunkInfo, \ target_slot.size = pTrunkInfo->file.size; target_slot.head = NULL; + result = 0; - pthread_mutex_lock(&trunk_mem_lock); - pSlot = (FDFSTrunkSlot *)avl_tree_find(tree_info_by_sizes + \ - pTrunkInfo->path.store_path_index, &target_slot); - if (pSlot == NULL) - { - pthread_mutex_unlock(&trunk_mem_lock); - logError("file: "__FILE__", line: %d, " \ - "can't find trunk entry: %s", __LINE__, \ - trunk_info_dump(pTrunkInfo, buff, sizeof(buff))); - return ENOENT; - } + if (bNeedLock) + { + pthread_mutex_lock(&trunk_mem_lock); + } + do + { + pSlot = (FDFSTrunkSlot *)avl_tree_find(tree_info_by_sizes + + pTrunkInfo->path.store_path_index, &target_slot); + if (pSlot == NULL) + { + logError("file: "__FILE__", line: %d, " + "can't find trunk entry: %s", __LINE__, + trunk_info_dump(pTrunkInfo, buff, sizeof(buff))); + result = ENOENT; + break; + } - pPrevious = NULL; - pCurrent = pSlot->head; - while (pCurrent != NULL && memcmp(&(pCurrent->trunk), pTrunkInfo, \ - sizeof(FDFSTrunkFullInfo)) != 0) - { - pPrevious = pCurrent; - pCurrent = pCurrent->next; - } + pPrevious = NULL; + pCurrent = pSlot->head; + while (pCurrent != NULL && memcmp(&(pCurrent->trunk), + pTrunkInfo, sizeof(FDFSTrunkFullInfo)) != 0) + { + pPrevious = pCurrent; + pCurrent = pCurrent->next; + } - if (pCurrent == NULL) - { - pthread_mutex_unlock(&trunk_mem_lock); - logError("file: "__FILE__", line: %d, " \ - "can't find trunk entry: %s", __LINE__, \ - trunk_info_dump(pTrunkInfo, buff, sizeof(buff))); - return ENOENT; - } + if (pCurrent == NULL) + { + logError("file: "__FILE__", line: %d, " + "can't find trunk entry: %s", __LINE__, + trunk_info_dump(pTrunkInfo, buff, sizeof(buff))); + result = ENOENT; + break; + } - if (pPrevious == NULL) - { - pSlot->head = pCurrent->next; - if (pSlot->head == NULL) - { - trunk_delete_size_tree_entry(pTrunkInfo->path. \ - store_path_index, pSlot); - } - } - else - { - pPrevious->next = pCurrent->next; - } + if (pPrevious == NULL) + { + pSlot->head = pCurrent->next; + if (pSlot->head == NULL) + { + trunk_delete_size_tree_entry(pTrunkInfo->path. + store_path_index, pSlot); + } + } + else + { + pPrevious->next = pCurrent->next; + } - trunk_free_block_delete(&(pCurrent->trunk)); - pthread_mutex_unlock(&trunk_mem_lock); + trunk_free_block_delete(&(pCurrent->trunk)); + } while (0); + + if (bNeedLock) + { + pthread_mutex_unlock(&trunk_mem_lock); + } + + if (result != 0) + { + return result; + } if (bWriteBinLog) { - result = trunk_mem_binlog_write(g_current_time, \ + result = trunk_mem_binlog_write(g_current_time, TRUNK_OP_TYPE_DEL_SPACE, &(pCurrent->trunk)); } else { - pthread_mutex_lock(&trunk_file_lock); - g_trunk_total_free_space -= pCurrent->trunk.file.size; - pthread_mutex_unlock(&trunk_file_lock); + __sync_sub_and_fetch(&g_trunk_total_free_space, + pCurrent->trunk.file.size); result = 0; } @@ -1513,10 +2117,33 @@ int trunk_alloc_space(const int size, FDFSTrunkFullInfo *pResult) FDFSTrunkNode *pPreviousNode; FDFSTrunkNode *pTrunkNode; int result; + int aligned_size; + int remain; STORAGE_TRUNK_CHECK_STATUS(); - target_slot.size = (size > g_slot_min_size) ? size : g_slot_min_size; + if (size <= g_slot_min_size) + { + aligned_size = g_slot_min_size; + } + else if (g_trunk_alloc_alignment_size == 0) + { + aligned_size = size; + } + else + { + remain = size % g_trunk_alloc_alignment_size; + if (remain == 0) + { + aligned_size = size; + } + else + { + aligned_size = size + (g_trunk_alloc_alignment_size - remain); + } + } + + target_slot.size = aligned_size; target_slot.head = NULL; pPreviousNode = NULL; @@ -1524,7 +2151,7 @@ int trunk_alloc_space(const int size, FDFSTrunkFullInfo *pResult) pthread_mutex_lock(&trunk_mem_lock); while (1) { - pSlot = (FDFSTrunkSlot *)avl_tree_find_ge(tree_info_by_sizes \ + pSlot = (FDFSTrunkSlot *)avl_tree_find_ge(tree_info_by_sizes + pResult->path.store_path_index, &target_slot); if (pSlot == NULL) { @@ -1533,8 +2160,8 @@ int trunk_alloc_space(const int size, FDFSTrunkFullInfo *pResult) pPreviousNode = NULL; pTrunkNode = pSlot->head; - while (pTrunkNode != NULL && \ - pTrunkNode->trunk.status == FDFS_TRUNK_STATUS_HOLD) + while (pTrunkNode != NULL && + pTrunkNode->trunk.status != FDFS_TRUNK_STATUS_FREE) { pPreviousNode = pTrunkNode; pTrunkNode = pTrunkNode->next; @@ -1555,7 +2182,7 @@ int trunk_alloc_space(const int size, FDFSTrunkFullInfo *pResult) pSlot->head = pTrunkNode->next; if (pSlot->head == NULL) { - trunk_delete_size_tree_entry(pResult->path. \ + trunk_delete_size_tree_entry(pResult->path. store_path_index, pSlot); } } @@ -1568,7 +2195,7 @@ int trunk_alloc_space(const int size, FDFSTrunkFullInfo *pResult) } else { - pTrunkNode = trunk_create_trunk_file(pResult->path. \ + pTrunkNode = trunk_create_trunk_file(pResult->path. store_path_index, &result); if (pTrunkNode == NULL) { @@ -1578,7 +2205,7 @@ int trunk_alloc_space(const int size, FDFSTrunkFullInfo *pResult) } pthread_mutex_unlock(&trunk_mem_lock); - result = trunk_split(pTrunkNode, size); + result = trunk_split(pTrunkNode, aligned_size); if (result != 0) { return result; @@ -1588,7 +2215,7 @@ int trunk_alloc_space(const int size, FDFSTrunkFullInfo *pResult) result = trunk_add_free_block(pTrunkNode, true); if (result == 0) { - memcpy(pResult, &(pTrunkNode->trunk), \ + memcpy(pResult, &(pTrunkNode->trunk), sizeof(FDFSTrunkFullInfo)); } @@ -1644,10 +2271,9 @@ static int trunk_create_next_file(FDFSTrunkFullInfo *pTrunkInfo) while (1) { - pthread_mutex_lock(&trunk_file_lock); - pTrunkInfo->file.id = ++g_current_trunk_file_id; + pTrunkInfo->file.id = __sync_add_and_fetch( + &g_current_trunk_file_id, 1); result = storage_write_to_sync_ini_file(); - pthread_mutex_unlock(&trunk_file_lock); if (result != 0) { return result; @@ -1859,16 +2485,13 @@ bool trunk_check_size(const int64_t file_size) return file_size <= g_slot_max_size; } -int trunk_file_delete(const char *trunk_filename, \ +int trunk_file_delete(const char *trunk_filename, const FDFSTrunkFullInfo *pTrunkInfo) { - char pack_buff[FDFS_TRUNK_FILE_HEADER_SIZE]; - char buff[64 * 1024]; int fd; int write_bytes; int result; int remain_bytes; - FDFSTrunkHeader trunkHeader; fd = open(trunk_filename, O_WRONLY); if (fd < 0) @@ -1883,27 +2506,13 @@ int trunk_file_delete(const char *trunk_filename, \ return result; } - memset(&trunkHeader, 0, sizeof(trunkHeader)); - trunkHeader.alloc_size = pTrunkInfo->file.size; - trunkHeader.file_type = FDFS_TRUNK_FILE_TYPE_NONE; - trunk_pack_header(&trunkHeader, pack_buff); - - write_bytes = fc_safe_write(fd, pack_buff, FDFS_TRUNK_FILE_HEADER_SIZE); - if (write_bytes != FDFS_TRUNK_FILE_HEADER_SIZE) - { - result = errno != 0 ? errno : EIO; - close(fd); - return result; - } - - memset(buff, 0, sizeof(buff)); result = 0; - remain_bytes = pTrunkInfo->file.size - FDFS_TRUNK_FILE_HEADER_SIZE; + remain_bytes = pTrunkInfo->file.size; while (remain_bytes > 0) { - write_bytes = remain_bytes > sizeof(buff) ? \ - sizeof(buff) : remain_bytes; - if (fc_safe_write(fd, buff, write_bytes) != write_bytes) + write_bytes = remain_bytes > g_zero_buffer.length ? + g_zero_buffer.length : remain_bytes; + if (fc_safe_write(fd, g_zero_buffer.buff, write_bytes) != write_bytes) { result = errno != 0 ? errno : EIO; break; @@ -1928,23 +2537,23 @@ int trunk_create_trunk_file_advance(void *args) if (!g_trunk_create_file_advance) { - logError("file: "__FILE__", line: %d, " \ + logError("file: "__FILE__", line: %d, " "do not need create trunk file advancely!", __LINE__); return EINVAL; } if (!g_if_trunker_self) { - logError("file: "__FILE__", line: %d, " \ + logError("file: "__FILE__", line: %d, " "I am not trunk server!", __LINE__); return ENOENT; } - alloc_space = g_trunk_create_file_space_threshold - \ - g_trunk_total_free_space; + alloc_space = g_trunk_create_file_space_threshold - + __sync_add_and_fetch(&g_trunk_total_free_space, 0); if (alloc_space <= 0) { - logDebug("file: "__FILE__", line: %d, " \ + logDebug("file: "__FILE__", line: %d, " "do not need create trunk file!", __LINE__); return 0; } @@ -1953,8 +2562,8 @@ int trunk_create_trunk_file_advance(void *args) free_mb_sum = 0; for (i=0; ipath.store_path_index, \ pTrunkInfo->path.sub_path_high, \ pTrunkInfo->path.sub_path_low, \ @@ -325,7 +342,7 @@ char *trunk_get_full_filename_ex(const FDFSStorePaths *pStorePaths, \ char short_filename[64]; char *pStorePath; - pStorePath = pStorePaths->paths[pTrunkInfo->path.store_path_index]; + pStorePath = pStorePaths->paths[pTrunkInfo->path.store_path_index].path; TRUNK_GET_FILENAME(pTrunkInfo->file.id, short_filename); snprintf(full_filename, buff_size, \ @@ -378,7 +395,7 @@ void trunk_file_info_encode(const FDFSTrunkFileInfo *pTrunkFile, char *str) int2buff(pTrunkFile->id, buff); int2buff(pTrunkFile->offset, buff + sizeof(int)); int2buff(pTrunkFile->size, buff + sizeof(int) * 2); - base64_encode_ex(&g_fdfs_base64_context, buff, sizeof(buff), \ + base64_encode_ex(&g_fdfs_base64_context, buff, sizeof(buff), str, &len, false); } @@ -387,7 +404,7 @@ void trunk_file_info_decode(const char *str, FDFSTrunkFileInfo *pTrunkFile) char buff[FDFS_TRUNK_FILE_INFO_LEN]; int len; - base64_decode_auto(&g_fdfs_base64_context, str, FDFS_TRUNK_FILE_INFO_LEN, \ + base64_decode_auto(&g_fdfs_base64_context, str, FDFS_TRUNK_FILE_INFO_LEN, buff, &len); pTrunkFile->id = buff2int(buff); @@ -547,7 +564,7 @@ int trunk_file_do_lstat_func_ex(const FDFSStorePaths *pStorePaths, \ if (filename_len != FDFS_TRUNK_FILENAME_LENGTH) //not trunk file { snprintf(full_filename, sizeof(full_filename), "%s/data/%s", \ - pStorePaths->paths[store_path_index], true_filename); + pStorePaths->paths[store_path_index].path, true_filename); if (stat_func == FDFS_STAT_FUNC_STAT) { @@ -576,7 +593,7 @@ int trunk_file_do_lstat_func_ex(const FDFSStorePaths *pStorePaths, \ if (!IS_TRUNK_FILE(file_size)) //slave file { snprintf(full_filename, sizeof(full_filename), "%s/data/%s", \ - pStorePaths->paths[store_path_index], true_filename); + pStorePaths->paths[store_path_index].path, true_filename); if (stat_func == FDFS_STAT_FUNC_STAT) { @@ -655,10 +672,13 @@ int trunk_file_do_lstat_func_ex(const FDFSStorePaths *pStorePaths, \ } else { - close(fd); - logError("file: "__FILE__", line: %d, " \ - "Invalid file type: %d", __LINE__, \ + /* + logError("file: "__FILE__", line: %d, " + "Invalid file type: %d", __LINE__, pTrunkHeader->file_type); + */ + + close(fd); return ENOENT; } diff --git a/storage/trunk_mgr/trunk_shared.h b/storage/trunk_mgr/trunk_shared.h index db2513c..c845c15 100644 --- a/storage/trunk_mgr/trunk_shared.h +++ b/storage/trunk_mgr/trunk_shared.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //trunk_shared.h @@ -46,7 +46,21 @@ #define IS_TRUNK_FILE_BY_ID(trunkInfo) (trunkInfo.file.id > 0) #define TRUNK_GET_FILENAME(file_id, filename) \ - sprintf(filename, "%06d", file_id) + sprintf(filename, "%06u", file_id) + +typedef struct +{ + int total_mb; //total spaces + int free_mb; //free spaces + int path_len; //the length of store path + char *path; //file store path + char *mark; //path mark to avoid confusion +} FDFSStorePathInfo; + +typedef struct { + int count; //store path count + FDFSStorePathInfo *paths; //file store paths +} FDFSStorePaths; #ifdef __cplusplus extern "C" { @@ -54,6 +68,7 @@ extern "C" { extern FDFSStorePaths g_fdfs_store_paths; //file store paths extern struct base64_context g_fdfs_base64_context; //base64 context +extern BufferInfo g_zero_buffer; //zero buffer for reset typedef int (*stat_func)(const char *filename, struct stat *buf); @@ -84,11 +99,11 @@ typedef struct tagFDFSTrunkFullInfo { FDFSTrunkFileInfo file; } FDFSTrunkFullInfo; -char **storage_load_paths_from_conf_file_ex(IniContext *pItemContext, \ - const char *szSectionName, const bool bUseBasePath, \ - int *path_count, int *err_no); +FDFSStorePathInfo *storage_load_paths_from_conf_file_ex( + IniContext *pItemContext, const char *szSectionName, + const bool bUseBasePath, int *path_count, int *err_no); int storage_load_paths_from_conf_file(IniContext *pItemContext); -void trunk_shared_init(); +int trunk_shared_init(); int storage_split_filename(const char *logic_filename, \ int *filename_len, char *true_filename, char **ppStorePath); diff --git a/storage/trunk_mgr/trunk_sync.c b/storage/trunk_mgr/trunk_sync.c index e359ac1..751d43c 100644 --- a/storage/trunk_mgr/trunk_sync.c +++ b/storage/trunk_mgr/trunk_sync.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //trunk_sync.c @@ -15,6 +15,7 @@ #include #include #include +#include #include #include #include @@ -38,10 +39,12 @@ #include "storage_sync_func.h" #include "trunk_sync.h" -#define TRUNK_SYNC_BINLOG_FILENAME "binlog" +#define TRUNK_SYNC_BINLOG_FILENAME_STR "binlog" +#define TRUNK_SYNC_BINLOG_FILENAME_LEN (sizeof(TRUNK_SYNC_BINLOG_FILENAME_STR) - 1) #define TRUNK_SYNC_BINLOG_ROLLBACK_EXT ".rollback" -#define TRUNK_SYNC_MARK_FILE_EXT ".mark" -#define TRUNK_DIR_NAME "trunk" +#define TRUNK_SYNC_MARK_FILE_EXT_STR ".mark" +#define TRUNK_SYNC_MARK_FILE_EXT_LEN (sizeof(TRUNK_SYNC_MARK_FILE_EXT_STR) - 1) +#define TRUNK_DIR_NAME "trunk" #define MARK_ITEM_BINLOG_FILE_OFFSET "binlog_offset" static int trunk_binlog_fd = -1; @@ -52,8 +55,22 @@ static char *trunk_binlog_write_cache_buff = NULL; static int trunk_binlog_write_cache_len = 0; static int trunk_binlog_write_version = 1; +typedef struct +{ + bool running; + bool reset_binlog_offset; + const FDFSStorageBrief *pStorage; + pthread_t tid; +} TrunkSyncThreadInfo; + +typedef struct +{ + TrunkSyncThreadInfo **thread_data; + int alloc_count; +} TrunkSyncThreadInfoArray; + /* save sync thread ids */ -static pthread_t *trunk_sync_tids = NULL; +static TrunkSyncThreadInfoArray sync_thread_info_array = {NULL, 0}; static int trunk_write_to_mark_file(TrunkBinLogReader *pReader); static int trunk_binlog_fsync_ex(const bool bNeedLock, \ @@ -66,12 +83,12 @@ static int trunk_binlog_preread(TrunkBinLogReader *pReader); char *get_trunk_binlog_filename(char *full_filename) { snprintf(full_filename, MAX_PATH_SIZE, \ - "%s/data/"TRUNK_DIR_NAME"/"TRUNK_SYNC_BINLOG_FILENAME, \ + "%s/data/"TRUNK_DIR_NAME"/"TRUNK_SYNC_BINLOG_FILENAME_STR, \ g_fdfs_base_path); return full_filename; } -static char *get_trunk_rollback_filename(char *full_filename) +static char *get_trunk_binlog_rollback_filename(char *full_filename) { get_trunk_binlog_filename(full_filename); if (strlen(full_filename) + sizeof(TRUNK_SYNC_BINLOG_ROLLBACK_EXT) > @@ -83,6 +100,38 @@ static char *get_trunk_rollback_filename(char *full_filename) return full_filename; } +static char *get_trunk_data_rollback_filename(char *full_filename) +{ + storage_trunk_get_data_filename(full_filename); + if (strlen(full_filename) + sizeof(TRUNK_SYNC_BINLOG_ROLLBACK_EXT) > + MAX_PATH_SIZE) + { + return NULL; + } + strcat(full_filename, TRUNK_SYNC_BINLOG_ROLLBACK_EXT); + return full_filename; +} + +char *get_trunk_binlog_tmp_filename_ex(const char *binlog_filename, + char *tmp_filename) +{ + const char *true_binlog_filename; + char filename[MAX_PATH_SIZE]; + + if (binlog_filename == NULL) + { + get_trunk_binlog_filename(filename); + true_binlog_filename = filename; + } + else + { + true_binlog_filename = binlog_filename; + } + + sprintf(tmp_filename, "%s.tmp", true_binlog_filename); + return tmp_filename; +} + static int trunk_binlog_open_writer(const char *binlog_filename) { trunk_binlog_fd = open(binlog_filename, O_WRONLY | O_CREAT | @@ -199,27 +248,43 @@ int kill_trunk_sync_threads() { int result; int kill_res; + TrunkSyncThreadInfo **thread_info; + TrunkSyncThreadInfo **info_end; - if (trunk_sync_tids == NULL) + if (sync_thread_info_array.thread_data == NULL) { return 0; } if ((result=pthread_mutex_lock(&trunk_sync_thread_lock)) != 0) { - logError("file: "__FILE__", line: %d, " \ - "call pthread_mutex_lock fail, " \ - "errno: %d, error info: %s", \ + logError("file: "__FILE__", line: %d, " + "call pthread_mutex_lock fail, " + "errno: %d, error info: %s", __LINE__, result, STRERROR(result)); } - kill_res = kill_work_threads(trunk_sync_tids, g_trunk_sync_thread_count); + kill_res = 0; + info_end = sync_thread_info_array.thread_data + + sync_thread_info_array.alloc_count; + for (thread_info=sync_thread_info_array.thread_data; + thread_inforunning && (kill_res=pthread_kill( + (*thread_info)->tid, SIGINT)) != 0) + { + logError("file: "__FILE__", line: %d, " + "kill thread failed, " + "errno: %d, error info: %s", + __LINE__, kill_res, STRERROR(kill_res)); + } + } if ((result=pthread_mutex_unlock(&trunk_sync_thread_lock)) != 0) { - logError("file: "__FILE__", line: %d, " \ - "call pthread_mutex_unlock fail, " \ - "errno: %d, error info: %s", \ + logError("file: "__FILE__", line: %d, " + "call pthread_mutex_unlock fail, " + "errno: %d, error info: %s", __LINE__, result, STRERROR(result)); } @@ -231,6 +296,104 @@ int kill_trunk_sync_threads() return kill_res; } +int trunk_sync_notify_thread_reset_offset() +{ + int result; + int i; + int count; + bool done; + TrunkSyncThreadInfo **thread_info; + TrunkSyncThreadInfo **info_end; + + if (sync_thread_info_array.thread_data == NULL) + { + return EINVAL; + } + + if ((result=pthread_mutex_lock(&trunk_sync_thread_lock)) != 0) + { + logError("file: "__FILE__", line: %d, " + "call pthread_mutex_lock fail, " + "errno: %d, error info: %s", + __LINE__, result, STRERROR(result)); + } + + count = 0; + info_end = sync_thread_info_array.thread_data + + sync_thread_info_array.alloc_count; + for (thread_info=sync_thread_info_array.thread_data; + thread_inforunning) + { + (*thread_info)->reset_binlog_offset = true; + count++; + } + } + + if ((result=pthread_mutex_unlock(&trunk_sync_thread_lock)) != 0) + { + logError("file: "__FILE__", line: %d, " + "call pthread_mutex_unlock fail, " + "errno: %d, error info: %s", + __LINE__, result, STRERROR(result)); + } + + logInfo("file: "__FILE__", line: %d, " + "notify %d trunk sync threads to reset offset.", + __LINE__, count); + + done = false; + for (i=0; i<300 && g_continue_flag; i++) + { + info_end = sync_thread_info_array.thread_data + + sync_thread_info_array.alloc_count; + for (thread_info=sync_thread_info_array.thread_data; + thread_inforunning && (*thread_info)->reset_binlog_offset) + { + break; + } + } + + if (thread_info == info_end) + { + done = true; + break; + } + + sleep(1); + } + + if (done) + { + logInfo("file: "__FILE__", line: %d, " + "trunk sync threads reset binlog offset done.", + __LINE__); + return 0; + } + else + { + count = 0; + info_end = sync_thread_info_array.thread_data + + sync_thread_info_array.alloc_count; + for (thread_info=sync_thread_info_array.thread_data; + thread_inforunning && (*thread_info)->reset_binlog_offset) + { + count++; + } + } + + logWarning("file: "__FILE__", line: %d, " + "%d trunk sync threads reset binlog offset timeout.", + __LINE__, count); + return EBUSY; + } +} + int trunk_binlog_sync_func(void *args) { if (trunk_binlog_write_cache_len > 0) @@ -243,99 +406,354 @@ int trunk_binlog_sync_func(void *args) } } +#define BACKUP_FILENAME_LEN (TRUNK_SYNC_BINLOG_FILENAME_LEN + 15) + +typedef struct +{ + char filename[BACKUP_FILENAME_LEN + 1]; +} TrunkBinlogBackupFileInfo; + +typedef struct +{ + TrunkBinlogBackupFileInfo *files; + int count; + int alloc; +} TrunkBinlogBackupFileArray; + +static int trunk_binlog_check_alloc_filename_array( + TrunkBinlogBackupFileArray *file_array) +{ + int bytes; + TrunkBinlogBackupFileInfo *files; + int alloc; + + if (file_array->count < file_array->alloc) + { + return 0; + } + + if (file_array->alloc == 0) + { + alloc = g_trunk_binlog_max_backups + 1; + } + else + { + alloc = file_array->alloc * 2; + } + + bytes = sizeof(TrunkBinlogBackupFileInfo) * alloc; + files = (TrunkBinlogBackupFileInfo *)malloc(bytes); + if (files == NULL) + { + logError("file: "__FILE__", line: %d, " + "malloc %d bytes fail", __LINE__, bytes); + return ENOMEM; + } + + if (file_array->count > 0) + { + memcpy(files, file_array->files, sizeof(TrunkBinlogBackupFileInfo) * + file_array->count); + } + + if (file_array->files != NULL) + { + free(file_array->files); + } + + file_array->files = files; + file_array->alloc = alloc; + return 0; +} + +static int trunk_binlog_compare_filename(const void *p1, const void *p2) +{ + return strcmp(((TrunkBinlogBackupFileInfo *)p1)->filename, + ((TrunkBinlogBackupFileInfo *)p2)->filename); +} + +static int trunk_binlog_delete_overflow_backups() +{ +#define BACKUP_FILENAME_PREFIX_STR TRUNK_SYNC_BINLOG_FILENAME_STR"." +#define BACKUP_FILENAME_PREFIX_LEN (sizeof(BACKUP_FILENAME_PREFIX_STR) - 1) + + int result; + int i; + int over_count; + char file_path[MAX_PATH_SIZE]; + char full_filename[MAX_PATH_SIZE]; + DIR *dir; + struct dirent *ent; + TrunkBinlogBackupFileArray file_array; + + snprintf(file_path, sizeof(file_path), + "%s/data/%s", g_fdfs_base_path, TRUNK_DIR_NAME); + if ((dir=opendir(file_path)) == NULL) + { + result = errno != 0 ? errno : EPERM; + logError("file: "__FILE__", line: %d, " + "call opendir %s fail, errno: %d, error info: %s", + __LINE__, file_path, result, STRERROR(result)); + return result; + } + + result = 0; + file_array.files = NULL; + file_array.count = 0; + file_array.alloc = 0; + while ((ent=readdir(dir)) != NULL) + { + if (strlen(ent->d_name) == BACKUP_FILENAME_LEN && + memcmp(ent->d_name, BACKUP_FILENAME_PREFIX_STR, + BACKUP_FILENAME_PREFIX_LEN) == 0) + { + if ((result=trunk_binlog_check_alloc_filename_array( + &file_array)) != 0) + { + break; + } + + strcpy(file_array.files[file_array.count]. + filename, ent->d_name); + file_array.count++; + } + } + + closedir(dir); + + over_count = (file_array.count - g_trunk_binlog_max_backups) + 1; + if (result != 0 || over_count <= 0) + { + if (file_array.files != NULL) + { + free(file_array.files); + } + return result; + } + + qsort(file_array.files, file_array.count, + sizeof(TrunkBinlogBackupFileInfo), + trunk_binlog_compare_filename); + for (i=0; i 0) - { - if ((result=trunk_binlog_fsync(true)) != 0) - { - return result; - } - } + result = 0; + pthread_mutex_lock(&trunk_sync_thread_lock); + do + { + if (g_trunk_binlog_max_backups > 0) + { + result = trunk_binlog_backup_and_truncate(); + } + else + { + if (trunk_binlog_write_cache_len > 0) + { + if ((result=trunk_binlog_fsync(false)) != 0) + { + break; + } + } + if (ftruncate(trunk_binlog_fd, 0) != 0) + { + result = errno != 0 ? errno : EIO; + logError("file: "__FILE__", line: %d, " + "call ftruncate fail, " + "errno: %d, error info: %s", + __LINE__, result, STRERROR(result)); + break; + } + } + } while (0); - if (ftruncate(trunk_binlog_fd, 0) != 0) - { - result = errno != 0 ? errno : EIO; - logError("file: "__FILE__", line: %d, " \ - "call ftruncate fail, " \ - "errno: %d, error info: %s", \ - __LINE__, result, STRERROR(result)); - return result; - } + pthread_mutex_unlock(&trunk_sync_thread_lock); + if (result == 0) + { + result = storage_delete_trunk_data_file(); + } - return 0; + return result; } -int trunk_binlog_compress_apply() +static int trunk_binlog_delete_rollback_file(const char *filename, + const bool silence) { int result; - char binlog_filename[MAX_PATH_SIZE]; - char rollback_filename[MAX_PATH_SIZE]; + if (access(filename, F_OK) == 0) + { + if (!silence) + { + logWarning("file: "__FILE__", line: %d, " + "rollback file %s exist, delete it!", + __LINE__, filename); + } + if (unlink(filename) != 0) + { + result = errno != 0 ? errno : EPERM; + if (result != ENOENT) + { + logError("file: "__FILE__", line: %d, " + "unlink file %s fail, errno: %d, error info: %s", + __LINE__, filename, result, STRERROR(result)); + return result; + } + } + } + else + { + result = errno != 0 ? errno : EPERM; + if (result != ENOENT) + { + logError("file: "__FILE__", line: %d, " + "access file %s fail, errno: %d, error info: %s", + __LINE__, filename, result, STRERROR(result)); + return result; + } + } - get_trunk_binlog_filename(binlog_filename); - if (get_trunk_rollback_filename(rollback_filename) == NULL) + return 0; +} + +int trunk_binlog_compress_delete_binlog_rollback_file(const bool silence) +{ + char binlog_rollback_filename[MAX_PATH_SIZE]; + + if (get_trunk_binlog_rollback_filename(binlog_rollback_filename) == NULL) { - logError("file: "__FILE__", line: %d, " \ - "filename: %s is too long", - __LINE__, binlog_filename); + logError("file: "__FILE__", line: %d, " + "binlog rollback filename is too long", __LINE__); return ENAMETOOLONG; } - if (trunk_binlog_fd < 0) - { - if (access(binlog_filename, F_OK) == 0) - { - if (rename(binlog_filename, rollback_filename) != 0) - { - result = errno != 0 ? errno : EIO; - logError("file: "__FILE__", line: %d, " \ - "rename %s to %s fail, " \ - "errno: %d, error info: %s", - __LINE__, binlog_filename, - rollback_filename, result, - STRERROR(result)); - return result; - } - } - else if (errno != ENOENT) - { - result = errno != 0 ? errno : EIO; - logError("file: "__FILE__", line: %d, " \ - "call access %s fail, " \ - "errno: %d, error info: %s", - __LINE__, binlog_filename, - result, STRERROR(result)); - return result; - } + return trunk_binlog_delete_rollback_file(binlog_rollback_filename, silence); +} - return 0; - } +int trunk_binlog_compress_delete_rollback_files(const bool silence) +{ + int result; + char data_rollback_filename[MAX_PATH_SIZE]; - if ((result=trunk_binlog_close_writer(true)) != 0) - { - return result; - } + if ((result=trunk_binlog_compress_delete_binlog_rollback_file( + silence)) != 0) + { + return result; + } - if (rename(binlog_filename, rollback_filename) != 0) - { - result = errno != 0 ? errno : EIO; - logError("file: "__FILE__", line: %d, " \ - "rename %s to %s fail, " \ - "errno: %d, error info: %s", - __LINE__, binlog_filename, rollback_filename, - result, STRERROR(result)); - return result; - } + if (get_trunk_data_rollback_filename(data_rollback_filename) == NULL) + { + logError("file: "__FILE__", line: %d, " + "data rollback filename is too long", __LINE__); + return ENAMETOOLONG; + } - if ((result=trunk_binlog_open_writer(binlog_filename)) != 0) - { - rename(rollback_filename, binlog_filename); //rollback - return result; - } + if ((result=trunk_binlog_delete_rollback_file(data_rollback_filename, + silence)) != 0) + { + return result; + } - return 0; + return 0; +} + +static int trunk_binlog_rename_file(const char *src_filename, + const char *dest_filename, const int log_ignore_errno) +{ + int result; + if (access(src_filename, F_OK) == 0) + { + if (rename(src_filename, dest_filename) != 0) + { + result = errno != 0 ? errno : EIO; + logError("file: "__FILE__", line: %d, " + "rename %s to %s fail, " + "errno: %d, error info: %s", + __LINE__, src_filename, + dest_filename, result, + STRERROR(result)); + return result; + } + } + else + { + result = errno != 0 ? errno : EIO; + if (result - log_ignore_errno != 0) + { + logError("file: "__FILE__", line: %d, " + "call access %s fail, " + "errno: %d, error info: %s", + __LINE__, src_filename, + result, STRERROR(result)); + } + + return result; + } + + return 0; } static int trunk_binlog_open_read(const char *filename, @@ -368,7 +786,7 @@ static int trunk_binlog_open_read(const char *filename, return fd; } -static int trunk_binlog_merge_file(int old_fd) +static int trunk_binlog_merge_file(int old_fd, const int stage) { int result; int tmp_fd; @@ -377,19 +795,19 @@ static int trunk_binlog_merge_file(int old_fd) char tmp_filename[MAX_PATH_SIZE]; char buff[64 * 1024]; - get_trunk_binlog_filename(binlog_filename); - sprintf(tmp_filename, "%s.tmp", binlog_filename); + get_trunk_binlog_filename(binlog_filename); + get_trunk_binlog_tmp_filename_ex(binlog_filename, tmp_filename); tmp_fd = open(tmp_filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); if (tmp_fd < 0) { result = errno != 0 ? errno : EACCES; - logError("file: "__FILE__", line: %d, " \ - "open file \"%s\" fail, " \ - "errno: %d, error info: %s", \ + logError("file: "__FILE__", line: %d, " + "open file \"%s\" fail, " + "errno: %d, error info: %s", __LINE__, tmp_filename, result, STRERROR(result)); return result; } - + while ((bytes=fc_safe_read(old_fd, buff, sizeof(buff))) > 0) { if (fc_safe_write(tmp_fd, buff, bytes) != bytes) @@ -446,6 +864,9 @@ static int trunk_binlog_merge_file(int old_fd) } close(tmp_fd); + g_trunk_binlog_compress_stage = stage; + storage_write_to_sync_ini_file(); + if (rename(tmp_filename, binlog_filename) != 0) { result = errno != 0 ? errno : EPERM; @@ -460,6 +881,269 @@ static int trunk_binlog_merge_file(int old_fd) return 0; } +static int trunk_compress_rollback_data_file() +{ + int result; + char data_filename[MAX_PATH_SIZE]; + char data_rollback_filename[MAX_PATH_SIZE]; + struct stat fs; + + storage_trunk_get_data_filename(data_filename); + get_trunk_data_rollback_filename(data_rollback_filename); + + if (stat(data_rollback_filename, &fs) != 0) + { + result = errno != 0 ? errno : EPERM; + if (result == ENOENT) + { + return 0; + } + + logError("file: "__FILE__", line: %d, " + "stat file %s fail, errno: %d, error info: %s", + __LINE__, data_rollback_filename, + result, STRERROR(result)); + return result; + } + + if (unlink(data_filename) != 0) + { + result = errno != 0 ? errno : EPERM; + if (result != ENOENT) + { + logError("file: "__FILE__", line: %d, " + "unlink %s fail, errno: %d, error info: %s", + __LINE__, data_filename, result, STRERROR(result)); + return result; + } + } + + if (fs.st_size == 0) + { + unlink(data_rollback_filename); //delete zero file directly + return 0; + } + + if (rename(data_rollback_filename, data_filename) != 0) + { + result = errno != 0 ? errno : EPERM; + if (result == ENOENT) + { + return 0; + } + + logError("file: "__FILE__", line: %d, " + "rename file %s to %s fail, " + "errno: %d, error info: %s", + __LINE__, data_rollback_filename, + data_filename, result, STRERROR(result)); + return result; + } + + return 0; +} + +static int trunk_compress_rollback_binlog_file(const char *binlog_filename) +{ + int result; + int rollback_fd; + char binlog_rollback_filename[MAX_PATH_SIZE]; + struct stat fs; + + get_trunk_binlog_rollback_filename(binlog_rollback_filename); + if (stat(binlog_rollback_filename, &fs) != 0) + { + result = errno != 0 ? errno : ENOENT; + if (result == ENOENT) + { + return 0; + } + logError("file: "__FILE__", line: %d, " + "stat file %s fail, errno: %d, error info: %s", + __LINE__, binlog_rollback_filename, + result, STRERROR(result)); + return result; + } + + if (fs.st_size == 0) + { + unlink(binlog_rollback_filename); //delete zero file directly + return 0; + } + + if (access(binlog_filename, F_OK) != 0) + { + result = errno != 0 ? errno : EPERM; + if (result == ENOENT) + { + if (rename(binlog_rollback_filename, binlog_filename) != 0) + { + result = errno != 0 ? errno : EPERM; + if (result != ENOENT) + { + logError("file: "__FILE__", line: %d, " + "rename file %s to %s fail, " + "errno: %d, error info: %s", + __LINE__, binlog_rollback_filename, + binlog_filename, errno, STRERROR(errno)); + return result; + } + } + + return 0; + } + else + { + logError("file: "__FILE__", line: %d, " + "access file %s fail, errno: %d, error info: %s", + __LINE__, binlog_filename, errno, STRERROR(errno)); + return result; + } + } + + if ((rollback_fd=trunk_binlog_open_read(binlog_rollback_filename, + false)) < 0) + { + result = errno != 0 ? errno : EPERM; + if (result == ENOENT) + { + return 0; + } + + return result; + } + + result = trunk_binlog_merge_file(rollback_fd, + STORAGE_TRUNK_COMPRESS_STAGE_ROLLBACK_MERGING); + close(rollback_fd); + + g_trunk_binlog_compress_stage = + STORAGE_TRUNK_COMPRESS_STAGE_ROLLBACK_MERGE_DONE; + storage_write_to_sync_ini_file(); + + if (unlink(binlog_rollback_filename) != 0) + { + logWarning("file: "__FILE__", line: %d, " + "unlink %s fail, errno: %d, error info: %s", + __LINE__, binlog_rollback_filename, + errno, STRERROR(errno)); + } + + return result; +} + +int trunk_binlog_compress_delete_temp_files_after_commit() +{ + int result; + char data_filename[MAX_PATH_SIZE]; + + storage_trunk_get_data_filename(data_filename); + if (unlink(data_filename) != 0) + { + result = errno != 0 ? errno : ENOENT; + logError("file: "__FILE__", line: %d, " + "unlink %s fail, errno: %d, error info: %s", + __LINE__, data_filename, + result, STRERROR(result)); + if (result != ENOENT) + { + return result; + } + } + + return trunk_binlog_compress_delete_rollback_files(true); +} + +int trunk_binlog_compress_apply() +{ + int result; + int open_res; + bool need_open_binlog; + char binlog_filename[MAX_PATH_SIZE]; + char data_filename[MAX_PATH_SIZE]; + char binlog_rollback_filename[MAX_PATH_SIZE]; + char data_rollback_filename[MAX_PATH_SIZE]; + + get_trunk_binlog_filename(binlog_filename); + if (get_trunk_binlog_rollback_filename(binlog_rollback_filename) == NULL) + { + logError("file: "__FILE__", line: %d, " + "filename: %s is too long", + __LINE__, binlog_filename); + return ENAMETOOLONG; + } + + storage_trunk_get_data_filename(data_filename); + if (get_trunk_data_rollback_filename(data_rollback_filename) == NULL) + { + logError("file: "__FILE__", line: %d, " + "data rollback filename is too long", __LINE__); + return ENAMETOOLONG; + } + + if (access(binlog_filename, F_OK) != 0) + { + result = errno != 0 ? errno : EPERM; + logError("file: "__FILE__", line: %d, " + "access file: %s is fail, " + "errno: %d, error info: %s", + __LINE__, binlog_filename, + result, STRERROR(result)); + return result; + } + + need_open_binlog = trunk_binlog_fd >= 0; + + pthread_mutex_lock(&trunk_sync_thread_lock); + if (need_open_binlog) + { + trunk_binlog_close_writer(false); + } + + do + { + result = trunk_binlog_rename_file(data_filename, + data_rollback_filename, ENOENT); + if (result != 0) + { + if (result == ENOENT) + { + result = writeToFile(data_rollback_filename, "", 0); + } + + if (result != 0) + { + break; + } + } + + if ((result=trunk_binlog_rename_file(binlog_filename, + binlog_rollback_filename, 0)) != 0) + { + trunk_compress_rollback_data_file(); + break; + } + } while (0); + + if (need_open_binlog) + { + if ((open_res=trunk_binlog_open_writer(binlog_filename)) != 0) + { + trunk_binlog_rename_file(binlog_rollback_filename, + binlog_filename, 0); //rollback + trunk_compress_rollback_data_file(); + + if (result == 0) + { + result = open_res; + } + } + } + + pthread_mutex_unlock(&trunk_sync_thread_lock); + return result; +} + int trunk_binlog_compress_commit() { int result; @@ -467,7 +1151,6 @@ int trunk_binlog_compress_commit() bool need_open_binlog; char binlog_filename[MAX_PATH_SIZE]; char data_filename[MAX_PATH_SIZE]; - char rollback_filename[MAX_PATH_SIZE]; need_open_binlog = trunk_binlog_fd >= 0; get_trunk_binlog_filename(binlog_filename); @@ -478,133 +1161,98 @@ int trunk_binlog_compress_commit() return errno != 0 ? errno : ENOENT; } + pthread_mutex_lock(&trunk_sync_thread_lock); if (need_open_binlog) { - trunk_binlog_close_writer(true); + trunk_binlog_close_writer(false); } - result = trunk_binlog_merge_file(data_fd); - close(data_fd); - if (result != 0) - { - return result; - } - if (unlink(data_filename) != 0) - { - result = errno != 0 ? errno : EPERM; - logError("file: "__FILE__", line: %d, " \ - "unlink %s fail, errno: %d, error info: %s", - __LINE__, data_filename, - result, STRERROR(result)); - return result; - } + do + { + result = trunk_binlog_merge_file(data_fd, + STORAGE_TRUNK_COMPRESS_STAGE_COMMIT_MERGING); + close(data_fd); + if (result != 0) + { + break; + } - get_trunk_rollback_filename(rollback_filename); - if (access(rollback_filename, F_OK) == 0) - { - if (unlink(rollback_filename) != 0) - { - result = errno != 0 ? errno : EPERM; - logWarning("file: "__FILE__", line: %d, " \ - "unlink %s fail, errno: %d, error info: %s", - __LINE__, rollback_filename, - result, STRERROR(result)); - } - } + g_trunk_binlog_compress_stage = + STORAGE_TRUNK_COMPRESS_STAGE_COMMIT_MERGE_DONE; + storage_write_to_sync_ini_file(); + if ((result=trunk_binlog_compress_delete_temp_files_after_commit()) != 0) + { + break; + } + + g_trunk_binlog_compress_stage = + STORAGE_TRUNK_COMPRESS_STAGE_COMPRESS_SUCCESS; + storage_write_to_sync_ini_file(); + + if (need_open_binlog) + { + result = trunk_binlog_open_writer(binlog_filename); + } + } while (0); + + pthread_mutex_unlock(&trunk_sync_thread_lock); + + return result; +} + +static int do_compress_rollback() +{ + int result; + bool need_open_binlog; + char binlog_filename[MAX_PATH_SIZE]; + + need_open_binlog = trunk_binlog_fd >= 0; + get_trunk_binlog_filename(binlog_filename); + + pthread_mutex_lock(&trunk_sync_thread_lock); if (need_open_binlog) { - return trunk_binlog_open_writer(binlog_filename); + trunk_binlog_close_writer(false); } - return 0; + do + { + if ((result=trunk_compress_rollback_binlog_file(binlog_filename)) != 0) + { + break; + } + + if ((result=trunk_compress_rollback_data_file()) != 0) + { + break; + } + + if (need_open_binlog) + { + result = trunk_binlog_open_writer(binlog_filename); + } + } while (0); + + pthread_mutex_unlock(&trunk_sync_thread_lock); + return result; } int trunk_binlog_compress_rollback() { - int result; - int rollback_fd; - char binlog_filename[MAX_PATH_SIZE]; - char rollback_filename[MAX_PATH_SIZE]; - struct stat fs; + int result; - get_trunk_binlog_filename(binlog_filename); - get_trunk_rollback_filename(rollback_filename); - if (trunk_binlog_fd < 0) - { - if (access(rollback_filename, F_OK) == 0) - { - if (rename(rollback_filename, binlog_filename) != 0) - { - result = errno != 0 ? errno : EPERM; - logError("file: "__FILE__", line: %d, "\ - "rename %s to %s fail, " \ - "errno: %d, error info: %s", - __LINE__, rollback_filename, - binlog_filename, result, - STRERROR(result)); - return result; - } - } + if ((result=do_compress_rollback()) == 0) + { + g_trunk_binlog_compress_stage = + STORAGE_TRUNK_COMPRESS_STAGE_FINISHED; + storage_write_to_sync_ini_file(); + } - return 0; - } - - if (stat(rollback_filename, &fs) != 0) - { - result = errno != 0 ? errno : ENOENT; - if (result == ENOENT) - { - return 0; - } - logError("file: "__FILE__", line: %d, " \ - "stat file %s fail, errno: %d, error info: %s", - __LINE__, rollback_filename, - result, STRERROR(result)); - return result; - } - - if (fs.st_size == 0) - { - unlink(rollback_filename); //delete zero file directly - return 0; - } - - if ((result=trunk_binlog_close_writer(true)) != 0) - { - return result; - } - - if ((rollback_fd=trunk_binlog_open_read(rollback_filename, - false)) < 0) - { - return errno != 0 ? errno : ENOENT; - } - - result = trunk_binlog_merge_file(rollback_fd); - close(rollback_fd); - if (result == 0) - { - if (unlink(rollback_filename) != 0) - { - result = errno != 0 ? errno : EPERM; - logWarning("file: "__FILE__", line: %d, " \ - "unlink %s fail, " \ - "errno: %d, error info: %s", - __LINE__, rollback_filename, - result, STRERROR(result)); - } - - return trunk_binlog_open_writer(binlog_filename); - } - else - { - trunk_binlog_open_writer(binlog_filename); - return result; - } + return result; } -static int trunk_binlog_fsync_ex(const bool bNeedLock, \ +static int trunk_binlog_fsync_ex(const bool bNeedLock, const char *buff, int *length) { int result; @@ -613,9 +1261,9 @@ static int trunk_binlog_fsync_ex(const bool bNeedLock, \ if (bNeedLock && (result=pthread_mutex_lock(&trunk_sync_thread_lock)) != 0) { - logError("file: "__FILE__", line: %d, " \ - "call pthread_mutex_lock fail, " \ - "errno: %d, error info: %s", \ + logError("file: "__FILE__", line: %d, " + "call pthread_mutex_lock fail, " + "errno: %d, error info: %s", __LINE__, result, STRERROR(result)); } @@ -626,19 +1274,19 @@ static int trunk_binlog_fsync_ex(const bool bNeedLock, \ else if (fc_safe_write(trunk_binlog_fd, buff, *length) != *length) { write_ret = errno != 0 ? errno : EIO; - logError("file: "__FILE__", line: %d, " \ - "write to binlog file \"%s\" fail, fd=%d, " \ - "errno: %d, error info: %s", \ - __LINE__, get_trunk_binlog_filename(full_filename), \ + logError("file: "__FILE__", line: %d, " + "write to binlog file \"%s\" fail, fd=%d, " + "errno: %d, error info: %s", + __LINE__, get_trunk_binlog_filename(full_filename), trunk_binlog_fd, errno, STRERROR(errno)); } else if (fsync(trunk_binlog_fd) != 0) { write_ret = errno != 0 ? errno : EIO; - logError("file: "__FILE__", line: %d, " \ - "sync to binlog file \"%s\" fail, " \ - "errno: %d, error info: %s", \ - __LINE__, get_trunk_binlog_filename(full_filename), \ + logError("file: "__FILE__", line: %d, " + "sync to binlog file \"%s\" fail, " + "errno: %d, error info: %s", + __LINE__, get_trunk_binlog_filename(full_filename), errno, STRERROR(errno)); } else @@ -654,15 +1302,22 @@ static int trunk_binlog_fsync_ex(const bool bNeedLock, \ if (bNeedLock && (result=pthread_mutex_unlock(&trunk_sync_thread_lock)) != 0) { - logError("file: "__FILE__", line: %d, " \ - "call pthread_mutex_unlock fail, " \ - "errno: %d, error info: %s", \ + logError("file: "__FILE__", line: %d, " + "call pthread_mutex_unlock fail, " + "errno: %d, error info: %s", __LINE__, result, STRERROR(result)); } return write_ret; } +int trunk_binlog_flush(const bool bNeedLock) +{ + return trunk_binlog_fsync_ex(bNeedLock, + trunk_binlog_write_cache_buff, + (&trunk_binlog_write_cache_len)); +} + int trunk_binlog_write(const int timestamp, const char op_type, \ const FDFSTrunkFullInfo *pTrunk) { @@ -679,7 +1334,7 @@ int trunk_binlog_write(const int timestamp, const char op_type, \ trunk_binlog_write_cache_len += sprintf(trunk_binlog_write_cache_buff + \ trunk_binlog_write_cache_len, \ - "%d %c %d %d %d %d %d %d\n", \ + "%d %c %d %d %d %u %d %d\n", \ timestamp, op_type, \ pTrunk->path.store_path_index, \ pTrunk->path.sub_path_high, \ @@ -768,7 +1423,7 @@ int trunk_binlog_write_buffer(const char *buff, const int length) return write_ret; } -static char *get_binlog_readable_filename(const void *pArg, \ +static char *get_binlog_readable_filename(const void *pArg, char *full_filename) { static char buff[MAX_PATH_SIZE]; @@ -779,7 +1434,7 @@ static char *get_binlog_readable_filename(const void *pArg, \ } snprintf(full_filename, MAX_PATH_SIZE, - "%s/data/"TRUNK_DIR_NAME"/"TRUNK_SYNC_BINLOG_FILENAME, \ + "%s/data/"TRUNK_DIR_NAME"/"TRUNK_SYNC_BINLOG_FILENAME_STR, g_fdfs_base_path); return full_filename; } @@ -788,6 +1443,7 @@ int trunk_open_readable_binlog(TrunkBinLogReader *pReader, \ get_filename_func filename_func, const void *pArg) { char full_filename[MAX_PATH_SIZE]; + struct stat file_stat; if (pReader->binlog_fd >= 0) { @@ -798,14 +1454,34 @@ int trunk_open_readable_binlog(TrunkBinLogReader *pReader, \ pReader->binlog_fd = open(full_filename, O_RDONLY); if (pReader->binlog_fd < 0) { - logError("file: "__FILE__", line: %d, " \ - "open binlog file \"%s\" fail, " \ - "errno: %d, error info: %s", \ - __LINE__, full_filename, \ + logError("file: "__FILE__", line: %d, " + "open binlog file \"%s\" fail, " + "errno: %d, error info: %s", + __LINE__, full_filename, errno, STRERROR(errno)); return errno != 0 ? errno : ENOENT; } + if (fstat(pReader->binlog_fd, &file_stat) != 0) + { + logError("file: "__FILE__", line: %d, " + "stat binlog file \"%s\" fail, " + "errno: %d, error info: %s", + __LINE__, full_filename, + errno, STRERROR(errno)); + return errno != 0 ? errno : ENOENT; + } + + if (pReader->binlog_offset > file_stat.st_size) + { + logWarning("file: "__FILE__", line: %d, " + "binlog file \"%s\", binlog_offset: %"PRId64 + " > file size: %"PRId64", set binlog_offset to 0", + __LINE__, full_filename, pReader->binlog_offset, + (int64_t)file_stat.st_size); + pReader->binlog_offset = 0; + } + if (pReader->binlog_offset > 0 && \ lseek(pReader->binlog_fd, pReader->binlog_offset, SEEK_SET) < 0) { @@ -830,13 +1506,13 @@ static char *trunk_get_mark_filename_by_id_and_port(const char *storage_id, \ { snprintf(full_filename, filename_size, \ "%s/data/"TRUNK_DIR_NAME"/%s%s", g_fdfs_base_path, \ - storage_id, TRUNK_SYNC_MARK_FILE_EXT); + storage_id, TRUNK_SYNC_MARK_FILE_EXT_STR); } else { snprintf(full_filename, filename_size, \ "%s/data/"TRUNK_DIR_NAME"/%s_%d%s", g_fdfs_base_path, \ - storage_id, port, TRUNK_SYNC_MARK_FILE_EXT); + storage_id, port, TRUNK_SYNC_MARK_FILE_EXT_STR); } return full_filename; @@ -847,7 +1523,7 @@ static char *trunk_get_mark_filename_by_ip_and_port(const char *ip_addr, \ { snprintf(full_filename, filename_size, \ "%s/data/"TRUNK_DIR_NAME"/%s_%d%s", g_fdfs_base_path, \ - ip_addr, port, TRUNK_SYNC_MARK_FILE_EXT); + ip_addr, port, TRUNK_SYNC_MARK_FILE_EXT_STR); return full_filename; } @@ -874,9 +1550,9 @@ static char *trunk_get_mark_filename_by_id(const char *storage_id, full_filename, filename_size); } -int trunk_reader_init(FDFSStorageBrief *pStorage, TrunkBinLogReader *pReader) +int trunk_reader_init(const FDFSStorageBrief *pStorage, + TrunkBinLogReader *pReader, const bool reset_binlog_offset) { - char full_filename[MAX_PATH_SIZE]; IniContext iniContext; int result; int64_t saved_binlog_offset; @@ -885,7 +1561,6 @@ int trunk_reader_init(FDFSStorageBrief *pStorage, TrunkBinLogReader *pReader) saved_binlog_offset = pReader->binlog_offset; memset(pReader, 0, sizeof(TrunkBinLogReader)); - pReader->mark_fd = -1; pReader->binlog_fd = -1; pReader->binlog_buff.buffer = (char *)malloc( \ @@ -909,7 +1584,7 @@ int trunk_reader_init(FDFSStorageBrief *pStorage, TrunkBinLogReader *pReader) { strcpy(pReader->storage_id, pStorage->id); } - trunk_mark_filename_by_reader(pReader, full_filename); + trunk_mark_filename_by_reader(pReader, pReader->mark_filename); if (pStorage == NULL) { @@ -918,22 +1593,23 @@ int trunk_reader_init(FDFSStorageBrief *pStorage, TrunkBinLogReader *pReader) } else { - bFileExist = fileExists(full_filename); + bFileExist = fileExists(pReader->mark_filename); if (!bFileExist && (g_use_storage_id && pStorage != NULL)) { char old_mark_filename[MAX_PATH_SIZE]; - trunk_get_mark_filename_by_ip_and_port( \ - pStorage->ip_addr, g_server_port, \ + trunk_get_mark_filename_by_ip_and_port( + pStorage->ip_addr, g_server_port, old_mark_filename, sizeof(old_mark_filename)); if (fileExists(old_mark_filename)) { - if (rename(old_mark_filename, full_filename)!=0) + if (rename(old_mark_filename, + pReader->mark_filename) != 0) { - logError("file: "__FILE__", line: %d, "\ - "rename file %s to %s fail" \ - ", errno: %d, error info: %s", \ - __LINE__, old_mark_filename, \ - full_filename, errno, \ + logError("file: "__FILE__", line: %d, " + "rename file %s to %s fail, " + "errno: %d, error info: %s", + __LINE__, old_mark_filename, + pReader->mark_filename, errno, STRERROR(errno)); return errno != 0 ? errno : EACCES; } @@ -945,35 +1621,36 @@ int trunk_reader_init(FDFSStorageBrief *pStorage, TrunkBinLogReader *pReader) if (bFileExist) { memset(&iniContext, 0, sizeof(IniContext)); - if ((result=iniLoadFromFile(full_filename, &iniContext)) \ - != 0) + if ((result=iniLoadFromFile(pReader->mark_filename, + &iniContext)) != 0) { - logError("file: "__FILE__", line: %d, " \ - "load from mark file \"%s\" fail, " \ - "error code: %d", \ - __LINE__, full_filename, result); + logError("file: "__FILE__", line: %d, " + "load from mark file \"%s\" fail, " + "error code: %d", __LINE__, + pReader->mark_filename, result); return result; } if (iniContext.global.count < 1) { iniFreeContext(&iniContext); - logError("file: "__FILE__", line: %d, " \ - "in mark file \"%s\", item count: %d < 7", \ - __LINE__, full_filename, iniContext.global.count); + logError("file: "__FILE__", line: %d, " + "in mark file \"%s\", item count: %d < 1", + __LINE__, pReader->mark_filename, + iniContext.global.count); return ENOENT; } - pReader->binlog_offset = iniGetInt64Value(NULL, \ - MARK_ITEM_BINLOG_FILE_OFFSET, \ + pReader->binlog_offset = iniGetInt64Value(NULL, + MARK_ITEM_BINLOG_FILE_OFFSET, &iniContext, -1); if (pReader->binlog_offset < 0) { iniFreeContext(&iniContext); - logError("file: "__FILE__", line: %d, " \ - "in mark file \"%s\", binlog_offset: "\ - "%"PRId64" < 0", \ - __LINE__, full_filename, \ + logError("file: "__FILE__", line: %d, " + "in mark file \"%s\", binlog_offset: " + "%"PRId64" < 0", __LINE__, + pReader->mark_filename, pReader->binlog_offset); return EINVAL; } @@ -982,18 +1659,6 @@ int trunk_reader_init(FDFSStorageBrief *pStorage, TrunkBinLogReader *pReader) } pReader->last_binlog_offset = pReader->binlog_offset; - - pReader->mark_fd = open(full_filename, O_WRONLY | O_CREAT, 0644); - if (pReader->mark_fd < 0) - { - logError("file: "__FILE__", line: %d, " \ - "open mark file \"%s\" fail, " \ - "error no: %d, error info: %s", \ - __LINE__, full_filename, \ - errno, STRERROR(errno)); - return errno != 0 ? errno : ENOENT; - } - if (!bFileExist && pStorage != NULL) { if ((result=trunk_write_to_mark_file(pReader)) != 0) @@ -1002,7 +1667,13 @@ int trunk_reader_init(FDFSStorageBrief *pStorage, TrunkBinLogReader *pReader) } } - if ((result=trunk_open_readable_binlog(pReader, \ + if (reset_binlog_offset && pReader->binlog_offset > 0) + { + pReader->binlog_offset = 0; + trunk_write_to_mark_file(pReader); + } + + if ((result=trunk_open_readable_binlog(pReader, get_binlog_readable_filename, pReader)) != 0) { return result; @@ -1019,12 +1690,6 @@ int trunk_reader_init(FDFSStorageBrief *pStorage, TrunkBinLogReader *pReader) void trunk_reader_destroy(TrunkBinLogReader *pReader) { - if (pReader->mark_fd >= 0) - { - close(pReader->mark_fd); - pReader->mark_fd = -1; - } - if (pReader->binlog_fd >= 0) { close(pReader->binlog_fd); @@ -1046,15 +1711,15 @@ static int trunk_write_to_mark_file(TrunkBinLogReader *pReader) int len; int result; - len = sprintf(buff, \ - "%s=%"PRId64"\n", \ + len = sprintf(buff, + "%s=%"PRId64"\n", MARK_ITEM_BINLOG_FILE_OFFSET, pReader->binlog_offset); - if ((result=storage_write_to_fd(pReader->mark_fd, \ - trunk_mark_filename_by_reader, pReader, buff, len)) == 0) - { + if ((result=safeWriteToFile(pReader->mark_filename, buff, len)) == 0) + { + STORAGE_CHOWN(pReader->mark_filename, geteuid(), getegid()) pReader->last_binlog_offset = pReader->binlog_offset; - } + } return result; } @@ -1064,7 +1729,7 @@ static int trunk_binlog_preread(TrunkBinLogReader *pReader) int bytes_read; int saved_trunk_binlog_write_version; - if (pReader->binlog_buff.version == trunk_binlog_write_version && \ + if (pReader->binlog_buff.version == trunk_binlog_write_version && pReader->binlog_buff.length == 0) { return ENOENT; @@ -1221,23 +1886,23 @@ int trunk_unlink_mark_file(const char *storage_id) t = g_current_time; localtime_r(&t, &tm); - trunk_get_mark_filename_by_id(storage_id, old_filename, \ + trunk_get_mark_filename_by_id(storage_id, old_filename, sizeof(old_filename)); if (!fileExists(old_filename)) { return ENOENT; } - snprintf(new_filename, sizeof(new_filename), \ - "%s.%04d%02d%02d%02d%02d%02d", old_filename, \ - tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, \ + snprintf(new_filename, sizeof(new_filename), + "%s.%04d%02d%02d%02d%02d%02d", old_filename, + tm.tm_year+1900, tm.tm_mon+1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec); if (rename(old_filename, new_filename) != 0) { - logError("file: "__FILE__", line: %d, " \ - "rename file %s to %s fail" \ - ", errno: %d, error info: %s", \ - __LINE__, old_filename, new_filename, \ + logError("file: "__FILE__", line: %d, " + "rename file %s to %s fail, " + "errno: %d, error info: %s", + __LINE__, old_filename, new_filename, errno, STRERROR(errno)); return errno != 0 ? errno : EACCES; } @@ -1282,48 +1947,33 @@ int trunk_rename_mark_file(const char *old_ip_addr, const int old_port, \ return 0; } -static void trunk_sync_thread_exit(ConnectionInfo *pStorage) +static void trunk_sync_thread_exit(TrunkSyncThreadInfo *thread_data, + const int port) { int result; - int i; - pthread_t tid; if ((result=pthread_mutex_lock(&trunk_sync_thread_lock)) != 0) { - logError("file: "__FILE__", line: %d, " \ - "call pthread_mutex_lock fail, " \ - "errno: %d, error info: %s", \ + logError("file: "__FILE__", line: %d, " + "call pthread_mutex_lock fail, " + "errno: %d, error info: %s", __LINE__, result, STRERROR(result)); } - - tid = pthread_self(); - for (i=0; irunning = false; g_trunk_sync_thread_count--; if ((result=pthread_mutex_unlock(&trunk_sync_thread_lock)) != 0) { - logError("file: "__FILE__", line: %d, " \ - "call pthread_mutex_unlock fail, " \ - "errno: %d, error info: %s", \ + logError("file: "__FILE__", line: %d, " + "call pthread_mutex_unlock fail, " + "errno: %d, error info: %s", __LINE__, result, STRERROR(result)); } - logInfo("file: "__FILE__", line: %d, " \ - "trunk sync thread to storage server %s:%d exit", - __LINE__, pStorage->ip_addr, pStorage->port); + logInfo("file: "__FILE__", line: %d, " + "trunk sync thread to storage server %s:%d exit", + __LINE__, thread_data->pStorage->ip_addr, port); } static int trunk_sync_data(TrunkBinLogReader *pReader, \ @@ -1398,9 +2048,10 @@ static int trunk_sync_data(TrunkBinLogReader *pReader, \ return 0; } -static void* trunk_sync_thread_entrance(void* arg) +static void *trunk_sync_thread_entrance(void* arg) { - FDFSStorageBrief *pStorage; + TrunkSyncThreadInfo *thread_data; + const FDFSStorageBrief *pStorage; TrunkBinLogReader reader; ConnectionInfo storage_server; char local_ip_addr[IP_ADDRESS_SIZE]; @@ -1412,13 +2063,13 @@ static void* trunk_sync_thread_entrance(void* arg) memset(local_ip_addr, 0, sizeof(local_ip_addr)); memset(&reader, 0, sizeof(reader)); - reader.mark_fd = -1; reader.binlog_fd = -1; current_time = g_current_time; last_keep_alive_time = 0; - pStorage = (FDFSStorageBrief *)arg; + thread_data = (TrunkSyncThreadInfo *)arg; + pStorage = thread_data->pStorage; strcpy(storage_server.ip_addr, pStorage->ip_addr); storage_server.port = g_server_port; @@ -1449,12 +2100,12 @@ static void* trunk_sync_thread_entrance(void* arg) break; } - if ((result=trunk_reader_init(pStorage, &reader)) != 0) + if ((result=trunk_reader_init(pStorage, &reader, + thread_data->reset_binlog_offset)) != 0) { - logCrit("file: "__FILE__", line: %d, " \ - "trunk_reader_init fail, errno=%d, " \ - "program exit!", \ - __LINE__, result); + logCrit("file: "__FILE__", line: %d, " + "trunk_reader_init fail, errno=%d, " + "program exit!", __LINE__, result); g_continue_flag = false; break; } @@ -1470,7 +2121,8 @@ static void* trunk_sync_thread_entrance(void* arg) __LINE__, pStorage->ip_addr, local_ip_addr); */ - if (is_local_host_ip(pStorage->ip_addr)) + if ((strcmp(pStorage->id, g_my_server_id_str) == 0) || + is_local_host_ip(pStorage->ip_addr)) { //can't self sync to self logError("file: "__FILE__", line: %d, " \ "ip_addr %s belong to the local host," \ @@ -1481,6 +2133,16 @@ static void* trunk_sync_thread_entrance(void* arg) break; } + if (thread_data->reset_binlog_offset) + { + thread_data->reset_binlog_offset = false; + if (reader.binlog_offset > 0) + { + reader.binlog_offset = 0; + trunk_write_to_mark_file(&reader); + } + } + if (reader.binlog_offset == 0) { if ((result=fdfs_deal_no_body_cmd(&storage_server, \ @@ -1498,21 +2160,21 @@ static void* trunk_sync_thread_entrance(void* arg) } sync_result = 0; - while (g_continue_flag && \ - pStorage->status != FDFS_STORAGE_STATUS_DELETED && \ - pStorage->status != FDFS_STORAGE_STATUS_IP_CHANGED && \ + while (g_continue_flag && !thread_data->reset_binlog_offset && + pStorage->status != FDFS_STORAGE_STATUS_DELETED && + pStorage->status != FDFS_STORAGE_STATUS_IP_CHANGED && pStorage->status != FDFS_STORAGE_STATUS_NONE) { read_result = trunk_binlog_preread(&reader); if (read_result == ENOENT) { - if (reader.last_binlog_offset != \ + if (reader.last_binlog_offset != reader.binlog_offset) { if (trunk_write_to_mark_file(&reader)!=0) { - logCrit("file: "__FILE__", line: %d, " \ - "trunk_write_to_mark_file fail, " \ + logCrit("file: "__FILE__", line: %d, " + "trunk_write_to_mark_file fail, " "program exit!", __LINE__); g_continue_flag = false; break; @@ -1591,7 +2253,7 @@ static void* trunk_sync_thread_entrance(void* arg) } trunk_reader_destroy(&reader); - trunk_sync_thread_exit(&storage_server); + trunk_sync_thread_exit(thread_data, storage_server.port); return NULL; } @@ -1617,20 +2279,107 @@ int trunk_sync_thread_start_all() return result; } +TrunkSyncThreadInfo *trunk_sync_alloc_thread_data() +{ + TrunkSyncThreadInfo **thread_info; + TrunkSyncThreadInfo **info_end; + TrunkSyncThreadInfo **old_thread_data; + TrunkSyncThreadInfo **new_thread_data; + TrunkSyncThreadInfo **new_data_start; + int alloc_count; + int bytes; + + if (g_trunk_sync_thread_count + 1 < sync_thread_info_array.alloc_count) + { + info_end = sync_thread_info_array.thread_data + + sync_thread_info_array.alloc_count; + for (thread_info=sync_thread_info_array.thread_data; + thread_inforunning) + { + return *thread_info; + } + } + } + + if (sync_thread_info_array.alloc_count == 0) + { + alloc_count = 1; + } + else + { + alloc_count = sync_thread_info_array.alloc_count * 2; + } + + bytes = sizeof(TrunkSyncThreadInfo *) * alloc_count; + new_thread_data = (TrunkSyncThreadInfo **)malloc(bytes); + if (new_thread_data == NULL) + { + logError("file: "__FILE__", line: %d, " + "malloc %d bytes fail, " + "errno: %d, error info: %s", + __LINE__, bytes, errno, STRERROR(errno)); + return NULL; + } + + logInfo("file: "__FILE__", line: %d, " + "alloc %d thread data entries", + __LINE__, alloc_count); + + if (sync_thread_info_array.alloc_count > 0) + { + memcpy(new_thread_data, sync_thread_info_array.thread_data, + sizeof(TrunkSyncThreadInfo *) * + sync_thread_info_array.alloc_count); + } + + new_data_start = new_thread_data + sync_thread_info_array.alloc_count; + info_end = new_thread_data + alloc_count; + for (thread_info=new_data_start; thread_infostatus == FDFS_STORAGE_STATUS_DELETED || \ - pStorage->status == FDFS_STORAGE_STATUS_IP_CHANGED || \ + if (pStorage->status == FDFS_STORAGE_STATUS_DELETED || + pStorage->status == FDFS_STORAGE_STATUS_IP_CHANGED || pStorage->status == FDFS_STORAGE_STATUS_NONE) { return 0; } - if (is_local_host_ip(pStorage->ip_addr)) //can't self sync to self + if ((strcmp(pStorage->id, g_my_server_id_str) == 0) || + is_local_host_ip(pStorage->ip_addr)) //can't self sync to self { return 0; } @@ -1640,86 +2389,155 @@ int trunk_sync_thread_start(const FDFSStorageBrief *pStorage) return result; } - /* - //printf("start storage ip_addr: %s, g_trunk_sync_thread_count=%d\n", - pStorage->ip_addr, g_trunk_sync_thread_count); - */ - - if ((result=pthread_create(&tid, &pattr, trunk_sync_thread_entrance, \ - (void *)pStorage)) != 0) + if ((lock_res=pthread_mutex_lock(&trunk_sync_thread_lock)) != 0) { - logError("file: "__FILE__", line: %d, " \ - "create thread failed, errno: %d, " \ - "error info: %s", \ - __LINE__, result, STRERROR(result)); - - pthread_attr_destroy(&pattr); - return result; + logError("file: "__FILE__", line: %d, " + "call pthread_mutex_lock fail, " + "errno: %d, error info: %s", + __LINE__, lock_res, STRERROR(lock_res)); } - if ((result=pthread_mutex_lock(&trunk_sync_thread_lock)) != 0) - { - logError("file: "__FILE__", line: %d, " \ - "call pthread_mutex_lock fail, " \ - "errno: %d, error info: %s", \ - __LINE__, result, STRERROR(result)); - } + do + { + thread_data = trunk_sync_alloc_thread_data(); + if (thread_data == NULL) + { + result = ENOMEM; + break; + } - g_trunk_sync_thread_count++; - trunk_sync_tids = (pthread_t *)realloc(trunk_sync_tids, sizeof(pthread_t) * \ - g_trunk_sync_thread_count); - if (trunk_sync_tids == NULL) - { - logError("file: "__FILE__", line: %d, " \ - "malloc %d bytes fail, " \ - "errno: %d, error info: %s", \ - __LINE__, (int)sizeof(pthread_t) * \ - g_trunk_sync_thread_count, \ - errno, STRERROR(errno)); - } - else - { - trunk_sync_tids[g_trunk_sync_thread_count - 1] = tid; - } + thread_data->running = true; + thread_data->pStorage = pStorage; + if ((result=pthread_create(&thread_data->tid, &pattr, + trunk_sync_thread_entrance, + (void *)thread_data)) != 0) + { + thread_data->running = false; + logError("file: "__FILE__", line: %d, " + "create thread failed, errno: %d, " + "error info: %s", + __LINE__, result, STRERROR(result)); + break; + } - if ((result=pthread_mutex_unlock(&trunk_sync_thread_lock)) != 0) - { - logError("file: "__FILE__", line: %d, " \ - "call pthread_mutex_unlock fail, " \ - "errno: %d, error info: %s", \ - __LINE__, result, STRERROR(result)); - } + g_trunk_sync_thread_count++; + } while (0); + + if ((lock_res=pthread_mutex_unlock(&trunk_sync_thread_lock)) != 0) + { + logError("file: "__FILE__", line: %d, " + "call pthread_mutex_unlock fail, " + "errno: %d, error info: %s", + __LINE__, lock_res, STRERROR(lock_res)); + } pthread_attr_destroy(&pattr); + return result; +} - return 0; +void trunk_waiting_sync_thread_exit() +{ + int saved_trunk_sync_thread_count; + int count; + + saved_trunk_sync_thread_count = g_trunk_sync_thread_count; + if (saved_trunk_sync_thread_count > 0) + { + logInfo("file: "__FILE__", line: %d, " + "waiting %d trunk sync threads exit ...", + __LINE__, saved_trunk_sync_thread_count); + } + + count = 0; + while (g_trunk_sync_thread_count > 0 && count < 60) + { + usleep(50000); + count++; + } + + if (g_trunk_sync_thread_count > 0) + { + logWarning("file: "__FILE__", line: %d, " + "kill %d trunk sync threads.", + __LINE__, g_trunk_sync_thread_count); + kill_trunk_sync_threads(); + } + + if (saved_trunk_sync_thread_count > 0) + { + logInfo("file: "__FILE__", line: %d, " + "%d trunk sync threads exited", + __LINE__, saved_trunk_sync_thread_count); + } } int trunk_unlink_all_mark_files() { - FDFSStorageServer *pStorageServer; - FDFSStorageServer *pServerEnd; + char file_path[MAX_PATH_SIZE]; + char full_filename[MAX_PATH_SIZE]; + DIR *dir; + struct dirent *ent; int result; + int name_len; + time_t t; + struct tm tm; - pServerEnd = g_storage_servers + g_storage_count; - for (pStorageServer=g_storage_servers; pStorageServerserver))) - { - continue; - } + t = g_current_time; + localtime_r(&t, &tm); - if ((result=trunk_unlink_mark_file( \ - pStorageServer->server.id)) != 0) - { - if (result != ENOENT) - { - return result; - } - } - } + snprintf(file_path, sizeof(file_path), + "%s/data/%s", g_fdfs_base_path, TRUNK_DIR_NAME); - return 0; + if ((dir=opendir(file_path)) == NULL) + { + result = errno != 0 ? errno : EPERM; + logError("file: "__FILE__", line: %d, " + "call opendir %s fail, errno: %d, error info: %s", + __LINE__, file_path, result, STRERROR(result)); + return result; + } + + result = 0; + while ((ent=readdir(dir)) != NULL) + { + name_len = strlen(ent->d_name); + if (name_len <= TRUNK_SYNC_MARK_FILE_EXT_LEN) + { + continue; + } + if (memcmp(ent->d_name + (name_len - + TRUNK_SYNC_MARK_FILE_EXT_LEN), + TRUNK_SYNC_MARK_FILE_EXT_STR, + TRUNK_SYNC_MARK_FILE_EXT_LEN) != 0) + { + continue; + } + + snprintf(full_filename, sizeof(full_filename), "%s/%s", + file_path, ent->d_name); + if (unlink(full_filename) != 0) + { + result = errno != 0 ? errno : EPERM; + if (result == ENOENT) + { + result = 0; + } + else + { + logError("file: "__FILE__", line: %d, " + "unlink %s fail, errno: %d, error info: %s", + __LINE__, full_filename, + result, STRERROR(result)); + break; + } + } + } + + closedir(dir); + return result; } +int trunk_binlog_get_write_version() +{ + return trunk_binlog_write_version; +} diff --git a/storage/trunk_mgr/trunk_sync.h b/storage/trunk_mgr/trunk_sync.h index 015392c..958d7bd 100644 --- a/storage/trunk_mgr/trunk_sync.h +++ b/storage/trunk_mgr/trunk_sync.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //trunk_sync.h @@ -28,8 +28,8 @@ extern "C" { typedef struct { char storage_id[FDFS_STORAGE_ID_MAX_SIZE]; + char mark_filename[MAX_PATH_SIZE]; BinLogBuffer binlog_buff; - int mark_fd; int binlog_fd; int64_t binlog_offset; int64_t last_binlog_offset; //for write to mark file @@ -61,6 +61,8 @@ int trunk_sync_thread_start_all(); int trunk_sync_thread_start(const FDFSStorageBrief *pStorage); int kill_trunk_sync_threads(); int trunk_binlog_sync_func(void *args); +int trunk_binlog_flush(const bool bNeedLock); //wrapper for trunk_binlog_fsync +void trunk_waiting_sync_thread_exit(); char *get_trunk_binlog_filename(char *full_filename); char *trunk_mark_filename_by_reader(const void *pArg, char *full_filename); @@ -72,14 +74,31 @@ int trunk_rename_mark_file(const char *old_ip_addr, const int old_port, \ int trunk_open_readable_binlog(TrunkBinLogReader *pReader, \ get_filename_func filename_func, const void *pArg); -int trunk_reader_init(FDFSStorageBrief *pStorage, TrunkBinLogReader *pReader); +int trunk_reader_init(const FDFSStorageBrief *pStorage, + TrunkBinLogReader *pReader, const bool reset_binlog_offset); void trunk_reader_destroy(TrunkBinLogReader *pReader); //trunk binlog compress +int trunk_binlog_compress_delete_binlog_rollback_file(const bool silence); +int trunk_binlog_compress_delete_rollback_files(const bool silence); +int trunk_binlog_compress_delete_temp_files_after_commit(); int trunk_binlog_compress_apply(); int trunk_binlog_compress_commit(); int trunk_binlog_compress_rollback(); +int trunk_sync_notify_thread_reset_offset(); +int trunk_binlog_get_write_version(); + +int storage_delete_trunk_data_file(); + +char *get_trunk_binlog_tmp_filename_ex(const char *binlog_filename, + char *tmp_filename); + +static inline char *get_trunk_binlog_tmp_filename(char *tmp_filename) +{ + return get_trunk_binlog_tmp_filename_ex(NULL, tmp_filename); +} + #ifdef __cplusplus } #endif diff --git a/tracker/fdfs_server_id_func.c b/tracker/fdfs_server_id_func.c index 3ddb489..8d76415 100644 --- a/tracker/fdfs_server_id_func.c +++ b/tracker/fdfs_server_id_func.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include @@ -177,7 +177,7 @@ static int fdfs_init_ip_array(FDFSStorageIdMapArray *mapArray, { idMap->idInfo = idInfo; idMap->group_name = idInfo->group_name; - idMap->ip_addr = idInfo->ip_addrs.ips[i]; + idMap->ip_addr = idInfo->ip_addrs.ips[i].address; idMap->port = idInfo->port; idMap++; } diff --git a/tracker/fdfs_server_id_func.h b/tracker/fdfs_server_id_func.h index 44557dc..a0f6007 100644 --- a/tracker/fdfs_server_id_func.h +++ b/tracker/fdfs_server_id_func.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //fdfs_server_id_func.h diff --git a/tracker/fdfs_shared_func.c b/tracker/fdfs_shared_func.c index 392a959..8d07163 100644 --- a/tracker/fdfs_shared_func.c +++ b/tracker/fdfs_shared_func.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include @@ -13,10 +13,12 @@ #include "fastcommon/logger.h" #include "fastcommon/sockopt.h" #include "fastcommon/shared_func.h" +#include "fastcommon/local_ip_func.h" #include "tracker_proto.h" #include "fdfs_global.h" #include "fdfs_shared_func.h" + bool fdfs_server_contain(TrackerServerInfo *pServerInfo, const char *target_ip, const int target_port) { @@ -108,6 +110,24 @@ bool fdfs_server_equal(TrackerServerInfo *pServer1, return true; } +bool fdfs_server_contain_local_service(TrackerServerInfo *pServerInfo, + const int target_port) +{ + const char *current_ip; + + current_ip = get_first_local_ip(); + while (current_ip != NULL) + { + if (fdfs_server_contain(pServerInfo, current_ip, target_port)) + { + return true; + } + current_ip = get_next_local_ip(current_ip); + } + + return false; +} + TrackerServerInfo *fdfs_tracker_group_get_server(TrackerServerGroup *pGroup, const char *target_ip, const int target_port) { @@ -150,7 +170,7 @@ void fdfs_server_sock_reset(TrackerServerInfo *pServerInfo) } } -int fdfs_get_tracker_leader_index_ex(TrackerServerGroup *pServerGroup, \ +int fdfs_get_tracker_leader_index_ex(TrackerServerGroup *pServerGroup, const char *leaderIp, const int leaderPort) { TrackerServerInfo *pServer; @@ -173,7 +193,7 @@ int fdfs_get_tracker_leader_index_ex(TrackerServerGroup *pServerGroup, \ return -1; } -int fdfs_parse_storage_reserved_space(IniContext *pIniContext, \ +int fdfs_parse_storage_reserved_space(IniContext *pIniContext, FDFSStorageReservedSpace *pStorageReservedSpace) { int result; @@ -495,11 +515,40 @@ int fdfs_server_info_to_string_ex(const TrackerServerInfo *pServer, return len; } +int fdfs_get_ip_type(const char* ip) +{ + if (ip == NULL || (int)strlen(ip) < 8) + { + return FDFS_IP_TYPE_UNKNOWN; + } + + if (memcmp(ip, "10.", 3) == 0) + { + return FDFS_IP_TYPE_PRIVATE_10; + } + if (memcmp(ip, "192.168.", 8) == 0) + { + return FDFS_IP_TYPE_PRIVATE_192; + } + + if (memcmp(ip, "172.", 4) == 0) + { + int b; + b = atoi(ip + 4); + if (b >= 16 && b < 32) + { + return FDFS_IP_TYPE_PRIVATE_172; + } + } + + return FDFS_IP_TYPE_OUTER; +} + int fdfs_check_server_ips(const TrackerServerInfo *pServer, char *error_info, const int error_size) { - int private0; - int private1; + int type0; + int type1; if (pServer->count == 1) { *error_info = '\0'; @@ -521,13 +570,14 @@ int fdfs_check_server_ips(const TrackerServerInfo *pServer, return EINVAL; } - private0 = is_private_ip(pServer->connections[0].ip_addr) ? 1 : 0; - private1 = is_private_ip(pServer->connections[1].ip_addr) ? 1 : 0; - if ((private0 ^ private1) == 0) + type0 = fdfs_get_ip_type(pServer->connections[0].ip_addr); + type1 = fdfs_get_ip_type(pServer->connections[1].ip_addr); + if (type0 == type1) { snprintf(error_info, error_size, "invalid ip addresses %s and %s, " - "one MUST be an inner IP and another is a outer IP", + "one MUST be an inner IP and another is a outer IP, " + "or two different types of inner IP addresses", pServer->connections[0].ip_addr, pServer->connections[1].ip_addr); return EINVAL; @@ -549,8 +599,8 @@ int fdfs_parse_multi_ips_ex(char *ip_str, FDFSMultiIP *ip_addrs, { if (resolve) { - if (getIpaddrByName(hosts[i], ip_addrs->ips[i], - sizeof(ip_addrs->ips[i])) == INADDR_NONE) + if (getIpaddrByName(hosts[i], ip_addrs->ips[i].address, + sizeof(ip_addrs->ips[i].address)) == INADDR_NONE) { snprintf(error_info, error_size, "host \"%s\" is invalid, error info: %s", @@ -560,7 +610,17 @@ int fdfs_parse_multi_ips_ex(char *ip_str, FDFSMultiIP *ip_addrs, } else { - snprintf(ip_addrs->ips[i], sizeof(ip_addrs->ips[i]), "%s", hosts[i]); + snprintf(ip_addrs->ips[i].address, + sizeof(ip_addrs->ips[i].address), "%s", hosts[i]); + } + + ip_addrs->ips[i].type = fdfs_get_ip_type(ip_addrs->ips[i].address); + if (ip_addrs->ips[i].type == FDFS_IP_TYPE_UNKNOWN) + { + snprintf(error_info, error_size, + "ip address \"%s\" is invalid", + ip_addrs->ips[i].address); + return EINVAL; } } @@ -582,14 +642,14 @@ int fdfs_multi_ips_to_string_ex(const FDFSMultiIP *ip_addrs, if (ip_addrs->count == 1) { return snprintf(buff, buffSize, "%s", - ip_addrs->ips[0]); + ip_addrs->ips[0].address); } - len = snprintf(buff, buffSize, "%s", ip_addrs->ips[0]); + len = snprintf(buff, buffSize, "%s", ip_addrs->ips[0].address); for (i=1; icount; i++) { len += snprintf(buff + len, buffSize - len, "%c%s", - seperator, ip_addrs->ips[i]); + seperator, ip_addrs->ips[i].address); } return len; } @@ -597,10 +657,11 @@ int fdfs_multi_ips_to_string_ex(const FDFSMultiIP *ip_addrs, const char *fdfs_get_ipaddr_by_peer_ip(const FDFSMultiIP *ip_addrs, const char *client_ip) { + int ip_type; int index; if (ip_addrs->count == 1) { - return ip_addrs->ips[0]; + return ip_addrs->ips[0].address; } if (ip_addrs->count <= 0) @@ -608,15 +669,16 @@ const char *fdfs_get_ipaddr_by_peer_ip(const FDFSMultiIP *ip_addrs, return ""; } - index = is_private_ip(client_ip) ? FDFS_MULTI_IP_INDEX_INNER : FDFS_MULTI_IP_INDEX_OUTER; - return ip_addrs->ips[index]; + ip_type = fdfs_get_ip_type(client_ip); + index = ip_addrs->ips[FDFS_MULTI_IP_INDEX_OUTER].type == ip_type ? + FDFS_MULTI_IP_INDEX_OUTER : FDFS_MULTI_IP_INDEX_INNER; + return ip_addrs->ips[index].address; } int fdfs_check_and_format_ips(FDFSMultiIP *ip_addrs, char *error_info, const int error_size) { - int privates[FDFS_MULTI_IP_MAX_COUNT]; - char swap_ip[IP_ADDRESS_SIZE]; + FDFSIPInfo swap_ip; if (ip_addrs->count == 1) { *error_info = '\0'; @@ -638,23 +700,23 @@ int fdfs_check_and_format_ips(FDFSMultiIP *ip_addrs, return EINVAL; } - privates[0] = is_private_ip(ip_addrs->ips[0]) ? 1 : 0; - privates[1] = is_private_ip(ip_addrs->ips[1]) ? 1 : 0; - if ((privates[0] ^ privates[1]) == 0) + if (ip_addrs->ips[FDFS_MULTI_IP_INDEX_INNER].type == + ip_addrs->ips[FDFS_MULTI_IP_INDEX_OUTER].type) { snprintf(error_info, error_size, "invalid ip addresses %s and %s, " - "one MUST be an inner IP and another is a outer IP", - ip_addrs->ips[0], ip_addrs->ips[1]); + "one MUST be an inner IP and another is a outer IP, " + "or two different types of inner IP addresses", + ip_addrs->ips[0].address, ip_addrs->ips[1].address); return EINVAL; } - if (!privates[FDFS_MULTI_IP_INDEX_INNER]) + if (ip_addrs->ips[FDFS_MULTI_IP_INDEX_INNER].type == FDFS_IP_TYPE_OUTER) { - strcpy(swap_ip, ip_addrs->ips[FDFS_MULTI_IP_INDEX_INNER]); - strcpy(ip_addrs->ips[FDFS_MULTI_IP_INDEX_INNER], - ip_addrs->ips[FDFS_MULTI_IP_INDEX_OUTER]); - strcpy(ip_addrs->ips[FDFS_MULTI_IP_INDEX_OUTER], swap_ip); + swap_ip = ip_addrs->ips[FDFS_MULTI_IP_INDEX_INNER]; + ip_addrs->ips[FDFS_MULTI_IP_INDEX_INNER] = + ip_addrs->ips[FDFS_MULTI_IP_INDEX_OUTER]; + ip_addrs->ips[FDFS_MULTI_IP_INDEX_OUTER] = swap_ip; } *error_info = '\0'; @@ -664,14 +726,14 @@ int fdfs_check_and_format_ips(FDFSMultiIP *ip_addrs, void fdfs_set_multi_ip_index(FDFSMultiIP *multi_ip, const char *target_ip) { int i; - if (multi_ip->count == 1) + if (multi_ip->count <= 1) { return; } for (i=0; icount; i++) { - if (strcmp(multi_ip->ips[i], target_ip) == 0) + if (strcmp(multi_ip->ips[i].address, target_ip) == 0) { multi_ip->index = i; break; @@ -679,6 +741,26 @@ void fdfs_set_multi_ip_index(FDFSMultiIP *multi_ip, const char *target_ip) } } +void fdfs_set_server_info_index(TrackerServerInfo *pServer, + const char *target_ip, const int target_port) +{ + int i; + if (pServer->count <= 1) + { + return; + } + + for (i=0; icount; i++) + { + if (FC_CONNECTION_SERVER_EQUAL(pServer->connections[i], + target_ip, target_port)) + { + pServer->index = i; + break; + } + } +} + void fdfs_set_server_info(TrackerServerInfo *pServer, const char *ip_addr, const int port) { @@ -697,6 +779,7 @@ void fdfs_set_server_info_ex(TrackerServerInfo *pServer, for (i=0; icount; i++) { conn_pool_set_server_info(pServer->connections + i, - ip_addrs->ips[i], port); + ip_addrs->ips[i].address, port); } } + diff --git a/tracker/fdfs_shared_func.h b/tracker/fdfs_shared_func.h index fdec711..aced559 100644 --- a/tracker/fdfs_shared_func.h +++ b/tracker/fdfs_shared_func.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //fdfs_shared_func.h @@ -17,6 +17,17 @@ #include "tracker_types.h" #include "fdfs_server_id_func.h" +#define FDFS_IP_TYPE_UNKNOWN 0 +#define FDFS_IP_TYPE_PRIVATE_10 1 +#define FDFS_IP_TYPE_PRIVATE_172 2 +#define FDFS_IP_TYPE_PRIVATE_192 3 +#define FDFS_IP_TYPE_OUTER 4 + +#define FDFS_IS_AVAILABLE_STATUS(status) \ + (status == FDFS_STORAGE_STATUS_OFFLINE || \ + status == FDFS_STORAGE_STATUS_ONLINE || \ + status == FDFS_STORAGE_STATUS_ACTIVE) + #ifdef __cplusplus extern "C" { #endif @@ -69,6 +80,9 @@ bool fdfs_server_contain_ex(TrackerServerInfo *pServer1, bool fdfs_server_equal(TrackerServerInfo *pServer1, TrackerServerInfo *pServer2); +bool fdfs_server_contain_local_service(TrackerServerInfo *pServerInfo, + const int target_port); + /** * tracker group get server * params: @@ -124,6 +138,8 @@ static inline int fdfs_parse_multi_ips(char *ip_str, FDFSMultiIP *ip_addrs, error_info, error_size, resolve); } +int fdfs_get_ip_type(const char* ip); + int fdfs_check_server_ips(const TrackerServerInfo *pServer, char *error_info, const int error_size); @@ -135,6 +151,16 @@ const char *fdfs_get_ipaddr_by_peer_ip(const FDFSMultiIP *ip_addrs, void fdfs_set_multi_ip_index(FDFSMultiIP *multi_ip, const char *target_ip); +void fdfs_set_server_info_index(TrackerServerInfo *pServer, + const char *target_ip, const int target_port); + +static inline void fdfs_set_server_info_index1(TrackerServerInfo *pServer, + const ConnectionInfo *target) +{ + return fdfs_set_server_info_index(pServer, + target->ip_addr, target->port); +} + void fdfs_set_server_info(TrackerServerInfo *pServer, const char *ip_addr, const int port); diff --git a/tracker/fdfs_trackerd.c b/tracker/fdfs_trackerd.c index 85f97d9..c340432 100644 --- a/tracker/fdfs_trackerd.c +++ b/tracker/fdfs_trackerd.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include @@ -70,13 +70,16 @@ static void sigDumpHandler(int sig); static void usage(const char *program) { - fprintf(stderr, "Usage: %s [start | stop | restart]\n", - program); + fprintf(stderr, "FastDFS server v%d.%02d\n" + "Usage: %s [start | stop | restart]\n", + g_fdfs_version.major, g_fdfs_version.minor, + program); } int main(int argc, char *argv[]) { char *conf_filename; + char *action; int result; int wait_count; int sock; @@ -100,6 +103,14 @@ int main(int argc, char *argv[]) log_init2(); conf_filename = argv[1]; + if (!fileExists(conf_filename)) + { + if (starts_with(conf_filename, "-")) + { + usage(argv[0]); + return 0; + } + } if ((result=get_base_path_from_conf_file(conf_filename, g_fdfs_base_path, sizeof(g_fdfs_base_path))) != 0) { @@ -109,7 +120,8 @@ int main(int argc, char *argv[]) snprintf(pidFilename, sizeof(pidFilename), "%s/data/fdfs_trackerd.pid", g_fdfs_base_path); - if ((result=process_action(pidFilename, argv[2], &stop)) != 0) + action = argc >= 3 ? argv[2] : "start"; + if ((result=process_action(pidFilename, action, &stop)) != 0) { if (result == EINVAL) { @@ -441,6 +453,7 @@ static void sigQuitHandler(int sig) { if (!bTerminateFlag) { + tcp_set_try_again_when_interrupt(false); set_timer(1, 1, sigAlarmHandler); bTerminateFlag = true; diff --git a/tracker/tracker_dump.c b/tracker/tracker_dump.c index 732d43a..8a8c444 100644 --- a/tracker/tracker_dump.c +++ b/tracker/tracker_dump.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include diff --git a/tracker/tracker_dump.h b/tracker/tracker_dump.h index 8a16368..f737a19 100644 --- a/tracker/tracker_dump.h +++ b/tracker/tracker_dump.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //tracker_dump.h diff --git a/tracker/tracker_func.c b/tracker/tracker_func.c index 1041e8b..be08a4c 100644 --- a/tracker/tracker_func.c +++ b/tracker/tracker_func.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //tracker_func.c @@ -504,19 +504,19 @@ int tracker_load_from_conf_file(const char *filename, \ g_trunk_file_size = (int)trunk_file_size; if (g_trunk_file_size < 4 * 1024 * 1024) { - logWarning("file: "__FILE__", line: %d, " \ - "item \"trunk_file_size\" %d is too small, " \ + logWarning("file: "__FILE__", line: %d, " + "item \"trunk_file_size\" %d is too small, " "change to 4MB", __LINE__, g_trunk_file_size); g_trunk_file_size = 4 * 1024 * 1024; } - pSlotMaxSize = iniGetStrValue(NULL, \ + pSlotMaxSize = iniGetStrValue(NULL, "slot_max_size", &iniContext); if (pSlotMaxSize == NULL) { - slot_max_size = g_trunk_file_size / 2; + slot_max_size = g_trunk_file_size / 8; } - else if ((result=parse_bytes(pSlotMaxSize, 1, \ + else if ((result=parse_bytes(pSlotMaxSize, 1, &slot_max_size)) != 0) { return result; @@ -524,26 +524,26 @@ int tracker_load_from_conf_file(const char *filename, \ g_slot_max_size = (int)slot_max_size; if (g_slot_max_size <= g_slot_min_size) { - logError("file: "__FILE__", line: %d, " \ - "item \"slot_max_size\" %d is invalid, " \ - "which <= slot_min_size: %d", \ + logError("file: "__FILE__", line: %d, " + "item \"slot_max_size\" %d is invalid, " + "which <= slot_min_size: %d", __LINE__, g_slot_max_size, g_slot_min_size); result = EINVAL; break; } if (g_slot_max_size > g_trunk_file_size / 2) { - logWarning("file: "__FILE__", line: %d, " \ - "item \"slot_max_size\": %d is too large, " \ - "change to %d", __LINE__, g_slot_max_size, \ + logWarning("file: "__FILE__", line: %d, " + "item \"slot_max_size\": %d is too large, " + "change to %d", __LINE__, g_slot_max_size, g_trunk_file_size / 2); g_slot_max_size = g_trunk_file_size / 2; } - g_trunk_create_file_advance = iniGetBoolValue(NULL, \ + g_trunk_create_file_advance = iniGetBoolValue(NULL, "trunk_create_file_advance", &iniContext, false); - if ((result=get_time_item_from_conf(&iniContext, \ - "trunk_create_file_time_base", \ + if ((result=get_time_item_from_conf(&iniContext, + "trunk_create_file_time_base", &g_trunk_create_file_time_base, 2, 0)) != 0) { return result; @@ -563,58 +563,100 @@ int tracker_load_from_conf_file(const char *filename, \ { return result; } - g_trunk_compress_binlog_min_interval = iniGetIntValue(NULL, \ - "trunk_compress_binlog_min_interval", \ + g_trunk_compress_binlog_min_interval = iniGetIntValue(NULL, + "trunk_compress_binlog_min_interval", &iniContext, 0); + g_trunk_compress_binlog_interval = iniGetIntValue(NULL, + "trunk_compress_binlog_interval", + &iniContext, 0); + if ((result=get_time_item_from_conf(&iniContext, + "trunk_compress_binlog_time_base", + &g_trunk_compress_binlog_time_base, 3, 0)) != 0) + { + return result; + } - g_trunk_init_check_occupying = iniGetBoolValue(NULL, \ + g_trunk_binlog_max_backups = iniGetIntValue(NULL, + "trunk_binlog_max_backups", &iniContext, 0); + + g_trunk_alloc_alignment_size = iniGetIntValue(NULL, + "trunk_alloc_alignment_size", &iniContext, 0); + if (g_slot_min_size < g_trunk_alloc_alignment_size) + { + logWarning("file: "__FILE__", line: %d, " + "item \"slot_min_size\": %d < " + "\"trunk_alloc_alignment_size\": %d, " + "change to %d", __LINE__, g_slot_min_size, + g_trunk_alloc_alignment_size, + g_trunk_alloc_alignment_size); + g_slot_min_size = g_trunk_alloc_alignment_size; + } + + g_trunk_init_check_occupying = iniGetBoolValue(NULL, "trunk_init_check_occupying", &iniContext, false); - g_trunk_init_reload_from_binlog = iniGetBoolValue(NULL, \ + g_trunk_init_reload_from_binlog = iniGetBoolValue(NULL, "trunk_init_reload_from_binlog", &iniContext, false); - if ((result=tracker_load_storage_id_info( \ + g_trunk_free_space_merge = iniGetBoolValue(NULL, + "trunk_free_space_merge", &iniContext, false); + + g_delete_unused_trunk_files = iniGetBoolValue(NULL, + "delete_unused_trunk_files", &iniContext, false); + + if ((result=tracker_load_storage_id_info( filename, &iniContext)) != 0) { return result; } - g_rotate_error_log = iniGetBoolValue(NULL, "rotate_error_log",\ + g_rotate_error_log = iniGetBoolValue(NULL, "rotate_error_log", &iniContext, false); - if ((result=get_time_item_from_conf(&iniContext, \ - "error_log_rotate_time", &g_error_log_rotate_time, \ + g_compress_old_error_log = iniGetBoolValue(NULL, "compress_old_error_log", + &iniContext, false); + g_compress_error_log_days_before = iniGetIntValue(NULL, + "compress_error_log_days_before", &iniContext, 1); + if (g_compress_old_error_log) + { + log_set_compress_log_flags(LOG_COMPRESS_FLAGS_ENABLED | + LOG_COMPRESS_FLAGS_NEW_THREAD); + log_set_compress_log_days_before(g_compress_error_log_days_before); + } + + if ((result=get_time_item_from_conf(&iniContext, + "error_log_rotate_time", &g_error_log_rotate_time, 0, 0)) != 0) { break; } - pRotateErrorLogSize = iniGetStrValue(NULL, \ + pRotateErrorLogSize = iniGetStrValue(NULL, "rotate_error_log_size", &iniContext); if (pRotateErrorLogSize == NULL) { rotate_error_log_size = 0; } - else if ((result=parse_bytes(pRotateErrorLogSize, 1, \ + else if ((result=parse_bytes(pRotateErrorLogSize, 1, &rotate_error_log_size)) != 0) { break; } - if (rotate_error_log_size > 0 && \ + if (rotate_error_log_size > 0 && rotate_error_log_size < FDFS_ONE_MB) { - logWarning("file: "__FILE__", line: %d, " \ - "item \"rotate_error_log_size\": " \ - "%"PRId64" is too small, " \ - "change to 1 MB", __LINE__, \ + logWarning("file: "__FILE__", line: %d, " + "item \"rotate_error_log_size\": " + "%"PRId64" is too small, " + "change to 1 MB", __LINE__, rotate_error_log_size); rotate_error_log_size = FDFS_ONE_MB; } fdfs_set_log_rotate_size(&g_log_context, rotate_error_log_size); - g_log_file_keep_days = iniGetIntValue(NULL, \ + g_log_file_keep_days = iniGetIntValue(NULL, "log_file_keep_days", &iniContext, 0); - g_store_slave_file_use_link = iniGetBoolValue(NULL, \ + g_store_slave_file_use_link = iniGetBoolValue(NULL, "store_slave_file_use_link", &iniContext, false); if ((result=fdfs_connection_pool_init(filename, &iniContext)) != 0) @@ -708,81 +750,97 @@ int tracker_load_from_conf_file(const char *filename, \ int_to_comma_str(g_min_buff_size, sz_min_buff_size); int_to_comma_str(g_max_buff_size, sz_max_buff_size); - logInfo("FastDFS v%d.%02d, base_path=%s, " \ - "run_by_group=%s, run_by_user=%s, " \ - "connect_timeout=%ds, " \ - "network_timeout=%ds, " \ - "port=%d, bind_addr=%s, " \ - "max_connections=%d, " \ - "accept_threads=%d, " \ - "work_threads=%d, " \ - "min_buff_size=%s, " \ - "max_buff_size=%s, " \ - "store_lookup=%d, store_group=%s, " \ - "store_server=%d, store_path=%d, " \ - "reserved_storage_space=%s, " \ - "download_server=%d, " \ - "allow_ip_count=%d, sync_log_buff_interval=%ds, " \ - "check_active_interval=%ds, " \ - "thread_stack_size=%d KB, " \ - "storage_ip_changed_auto_adjust=%d, " \ - "storage_sync_file_max_delay=%ds, " \ - "storage_sync_file_max_time=%ds, " \ - "use_trunk_file=%d, " \ - "slot_min_size=%d, " \ - "slot_max_size=%d MB, " \ - "trunk_file_size=%d MB, " \ - "trunk_create_file_advance=%d, " \ - "trunk_create_file_time_base=%02d:%02d, " \ - "trunk_create_file_interval=%d, " \ - "trunk_create_file_space_threshold=%d GB, " \ - "trunk_init_check_occupying=%d, " \ - "trunk_init_reload_from_binlog=%d, " \ - "trunk_compress_binlog_min_interval=%d, " \ - "use_storage_id=%d, " \ - "id_type_in_filename=%s, " \ - "storage_id/ip_count=%d / %d, " \ - "rotate_error_log=%d, " \ - "error_log_rotate_time=%02d:%02d, " \ - "rotate_error_log_size=%"PRId64", " \ - "log_file_keep_days=%d, " \ - "store_slave_file_use_link=%d, " \ - "use_connection_pool=%d, " \ - "g_connection_pool_max_idle_time=%ds", \ - g_fdfs_version.major, g_fdfs_version.minor, \ - g_fdfs_base_path, g_run_by_group, g_run_by_user, \ - g_fdfs_connect_timeout, \ - g_fdfs_network_timeout, g_server_port, bind_addr, \ - g_max_connections, g_accept_threads, g_work_threads, \ - sz_min_buff_size, sz_max_buff_size, \ - g_groups.store_lookup, g_groups.store_group, \ - g_groups.store_server, g_groups.store_path, \ - fdfs_storage_reserved_space_to_string( \ - &g_storage_reserved_space, reserved_space_str), \ - g_groups.download_server, \ - g_allow_ip_count, g_sync_log_buff_interval, \ - g_check_active_interval, g_thread_stack_size / 1024, \ - g_storage_ip_changed_auto_adjust, \ - g_storage_sync_file_max_delay, \ - g_storage_sync_file_max_time, \ - g_if_use_trunk_file, g_slot_min_size, \ - g_slot_max_size / FDFS_ONE_MB, \ - g_trunk_file_size / FDFS_ONE_MB, \ - g_trunk_create_file_advance, \ - g_trunk_create_file_time_base.hour, \ - g_trunk_create_file_time_base.minute, \ - g_trunk_create_file_interval, \ - (int)(g_trunk_create_file_space_threshold / \ - (FDFS_ONE_MB * 1024)), g_trunk_init_check_occupying, \ - g_trunk_init_reload_from_binlog, \ - g_trunk_compress_binlog_min_interval, \ - g_use_storage_id, g_id_type_in_filename == \ - FDFS_ID_TYPE_SERVER_ID ? "id" : "ip", \ - g_storage_ids_by_id.count, g_storage_ids_by_ip.count, \ - g_rotate_error_log, g_error_log_rotate_time.hour, \ - g_error_log_rotate_time.minute, \ + logInfo("FastDFS v%d.%02d, base_path=%s, " + "run_by_group=%s, run_by_user=%s, " + "connect_timeout=%ds, " + "network_timeout=%ds, " + "port=%d, bind_addr=%s, " + "max_connections=%d, " + "accept_threads=%d, " + "work_threads=%d, " + "min_buff_size=%s, " + "max_buff_size=%s, " + "store_lookup=%d, store_group=%s, " + "store_server=%d, store_path=%d, " + "reserved_storage_space=%s, " + "download_server=%d, " + "allow_ip_count=%d, sync_log_buff_interval=%ds, " + "check_active_interval=%ds, " + "thread_stack_size=%d KB, " + "storage_ip_changed_auto_adjust=%d, " + "storage_sync_file_max_delay=%ds, " + "storage_sync_file_max_time=%ds, " + "use_trunk_file=%d, " + "slot_min_size=%d, " + "slot_max_size=%d KB, " + "trunk_alloc_alignment_size=%d, " + "trunk_file_size=%d MB, " + "trunk_create_file_advance=%d, " + "trunk_create_file_time_base=%02d:%02d, " + "trunk_create_file_interval=%d, " + "trunk_create_file_space_threshold=%d GB, " + "trunk_init_check_occupying=%d, " + "trunk_init_reload_from_binlog=%d, " + "trunk_free_space_merge=%d, " + "delete_unused_trunk_files=%d, " + "trunk_compress_binlog_min_interval=%d, " + "trunk_compress_binlog_interval=%d, " + "trunk_compress_binlog_time_base=%02d:%02d, " + "trunk_binlog_max_backups=%d, " + "use_storage_id=%d, " + "id_type_in_filename=%s, " + "storage_id/ip_count=%d / %d, " + "rotate_error_log=%d, " + "error_log_rotate_time=%02d:%02d, " + "compress_old_error_log=%d, " + "compress_error_log_days_before=%d, " + "rotate_error_log_size=%"PRId64", " + "log_file_keep_days=%d, " + "store_slave_file_use_link=%d, " + "use_connection_pool=%d, " + "g_connection_pool_max_idle_time=%ds", + g_fdfs_version.major, g_fdfs_version.minor, + g_fdfs_base_path, g_run_by_group, g_run_by_user, + g_fdfs_connect_timeout, + g_fdfs_network_timeout, g_server_port, bind_addr, + g_max_connections, g_accept_threads, g_work_threads, + sz_min_buff_size, sz_max_buff_size, + g_groups.store_lookup, g_groups.store_group, + g_groups.store_server, g_groups.store_path, + fdfs_storage_reserved_space_to_string( + &g_storage_reserved_space, reserved_space_str), + g_groups.download_server, + g_allow_ip_count, g_sync_log_buff_interval, + g_check_active_interval, g_thread_stack_size / 1024, + g_storage_ip_changed_auto_adjust, + g_storage_sync_file_max_delay, + g_storage_sync_file_max_time, + g_if_use_trunk_file, g_slot_min_size, + g_slot_max_size / 1024, + g_trunk_alloc_alignment_size, + g_trunk_file_size / FDFS_ONE_MB, + g_trunk_create_file_advance, + g_trunk_create_file_time_base.hour, + g_trunk_create_file_time_base.minute, + g_trunk_create_file_interval, + (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_delete_unused_trunk_files, + g_trunk_compress_binlog_min_interval, + g_trunk_compress_binlog_interval, + g_trunk_compress_binlog_time_base.hour, + g_trunk_compress_binlog_time_base.minute, + g_trunk_binlog_max_backups, + g_use_storage_id, g_id_type_in_filename == + FDFS_ID_TYPE_SERVER_ID ? "id" : "ip", + g_storage_ids_by_id.count, g_storage_ids_by_ip.count, + g_rotate_error_log, g_error_log_rotate_time.hour, + g_error_log_rotate_time.minute, g_compress_old_error_log, + g_compress_error_log_days_before, g_log_context.rotate_size, g_log_file_keep_days, - g_store_slave_file_use_link, \ + g_store_slave_file_use_link, g_use_connection_pool, g_connection_pool_max_idle_time); #ifdef WITH_HTTPD diff --git a/tracker/tracker_func.h b/tracker/tracker_func.h index cb044f6..67a0737 100644 --- a/tracker/tracker_func.h +++ b/tracker/tracker_func.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //tracker_func.h diff --git a/tracker/tracker_global.c b/tracker/tracker_global.c index 98967b3..a02d530 100644 --- a/tracker/tracker_global.c +++ b/tracker/tracker_global.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include "tracker_global.h" @@ -39,6 +39,7 @@ bool g_storage_ip_changed_auto_adjust = true; bool g_use_storage_id = false; //if use storage ID instead of IP address byte g_id_type_in_filename = FDFS_ID_TYPE_IP_ADDRESS; //id type of the storage server in the filename bool g_rotate_error_log = false; //if rotate the error log every day +bool g_compress_old_error_log = false; //if compress the old error log TimeInfo g_error_log_rotate_time = {0, 0, 0}; //rotate error log time base int g_thread_stack_size = 64 * 1024; @@ -50,12 +51,18 @@ 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; +bool g_delete_unused_trunk_files = 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 TimeInfo g_trunk_create_file_time_base = {0, 0}; +TimeInfo g_trunk_compress_binlog_time_base = {0, 0}; int g_trunk_create_file_interval = 86400; +int g_trunk_compress_binlog_interval = 0; int g_trunk_compress_binlog_min_interval = 0; +int g_trunk_binlog_max_backups = 0; +int g_trunk_alloc_alignment_size = 0; int64_t g_trunk_create_file_space_threshold = 0; time_t g_up_time = 0; @@ -74,5 +81,6 @@ char g_exe_name[256] = {0}; #endif int g_log_file_keep_days = 0; +int g_compress_error_log_days_before = 0; FDFSConnectionStat g_connection_stat = {0, 0}; diff --git a/tracker/tracker_global.h b/tracker/tracker_global.h index af3d010..fc0580f 100644 --- a/tracker/tracker_global.h +++ b/tracker/tracker_global.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //tracker_global.h @@ -62,8 +62,9 @@ extern char g_run_by_user[32]; extern bool g_storage_ip_changed_auto_adjust; extern bool g_use_storage_id; //identify storage by ID instead of IP address extern byte g_id_type_in_filename; //id type of the storage server in the filename -extern bool g_rotate_error_log; //if rotate the error log every day -extern TimeInfo g_error_log_rotate_time; //rotate error log time base +extern bool g_rotate_error_log; //if rotate the error log every day +extern bool g_compress_old_error_log; //if compress the old error log +extern TimeInfo g_error_log_rotate_time; //rotate error log time base extern int g_thread_stack_size; extern int g_storage_sync_file_max_delay; @@ -74,12 +75,18 @@ 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 bool g_delete_unused_trunk_files; 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 extern TimeInfo g_trunk_create_file_time_base; +extern TimeInfo g_trunk_compress_binlog_time_base; extern int g_trunk_create_file_interval; +extern int g_trunk_compress_binlog_interval; extern int g_trunk_compress_binlog_min_interval; +extern int g_trunk_binlog_max_backups; +extern int g_trunk_alloc_alignment_size; extern int64_t g_trunk_create_file_space_threshold; extern time_t g_up_time; @@ -98,6 +105,7 @@ extern char g_exe_name[256]; #endif extern int g_log_file_keep_days; +extern int g_compress_error_log_days_before; extern FDFSConnectionStat g_connection_stat; #ifdef __cplusplus diff --git a/tracker/tracker_http_check.h b/tracker/tracker_http_check.h index 6bfd23a..39e8743 100644 --- a/tracker/tracker_http_check.h +++ b/tracker/tracker_http_check.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //tracker_httpd.h diff --git a/tracker/tracker_mem.c b/tracker/tracker_mem.c index 859db57..0161e0a 100644 --- a/tracker/tracker_mem.c +++ b/tracker/tracker_mem.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include @@ -3448,9 +3448,9 @@ int tracker_mem_delete_storage(FDFSGroupInfo *pGroup, const char *id) } } - logDebug("file: "__FILE__", line: %d, " \ - "delete storage server: %s:%d, group: %s", \ - __LINE__, pStorageServer->ip_addrs.ips[0], + logDebug("file: "__FILE__", line: %d, " + "delete storage server: %s:%d, group: %s", + __LINE__, pStorageServer->ip_addrs.ips[0].address, pStorageServer->storage_port, pGroup->group_name); tracker_mem_clear_storage_fields(pStorageServer); @@ -3536,16 +3536,18 @@ int tracker_mem_storage_ip_changed(FDFSGroupInfo *pGroup, \ pthread_mutex_lock(&mem_thread_lock); //exchange old and new storage server - snprintf(pOldStorageServer->id, sizeof(pOldStorageServer->id), \ + snprintf(pOldStorageServer->id, sizeof(pOldStorageServer->id), "%s", new_storage_ip); - snprintf(pOldStorageServer->ip_addrs.ips[0], - sizeof(pOldStorageServer->ip_addrs.ips[0]), "%s", new_storage_ip); + snprintf(pOldStorageServer->ip_addrs.ips[0].address, + sizeof(pOldStorageServer->ip_addrs.ips[0].address), + "%s", new_storage_ip); - snprintf(pNewStorageServer->id, sizeof(pNewStorageServer->id), \ + snprintf(pNewStorageServer->id, sizeof(pNewStorageServer->id), "%s", old_storage_ip); pNewStorageServer->ip_addrs.count = 1; - snprintf(pNewStorageServer->ip_addrs.ips[0], - sizeof(pNewStorageServer->ip_addrs.ips[0]), "%s", old_storage_ip); + snprintf(pNewStorageServer->ip_addrs.ips[0].address, + sizeof(pNewStorageServer->ip_addrs.ips[0].address), + "%s", old_storage_ip); pNewStorageServer->status = FDFS_STORAGE_STATUS_IP_CHANGED; pGroup->chg_count++; @@ -3684,7 +3686,7 @@ static int _tracker_mem_add_storage(FDFSGroupInfo *pGroup, { multi_ip.count = 1; multi_ip.index = 0; - strcpy(multi_ip.ips[0], ip_addr); + strcpy(multi_ip.ips[0].address, ip_addr); } if (id != NULL) @@ -4273,8 +4275,7 @@ static int tracker_mem_get_tracker_server(FDFSStorageJoinBody *pJoinBody, \ for (pTrackerServer=pJoinBody->tracker_servers; pTrackerServerconnections[0].port == g_server_port && - is_local_host_ip(pTrackerServer->connections[0].ip_addr)) + if (fdfs_server_contain_local_service(pTrackerServer, g_server_port)) { continue; } @@ -4708,16 +4709,21 @@ int tracker_mem_add_group_and_storage(TrackerClientInfo *pClientInfo, \ } else { - if (pClientInfo->pGroup->store_path_count != \ + if (pClientInfo->pGroup->store_path_count != pJoinBody->store_path_count) { - ppEnd = pClientInfo->pGroup->all_servers + \ + ppEnd = pClientInfo->pGroup->all_servers + pClientInfo->pGroup->count; - for (ppServer=pClientInfo->pGroup->all_servers; \ + for (ppServer=pClientInfo->pGroup->all_servers; ppServerstore_path_count != \ - pJoinBody->store_path_count) + if ((*ppServer)->status == FDFS_STORAGE_STATUS_DELETED) + { + continue; + } + + if ((*ppServer)->store_path_count != + pJoinBody->store_path_count) { break; } @@ -4725,9 +4731,9 @@ int tracker_mem_add_group_and_storage(TrackerClientInfo *pClientInfo, \ if (ppServer == ppEnd) //all servers are same, adjust { - if ((result=tracker_realloc_group_path_mbs( \ - pClientInfo->pGroup, \ - pJoinBody->store_path_count))!=0) + if ((result=tracker_realloc_group_path_mbs( + pClientInfo->pGroup, pJoinBody-> + store_path_count)) != 0) { return result; } @@ -4881,14 +4887,14 @@ int tracker_mem_sync_storages(FDFSGroupInfo *pGroup, \ continue; } - memcpy(target_storage.id, pServer->id, \ + memcpy(target_storage.id, pServer->id, FDFS_STORAGE_ID_MAX_SIZE); pTargetStorage = &target_storage; - if ((ppFound=(FDFSStorageDetail **)bsearch( \ - &pTargetStorage, \ - pGroup->sorted_servers, \ - pGroup->count, \ - sizeof(FDFSStorageDetail *), \ + if ((ppFound=(FDFSStorageDetail **)bsearch( + &pTargetStorage, + pGroup->sorted_servers, + pGroup->count, + sizeof(FDFSStorageDetail *), tracker_mem_cmp_by_storage_id)) != NULL) { if ((*ppFound)->status == pServer->status \ @@ -4946,7 +4952,7 @@ int tracker_mem_sync_storages(FDFSGroupInfo *pGroup, \ &pStorageServer, pServer->id, pServer->ip_addr, true, false, &bInserted); - if (result != 0) + if (result == 0 && bInserted) { pStorageServer->status = pServer->status; } diff --git a/tracker/tracker_mem.h b/tracker/tracker_mem.h index 0d8273f..4083bfb 100644 --- a/tracker/tracker_mem.h +++ b/tracker/tracker_mem.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //tracker_mem.h diff --git a/tracker/tracker_nio.c b/tracker/tracker_nio.c index 51b1f24..92f230f 100644 --- a/tracker/tracker_nio.c +++ b/tracker/tracker_nio.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include @@ -134,10 +134,11 @@ void recv_notify_read(int sock, short event, void *arg) pTask = free_queue_pop(); if (pTask == NULL) { - logError("file: "__FILE__", line: %d, " \ - "malloc task buff failed, you should " \ - "increase the parameter: max_connections", \ - __LINE__); + logError("file: "__FILE__", line: %d, " + "malloc task buff fail, you should " + "increase the parameter \"max_connections\" " + "in tracker.conf, or check your applications " + "for connection leaks", __LINE__); close(incomesock); continue; } @@ -198,21 +199,33 @@ static void client_sock_read(int sock, short event, void *arg) if (event & IOEVENT_TIMEOUT) { - if (pTask->offset == 0 && pTask->req_count > 0) + if (pTask->offset == 0) { - pTask->event.timer.expires = g_current_time + - g_fdfs_network_timeout; - fast_timer_add(&pTask->thread_data->timer, - &pTask->event.timer); + if (pTask->req_count > 0) + { + pTask->event.timer.expires = g_current_time + + g_fdfs_network_timeout; + fast_timer_add(&pTask->thread_data->timer, + &pTask->event.timer); + } + else + { + logWarning("file: "__FILE__", line: %d, " + "client ip: %s, recv timeout. " + "after the connection is established, " + "you must send a request before %ds timeout, " + "maybe connections leak in you application.", + __LINE__, pTask->client_ip, g_fdfs_network_timeout); + task_finish_clean_up(pTask); + } } else { - logError("file: "__FILE__", line: %d, " \ - "client ip: %s, recv timeout, " \ - "recv offset: %d, expect length: %d", \ - __LINE__, pTask->client_ip, \ - pTask->offset, pTask->length); - + logError("file: "__FILE__", line: %d, " + "client ip: %s, recv timeout, " + "recv offset: %d, expect length: %d, " + "req_count: %"PRId64, __LINE__, pTask->client_ip, + pTask->offset, pTask->length, pTask->req_count); task_finish_clean_up(pTask); } diff --git a/tracker/tracker_nio.h b/tracker/tracker_nio.h index e4625d4..85140a8 100644 --- a/tracker/tracker_nio.h +++ b/tracker/tracker_nio.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //tracker_nio.h diff --git a/tracker/tracker_proto.c b/tracker/tracker_proto.c index 3e737b7..a319193 100644 --- a/tracker/tracker_proto.c +++ b/tracker/tracker_proto.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include @@ -24,19 +24,20 @@ #include "tracker_proto.h" #include "fdfs_shared_func.h" -int fdfs_recv_header(ConnectionInfo *pTrackerServer, int64_t *in_bytes) +int fdfs_recv_header_ex(ConnectionInfo *pTrackerServer, + const int network_timeout, int64_t *in_bytes) { TrackerHeader resp; int result; - if ((result=tcprecvdata_nb(pTrackerServer->sock, &resp, \ - sizeof(resp), g_fdfs_network_timeout)) != 0) + if ((result=tcprecvdata_nb(pTrackerServer->sock, &resp, + sizeof(resp), network_timeout)) != 0) { - logError("file: "__FILE__", line: %d, " \ - "server: %s:%d, recv data fail, " \ - "errno: %d, error info: %s", \ - __LINE__, pTrackerServer->ip_addr, \ - pTrackerServer->port, \ + logError("file: "__FILE__", line: %d, " + "server: %s:%d, recv data fail, " + "errno: %d, error info: %s", + __LINE__, pTrackerServer->ip_addr, + pTrackerServer->port, result, STRERROR(result)); *in_bytes = 0; return result; @@ -56,10 +57,10 @@ int fdfs_recv_header(ConnectionInfo *pTrackerServer, int64_t *in_bytes) *in_bytes = buff2long(resp.pkg_len); if (*in_bytes < 0) { - logError("file: "__FILE__", line: %d, " \ - "server: %s:%d, recv package size " \ - "%"PRId64" is not correct", \ - __LINE__, pTrackerServer->ip_addr, \ + logError("file: "__FILE__", line: %d, " + "server: %s:%d, recv package size " + "%"PRId64" is not correct", + __LINE__, pTrackerServer->ip_addr, pTrackerServer->port, *in_bytes); *in_bytes = 0; return EINVAL; diff --git a/tracker/tracker_proto.h b/tracker/tracker_proto.h index e37fd6c..41069dd 100644 --- a/tracker/tracker_proto.h +++ b/tracker/tracker_proto.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //tracker_proto.h @@ -12,6 +12,7 @@ #define _TRACKER_PROTO_H_ #include "tracker_types.h" +#include "fdfs_global.h" #include "fastcommon/connection_pool.h" #include "fastcommon/ini_file_reader.h" @@ -35,6 +36,7 @@ #define TRACKER_PROTO_CMD_STORAGE_GET_STATUS 71 //get storage status from tracker #define TRACKER_PROTO_CMD_STORAGE_GET_SERVER_ID 70 //get storage server id from tracker #define TRACKER_PROTO_CMD_STORAGE_GET_MY_IP 60 //get storage server ip from tracker +#define TRACKER_PROTO_CMD_STORAGE_CHANGE_STATUS 59 //current storage can change it's status #define TRACKER_PROTO_CMD_STORAGE_FETCH_STORAGE_IDS 69 //get all storage ids from tracker #define TRACKER_PROTO_CMD_STORAGE_GET_GROUP_NAME 109 //get storage group name from tracker @@ -78,7 +80,7 @@ #define STORAGE_PROTO_CMD_UPLOAD_SLAVE_FILE 21 #define STORAGE_PROTO_CMD_QUERY_FILE_INFO 22 #define STORAGE_PROTO_CMD_UPLOAD_APPENDER_FILE 23 //create appender file -#define STORAGE_PROTO_CMD_APPEND_FILE 24 //append file +#define STORAGE_PROTO_CMD_APPEND_FILE 24 //append file #define STORAGE_PROTO_CMD_SYNC_APPEND_FILE 25 #define STORAGE_PROTO_CMD_FETCH_ONE_PATH_BINLOG 26 //fetch binlog of one store path #define STORAGE_PROTO_CMD_RESP TRACKER_PROTO_CMD_RESP @@ -92,10 +94,12 @@ #define STORAGE_PROTO_CMD_TRUNK_DELETE_BINLOG_MARKS 32 //since V3.07, tracker to storage #define STORAGE_PROTO_CMD_TRUNK_TRUNCATE_BINLOG_FILE 33 //since V3.07, trunk storage to storage -#define STORAGE_PROTO_CMD_MODIFY_FILE 34 //since V3.08 -#define STORAGE_PROTO_CMD_SYNC_MODIFY_FILE 35 //since V3.08 -#define STORAGE_PROTO_CMD_TRUNCATE_FILE 36 //since V3.08 -#define STORAGE_PROTO_CMD_SYNC_TRUNCATE_FILE 37 //since V3.08 +#define STORAGE_PROTO_CMD_MODIFY_FILE 34 //since V3.08 +#define STORAGE_PROTO_CMD_SYNC_MODIFY_FILE 35 //since V3.08 +#define STORAGE_PROTO_CMD_TRUNCATE_FILE 36 //since V3.08 +#define STORAGE_PROTO_CMD_SYNC_TRUNCATE_FILE 37 //since V3.08 +#define STORAGE_PROTO_CMD_REGENERATE_APPENDER_FILENAME 38 //since V6.02, rename appender file to normal file +#define STORAGE_PROTO_CMD_SYNC_RENAME_FILE 40 //since V6.02 //for overwrite all old metadata #define STORAGE_SET_METADATA_FLAG_OVERWRITE 'O' @@ -144,6 +148,7 @@ typedef struct typedef struct { + unsigned char my_status; //storage server status char src_id[FDFS_STORAGE_ID_MAX_SIZE]; //src storage id } TrackerStorageJoinBodyResp; @@ -283,7 +288,15 @@ int metadata_cmp_by_name(const void *p1, const void *p2); const char *get_storage_status_caption(const int status); -int fdfs_recv_header(ConnectionInfo *pTrackerServer, int64_t *in_bytes); +int fdfs_recv_header_ex(ConnectionInfo *pTrackerServer, + const int network_timeout, int64_t *in_bytes); + +static inline int fdfs_recv_header(ConnectionInfo *pTrackerServer, + int64_t *in_bytes) +{ + return fdfs_recv_header_ex(pTrackerServer, + g_fdfs_network_timeout, in_bytes); +} int fdfs_recv_response(ConnectionInfo *pTrackerServer, \ char **buff, const int buff_size, \ diff --git a/tracker/tracker_relationship.c b/tracker/tracker_relationship.c index 60fc3f9..dd38457 100644 --- a/tracker/tracker_relationship.c +++ b/tracker/tracker_relationship.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ #include @@ -177,6 +177,21 @@ static int relationship_cmp_tracker_status(const void *p1, const void *p2) return conn1->port - conn2->port; } +static int relationship_get_tracker_status(TrackerRunningStatus *pStatus) +{ + if (fdfs_server_contain_local_service(pStatus->pTrackerServer, + g_server_port)) + { + tracker_calc_running_times(pStatus); + pStatus->if_leader = g_if_leader_self; + return 0; + } + else + { + return fdfs_get_tracker_status(pStatus->pTrackerServer, pStatus); + } +} + static int relationship_get_tracker_leader(TrackerRunningStatus *pTrackerStatus) { TrackerServerInfo *pTrackerServer; @@ -196,7 +211,7 @@ static int relationship_get_tracker_leader(TrackerRunningStatus *pTrackerStatus) pTrackerServerpTrackerServer = pTrackerServer; - r = fdfs_get_tracker_status(pTrackerServer, pStatus); + r = relationship_get_tracker_status(pStatus); if (r == 0) { pStatus++; @@ -237,14 +252,6 @@ static int relationship_get_tracker_leader(TrackerRunningStatus *pTrackerStatus) return 0; } -#define relationship_notify_next_leader(pTrackerServer, pLeader, bConnectFail) \ - do_notify_leader_changed(pTrackerServer, pLeader, \ - TRACKER_PROTO_CMD_TRACKER_NOTIFY_NEXT_LEADER, bConnectFail) - -#define relationship_commit_next_leader(pTrackerServer, pLeader, bConnectFail) \ - do_notify_leader_changed(pTrackerServer, pLeader, \ - TRACKER_PROTO_CMD_TRACKER_COMMIT_NEXT_LEADER, bConnectFail) - static int do_notify_leader_changed(TrackerServerInfo *pTrackerServer, \ ConnectionInfo *pLeader, const char cmd, bool *bConnectFail) { @@ -320,7 +327,74 @@ static int do_notify_leader_changed(TrackerServerInfo *pTrackerServer, \ return result; } -static int relationship_notify_leader_changed(ConnectionInfo *pLeader) +void relationship_set_tracker_leader(const int server_index, + ConnectionInfo *pLeader, const bool leader_self) +{ + g_tracker_servers.leader_index = server_index; + g_next_leader_index = -1; + + if (leader_self) + { + g_if_leader_self = true; + g_tracker_leader_chg_count++; + } + else + { + logInfo("file: "__FILE__", line: %d, " + "the tracker leader is %s:%d", __LINE__, + pLeader->ip_addr, pLeader->port); + } +} + +static int relationship_notify_next_leader(TrackerServerInfo *pTrackerServer, + TrackerRunningStatus *pTrackerStatus, bool *bConnectFail) +{ + if (pTrackerStatus->pTrackerServer == pTrackerServer) + { + g_next_leader_index = pTrackerServer - g_tracker_servers.servers; + return 0; + } + else + { + ConnectionInfo *pLeader; + pLeader = pTrackerStatus->pTrackerServer->connections; + return do_notify_leader_changed(pTrackerServer, pLeader, + TRACKER_PROTO_CMD_TRACKER_NOTIFY_NEXT_LEADER, bConnectFail); + } +} + +static int relationship_commit_next_leader(TrackerServerInfo *pTrackerServer, + TrackerRunningStatus *pTrackerStatus, bool *bConnectFail) +{ + ConnectionInfo *pLeader; + + pLeader = pTrackerStatus->pTrackerServer->connections; + if (pTrackerStatus->pTrackerServer == pTrackerServer) + { + int server_index; + int expect_index; + server_index = g_next_leader_index; + expect_index = pTrackerServer - g_tracker_servers.servers; + if (server_index != expect_index) + { + logError("file: "__FILE__", line: %d, " + "g_next_leader_index: %d != expected: %d", + __LINE__, server_index, expect_index); + g_next_leader_index = -1; + return EBUSY; + } + + relationship_set_tracker_leader(server_index, pLeader, true); + return 0; + } + else + { + return do_notify_leader_changed(pTrackerServer, pLeader, + TRACKER_PROTO_CMD_TRACKER_COMMIT_NEXT_LEADER, bConnectFail); + } +} + +static int relationship_notify_leader_changed(TrackerRunningStatus *pTrackerStatus) { TrackerServerInfo *pTrackerServer; TrackerServerInfo *pTrackerEnd; @@ -331,11 +405,11 @@ static int relationship_notify_leader_changed(ConnectionInfo *pLeader) result = ENOENT; pTrackerEnd = g_tracker_servers.servers + g_tracker_servers.server_count; success_count = 0; - for (pTrackerServer=g_tracker_servers.servers; \ + for (pTrackerServer=g_tracker_servers.servers; pTrackerServerconnections; - if (conn->port == g_server_port && is_local_host_ip(conn->ip_addr)) + if (fdfs_server_contain_local_service(trackerStatus. + pTrackerServer, g_server_port)) { - if ((result=relationship_notify_leader_changed(conn)) != 0) + if ((result=relationship_notify_leader_changed( + &trackerStatus)) != 0) { return result; } @@ -416,11 +492,11 @@ static int relationship_select_leader() { if (trackerStatus.if_leader) { - g_tracker_servers.leader_index = \ - trackerStatus.pTrackerServer - \ + g_tracker_servers.leader_index = + trackerStatus.pTrackerServer - g_tracker_servers.servers; - if (g_tracker_servers.leader_index < 0 || \ - g_tracker_servers.leader_index >= \ + if (g_tracker_servers.leader_index < 0 || + g_tracker_servers.leader_index >= g_tracker_servers.server_count) { logError("file: "__FILE__", line: %d, " @@ -429,12 +505,15 @@ static int relationship_select_leader() g_tracker_servers.leader_index = -1; return EINVAL; } + } + if (g_tracker_servers.leader_index >= 0) + { logInfo("file: "__FILE__", line: %d, " "the tracker leader %s:%d", __LINE__, conn->ip_addr, conn->port); - } - else + } + else { logInfo("file: "__FILE__", line: %d, " "waiting for the candidate tracker leader %s:%d notify ...", @@ -483,9 +562,9 @@ static void *relationship_thread_entrance(void* arg) int sleep_seconds; fail_count = 0; + sleep_seconds = 1; while (g_continue_flag) { - sleep_seconds = 1; if (g_tracker_servers.servers != NULL) { if (g_tracker_servers.leader_index < 0) @@ -495,20 +574,48 @@ static void *relationship_thread_entrance(void* arg) sleep_seconds = 1 + (int)((double)rand() * (double)MAX_SLEEP_SECONDS / RAND_MAX); } + else + { + sleep_seconds = 1; + } } else { + int leader_index; + leader_index = g_tracker_servers.leader_index; if (relationship_ping_leader() == 0) { fail_count = 0; + sleep_seconds = 1; } else { - fail_count++; + char leader_str[64]; + ConnectionInfo *pLeader; + + if (leader_index < 0) + { + strcpy(leader_str, "unknown leader"); + } + else + { + pLeader = g_tracker_servers.servers + [leader_index].connections; + sprintf(leader_str, "leader %s:%d", + pLeader->ip_addr, pLeader->port); + } + + ++fail_count; + logError("file: "__FILE__", line: %d, " + "%dth ping %s fail", __LINE__, + fail_count, leader_str); + + sleep_seconds *= 2; if (fail_count >= 3) { g_tracker_servers.leader_index = -1; fail_count = 0; + sleep_seconds = 1; } } } diff --git a/tracker/tracker_relationship.h b/tracker/tracker_relationship.h index 69fd9f3..b51ee81 100644 --- a/tracker/tracker_relationship.h +++ b/tracker/tracker_relationship.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //tracker_relationship.h @@ -24,6 +24,9 @@ extern bool g_if_leader_self; //if I am leader int tracker_relationship_init(); int tracker_relationship_destroy(); +void relationship_set_tracker_leader(const int server_index, + ConnectionInfo *pLeader, const bool if_leader_self); + #ifdef __cplusplus } #endif diff --git a/tracker/tracker_service.c b/tracker/tracker_service.c index 02ca9bb..372bedd 100644 --- a/tracker/tracker_service.c +++ b/tracker/tracker_service.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //tracker_service.c @@ -413,8 +413,10 @@ static int tracker_check_and_sync(struct fast_task_info *pTask, \ pDestServer->status = pServer->status; memcpy(pDestServer->id, pServer->id, FDFS_STORAGE_ID_MAX_SIZE); - memcpy(pDestServer->ip_addr, FDFS_CURRENT_IP_ADDR(pServer), - IP_ADDRESS_SIZE); + memcpy(pDestServer->ip_addr, + fdfs_get_ipaddr_by_peer_ip(&pServer->ip_addrs, + pTask->client_ip), IP_ADDRESS_SIZE); + int2buff(pClientInfo->pGroup->storage_port, pDestServer->port); } @@ -438,8 +440,9 @@ static int tracker_check_and_sync(struct fast_task_info *pTask, \ pDestServer->status = (*ppServer)->status; memcpy(pDestServer->id, (*ppServer)->id, FDFS_STORAGE_ID_MAX_SIZE); - memcpy(pDestServer->ip_addr, FDFS_CURRENT_IP_ADDR(*ppServer), - IP_ADDRESS_SIZE); + memcpy(pDestServer->ip_addr, + fdfs_get_ipaddr_by_peer_ip(&(*ppServer)->ip_addrs, + pTask->client_ip), IP_ADDRESS_SIZE); int2buff(pClientInfo->pGroup->storage_port, pDestServer->port); pDestServer++; @@ -588,14 +591,14 @@ static int tracker_deal_changelog_req(struct fast_task_info *pTask) break; } - memcpy(group_name, pTask->data + sizeof(TrackerHeader), \ + memcpy(group_name, pTask->data + sizeof(TrackerHeader), FDFS_GROUP_NAME_MAX_LEN); *(group_name + FDFS_GROUP_NAME_MAX_LEN) = '\0'; pGroup = tracker_mem_get_group(group_name); if (pGroup == NULL) { - logError("file: "__FILE__", line: %d, " \ - "client ip: %s, invalid group_name: %s", \ + logError("file: "__FILE__", line: %d, " + "client ip: %s, group_name: %s not exist", __LINE__, pTask->client_ip, group_name); result = ENOENT; break; @@ -658,59 +661,73 @@ static int tracker_deal_get_trunk_fid(struct fast_task_info *pTask) static int tracker_deal_parameter_req(struct fast_task_info *pTask) { char reserved_space_str[32]; + int body_len; if (pTask->length - sizeof(TrackerHeader) != 0) { - logError("file: "__FILE__", line: %d, " \ - "cmd=%d, client ip: %s, package size " \ - PKG_LEN_PRINTF_FORMAT" is not correct, " \ - "expect length = %d", __LINE__, \ - TRACKER_PROTO_CMD_STORAGE_PARAMETER_REQ, \ - pTask->client_ip, pTask->length - \ + logError("file: "__FILE__", line: %d, " + "cmd=%d, client ip: %s, package size " + PKG_LEN_PRINTF_FORMAT" is not correct, " + "expect length = %d", __LINE__, + TRACKER_PROTO_CMD_STORAGE_PARAMETER_REQ, + pTask->client_ip, pTask->length - (int)sizeof(TrackerHeader), 0); pTask->length = sizeof(TrackerHeader); return EINVAL; } - pTask->length = sizeof(TrackerHeader) + \ - sprintf(pTask->data + sizeof(TrackerHeader), \ - "use_storage_id=%d\n" \ - "id_type_in_filename=%s\n" \ - "storage_ip_changed_auto_adjust=%d\n" \ - "storage_sync_file_max_delay=%d\n" \ - "store_path=%d\n" \ - "reserved_storage_space=%s\n" \ - "use_trunk_file=%d\n" \ - "slot_min_size=%d\n" \ - "slot_max_size=%d\n" \ - "trunk_file_size=%d\n" \ - "trunk_create_file_advance=%d\n" \ - "trunk_create_file_time_base=%02d:%02d\n" \ - "trunk_create_file_interval=%d\n" \ - "trunk_create_file_space_threshold=%"PRId64"\n" \ - "trunk_init_check_occupying=%d\n" \ - "trunk_init_reload_from_binlog=%d\n" \ - "trunk_compress_binlog_min_interval=%d\n" \ - "store_slave_file_use_link=%d\n", \ - g_use_storage_id, g_id_type_in_filename == \ - FDFS_ID_TYPE_SERVER_ID ? "id" : "ip", \ - g_storage_ip_changed_auto_adjust, \ - g_storage_sync_file_max_delay, g_groups.store_path, \ - fdfs_storage_reserved_space_to_string( \ - &g_storage_reserved_space, reserved_space_str), \ - g_if_use_trunk_file, \ - g_slot_min_size, g_slot_max_size, \ - g_trunk_file_size, g_trunk_create_file_advance, \ - g_trunk_create_file_time_base.hour, \ - g_trunk_create_file_time_base.minute, \ - g_trunk_create_file_interval, \ - g_trunk_create_file_space_threshold, \ - g_trunk_init_check_occupying, \ - g_trunk_init_reload_from_binlog, \ - g_trunk_compress_binlog_min_interval, \ - g_store_slave_file_use_link); + body_len = sprintf(pTask->data + sizeof(TrackerHeader), + "use_storage_id=%d\n" + "id_type_in_filename=%s\n" + "storage_ip_changed_auto_adjust=%d\n" + "storage_sync_file_max_delay=%d\n" + "store_path=%d\n" + "reserved_storage_space=%s\n" + "use_trunk_file=%d\n" + "slot_min_size=%d\n" + "slot_max_size=%d\n" + "trunk_alloc_alignment_size=%d\n" + "trunk_file_size=%d\n" + "trunk_create_file_advance=%d\n" + "trunk_create_file_time_base=%02d:%02d\n" + "trunk_create_file_interval=%d\n" + "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" + "delete_unused_trunk_files=%d\n" + "trunk_compress_binlog_min_interval=%d\n" + "trunk_compress_binlog_interval=%d\n" + "trunk_compress_binlog_time_base=%02d:%02d\n" + "trunk_binlog_max_backups=%d\n" + "store_slave_file_use_link=%d\n", + g_use_storage_id, g_id_type_in_filename == + FDFS_ID_TYPE_SERVER_ID ? "id" : "ip", + g_storage_ip_changed_auto_adjust, + g_storage_sync_file_max_delay, g_groups.store_path, + fdfs_storage_reserved_space_to_string( + &g_storage_reserved_space, reserved_space_str), + g_if_use_trunk_file, + g_slot_min_size, g_slot_max_size, + g_trunk_alloc_alignment_size, + g_trunk_file_size, g_trunk_create_file_advance, + g_trunk_create_file_time_base.hour, + g_trunk_create_file_time_base.minute, + g_trunk_create_file_interval, + g_trunk_create_file_space_threshold, + g_trunk_init_check_occupying, + g_trunk_init_reload_from_binlog, + g_trunk_free_space_merge, + g_delete_unused_trunk_files, + g_trunk_compress_binlog_min_interval, + g_trunk_compress_binlog_interval, + g_trunk_compress_binlog_time_base.hour, + g_trunk_compress_binlog_time_base.minute, + g_trunk_binlog_max_backups, + g_store_slave_file_use_link); + pTask->length = sizeof(TrackerHeader) + body_len; return 0; } @@ -897,8 +914,8 @@ static int tracker_deal_notify_next_leader(struct fast_task_info *pTask) return ENOENT; } - if (g_if_leader_self && (leader.port != g_server_port || \ - !is_local_host_ip(leader.ip_addr))) + if (g_if_leader_self && !(leader.port == g_server_port && + is_local_host_ip(leader.ip_addr))) { g_if_leader_self = false; g_tracker_servers.leader_index = -1; @@ -922,6 +939,7 @@ static int tracker_deal_commit_next_leader(struct fast_task_info *pTask) char *ipAndPort[2]; ConnectionInfo leader; int server_index; + bool leader_self; if (pTask->length - sizeof(TrackerHeader) != FDFS_PROTO_IP_PORT_SIZE) { @@ -969,19 +987,9 @@ static int tracker_deal_commit_next_leader(struct fast_task_info *pTask) return EINVAL; } - g_tracker_servers.leader_index = server_index; - g_next_leader_index = -1; - if (leader.port == g_server_port && is_local_host_ip(leader.ip_addr)) - { - g_if_leader_self = true; - g_tracker_leader_chg_count++; - } - else - { - logInfo("file: "__FILE__", line: %d, " \ - "the tracker leader is %s:%d", __LINE__, \ - leader.ip_addr, leader.port); - } + leader_self = (leader.port == g_server_port) && + is_local_host_ip(leader.ip_addr); + relationship_set_tracker_leader(server_index, &leader, leader_self); return 0; } @@ -1054,7 +1062,7 @@ static int tracker_deal_server_get_storage_status(struct fast_task_info *pTask) pDest = (FDFSStorageBrief *)(pTask->data + sizeof(TrackerHeader)); memset(pDest, 0, sizeof(FDFSStorageBrief)); strcpy(pDest->id, pStorage->id); - strcpy(pDest->ip_addr, pStorage->ip_addrs.ips[0]); + strcpy(pDest->ip_addr, pStorage->ip_addrs.ips[0].address); pDest->status = pStorage->status; int2buff(pGroup->storage_port, pDest->port); @@ -1382,6 +1390,59 @@ static int tracker_deal_storage_report_status(struct fast_task_info *pTask) return tracker_mem_sync_storages(pGroup, briefServers, 1); } +static int tracker_deal_storage_change_status(struct fast_task_info *pTask) +{ + TrackerClientInfo *pClientInfo; + int old_status; + int new_status; + + if (pTask->length - sizeof(TrackerHeader) != 1) + { + logError("file: "__FILE__", line: %d, " + "cmd=%d, client ip addr: %s, " + "body size "PKG_LEN_PRINTF_FORMAT" " + "is not correct", __LINE__, + TRACKER_PROTO_CMD_STORAGE_CHANGE_STATUS, + pTask->client_ip, pTask->length - + (int)sizeof(TrackerHeader)); + pTask->length = sizeof(TrackerHeader); + return EINVAL; + } + + pClientInfo = (TrackerClientInfo *)pTask->arg; + old_status = pClientInfo->pStorage->status; + pTask->length = sizeof(TrackerHeader); + + new_status = *(pTask->data + sizeof(TrackerHeader)); + if ((old_status == new_status) || + (FDFS_IS_AVAILABLE_STATUS(old_status) && + FDFS_IS_AVAILABLE_STATUS(new_status))) + { + logInfo("file: "__FILE__", line: %d, " + "client ip: %s, do NOT change storage status, " + "old status: %d (%s), new status: %d (%s)", + __LINE__, pTask->client_ip, + old_status, get_storage_status_caption(old_status), + new_status, get_storage_status_caption(new_status)); + return 0; + } + if (new_status == FDFS_STORAGE_STATUS_ONLINE || + new_status == FDFS_STORAGE_STATUS_ACTIVE) + { + new_status = FDFS_STORAGE_STATUS_OFFLINE; + } + + pClientInfo->pStorage->status = new_status; + tracker_save_storages(); + + logInfo("file: "__FILE__", line: %d, " + "client ip: %s, set storage status from %d (%s) " + "to %d (%s)", __LINE__, pTask->client_ip, + old_status, get_storage_status_caption(old_status), + new_status, get_storage_status_caption(new_status)); + return 0; +} + static int tracker_deal_storage_join(struct fast_task_info *pTask) { TrackerStorageJoinBodyResp *pJoinBodyResp; @@ -1552,17 +1613,18 @@ static int tracker_deal_storage_join(struct fast_task_info *pTask) return result; } - pJoinBodyResp = (TrackerStorageJoinBodyResp *)(pTask->data + \ + pJoinBodyResp = (TrackerStorageJoinBodyResp *)(pTask->data + sizeof(TrackerHeader)); memset(pJoinBodyResp, 0, sizeof(TrackerStorageJoinBodyResp)); + pJoinBodyResp->my_status = pClientInfo->pStorage->status; if (pClientInfo->pStorage->psync_src_server != NULL) { - strcpy(pJoinBodyResp->src_id, \ + strcpy(pJoinBodyResp->src_id, pClientInfo->pStorage->psync_src_server->id); } - pTask->length = sizeof(TrackerHeader) + \ + pTask->length = sizeof(TrackerHeader) + sizeof(TrackerStorageJoinBodyResp); return 0; } @@ -2337,7 +2399,7 @@ static int tracker_deal_server_list_group_storages(struct fast_task_info *pTask) pStorageId = NULL; } - memset(pTask->data + sizeof(TrackerHeader), 0, \ + memset(pTask->data + sizeof(TrackerHeader), 0, pTask->size - sizeof(TrackerHeader)); pDest = pStart = (TrackerStorageStat *)(pTask->data + \ sizeof(TrackerHeader)); @@ -2355,7 +2417,8 @@ static int tracker_deal_server_list_group_storages(struct fast_task_info *pTask) pStorageStat = &((*ppServer)->stat); pDest->status = (*ppServer)->status; strcpy(pDest->id, (*ppServer)->id); - strcpy(pDest->ip_addr, FDFS_CURRENT_IP_ADDR(*ppServer)); + strcpy(pDest->ip_addr, fdfs_get_ipaddr_by_peer_ip( + &(*ppServer)->ip_addrs, pTask->client_ip)); if ((*ppServer)->psync_src_server != NULL) { strcpy(pDest->src_id, \ @@ -2554,11 +2617,12 @@ static int tracker_deal_service_query_fetch_update( \ } - pTask->length = sizeof(TrackerHeader) + \ - TRACKER_QUERY_STORAGE_FETCH_BODY_LEN + \ + pTask->length = sizeof(TrackerHeader) + + TRACKER_QUERY_STORAGE_FETCH_BODY_LEN + (server_count - 1) * (IP_ADDRESS_SIZE - 1); p = pTask->data + sizeof(TrackerHeader); + memset(p, 0, pTask->length - sizeof(TrackerHeader)); memcpy(p, pGroup->group_name, FDFS_GROUP_NAME_MAX_LEN); p += FDFS_GROUP_NAME_MAX_LEN; strcpy(p, fdfs_get_ipaddr_by_peer_ip( @@ -2946,6 +3010,8 @@ static int tracker_deal_service_query_storage( \ return ENOENT; } + memset(p, 0, active_count * (IP_ADDRESS_SIZE + + FDFS_PROTO_PKG_LEN_SIZE)); ppEnd = pStoreGroup->active_servers + active_count; for (ppServer=pStoreGroup->active_servers; ppServerip_addrs, pTask->client_ip)); p += IP_ADDRESS_SIZE - 1; @@ -3863,6 +3930,10 @@ int tracker_deal_task(struct fast_task_info *pTask) case TRACKER_PROTO_CMD_STORAGE_REPORT_STATUS: result = tracker_deal_storage_report_status(pTask); break; + case TRACKER_PROTO_CMD_STORAGE_CHANGE_STATUS: + TRACKER_CHECK_LOGINED(pTask) + result = tracker_deal_storage_change_status(pTask); + break; case TRACKER_PROTO_CMD_STORAGE_GET_STATUS: result = tracker_deal_server_get_storage_status(pTask); break; diff --git a/tracker/tracker_service.h b/tracker/tracker_service.h index 62d56f3..b52d5db 100644 --- a/tracker/tracker_service.h +++ b/tracker/tracker_service.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //tracker_service.h diff --git a/tracker/tracker_status.c b/tracker/tracker_status.c index ce4e5ab..347d4ab 100644 --- a/tracker/tracker_status.c +++ b/tracker/tracker_status.c @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //tracker_func.c diff --git a/tracker/tracker_status.h b/tracker/tracker_status.h index c45b5e9..91629cc 100644 --- a/tracker/tracker_status.h +++ b/tracker/tracker_status.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //tracker_status.h diff --git a/tracker/tracker_types.h b/tracker/tracker_types.h index 04fc51e..b92002f 100644 --- a/tracker/tracker_types.h +++ b/tracker/tracker_types.h @@ -3,7 +3,7 @@ * * 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.csource.org/ for more detail. +* Please visit the FastDFS Home Page http://www.fastken.com/ for more detail. **/ //tracker_types.h @@ -117,6 +117,10 @@ #define FDFS_TRUNK_FILE_TRUE_SIZE(file_size) \ (file_size & 0xFFFFFFFF) +#define FDFS_FILE_TYPE_NORMAL 1 //normal file +#define FDFS_FILE_TYPE_APPENDER 2 //appender file +#define FDFS_FILE_TYPE_SLAVE 4 //slave file + #define FDFS_STORAGE_ID_MAX_SIZE 16 #define TRACKER_STORAGE_RESERVED_SPACE_FLAG_MB 0 @@ -272,15 +276,21 @@ typedef struct char sz_last_heart_beat_time[8]; } FDFSStorageStatBuff; +typedef struct StructFDFSIPInfo +{ + int type; //ip type + char address[IP_ADDRESS_SIZE]; +} FDFSIPInfo; + typedef struct StructFDFSMultiIP { int count; int index; - char ips[FDFS_MULTI_IP_MAX_COUNT][IP_ADDRESS_SIZE]; + FDFSIPInfo ips[FDFS_MULTI_IP_MAX_COUNT]; } FDFSMultiIP; #define FDFS_CURRENT_IP_ADDR(pServer) \ - (pServer)->ip_addrs.ips[(pServer)->ip_addrs.index] + (pServer)->ip_addrs.ips[(pServer)->ip_addrs.index].address typedef struct StructFDFSStorageDetail { @@ -454,11 +464,6 @@ typedef struct { } rs; } FDFSStorageReservedSpace; -typedef struct { - int count; //store path count - char **paths; //file store paths -} FDFSStorePaths; - typedef struct { TrackerServerInfo *pTrackerServer; int running_time; //running seconds, more means higher weight