多线程

作者原答案:多线程环境下,TrackerServerGroup必须每个线程一份。必须使用 fdfs_client_init_ex、tracker_get_connection_ex等函数。

在fastDFS中有一个 client_global.h的头文件,其中定义了一个全局变量
extern TrackerServerGroup g_tracker_group;
**fdfs_client_init** **tracker_get_connection** 等宏展开成的时候会传入这个全局变量

define fdfs_client_init(filename) \
fdfs_client_init_ex((&g_tracker_group), filename)

define fdfs_client_init_from_buffer(buffer) \
fdfs_client_init_from_buffer_ex((&g_tracker_group), buffer)

define fdfs_client_destroy() \
fdfs_client_destroy_ex((&g_tracker_group))

如果要在多线程下使用fastdfs,那么就要在每个线程包含一份TrackerServerGroup,并且使用_ex后缀的函数,而不是宏

线程安全版

FastDfs.h

  1. //
  2. // Created by wanghaitao on 2021/2/5.
  3. //
  4. #ifndef CLOUD_DISK_FASTDFS_H
  5. #define CLOUD_DISK_FASTDFS_H
  6. #include "fdfs_client.h"
  7. /**
  8. * local_filename不应超过64个字符
  9. */
  10. class FastDfs {
  11. public:
  12. /**
  13. * 操作fastDfs的api类
  14. * 不使用持久连接,每次上传、删除等操作都开启一个新连接
  15. * 目前未提供下载的api
  16. * @param conf_fileName 配置文件的路径
  17. */
  18. explicit FastDfs(const char * conf_fileName = nullptr);
  19. ~FastDfs();
  20. /**
  21. * 通过文件名上传文件
  22. * @param local_filename 本地文件名,not null,小于 64字符
  23. * @param remote_filename 返回远程文件名,不带group, not null
  24. * @throw FastDfsException 上传不成功
  25. */
  26. void file_upload_by_filename(const char * local_filename,char * remote_filename);
  27. /**
  28. * 通过文件缓存上传文件
  29. * @param buffer 文件缓存,not null
  30. * @param file_size 文件大小
  31. * @param local_filename 本地文件名,not null,小于 64字符
  32. * @param remote_filename 返回远程文件名,不带group, not null
  33. * @param meta_data 文件元数据,可以null
  34. * @param meta_count 元数据数量, 可以null
  35. // 元数据构造示例
  36. FDFSMetaData meta_data[Max_Meta_Date_num];
  37. int meta_count = 0;
  38. strcpy(meta_data[meta_count].name,"File");
  39. strcpy(meta_data[meta_count++].value,local_filename);
  40. * @throw FastDfsException 上传不成功
  41. */
  42. void file_upload_by_buffer(const char * buffer,const int file_size, const char * local_filename, char * remote_filename,
  43. const FDFSMetaData * meta_data,const int meta_count);
  44. /**
  45. * 删除文件
  46. * @param remote_filename 要删除的远程文件名
  47. * @throw FastDfsException 删除出错
  48. */
  49. void file_delete_by_remote_filename(const char * remote_filename);
  50. private:
  51. TrackerServerGroup tracker_group;
  52. };
  53. #endif //CLOUD_DISK_FASTDFS_H

Exceptions.h

  1. class FastDfsException: public std::exception{
  2. public:
  3. const char * what() const noexcept override;
  4. explicit FastDfsException(int errorNumber):_what(strerror(errorNumber)){}
  5. explicit FastDfsException(const char * what):_what(what){}
  6. private:
  7. std::string _what;
  8. };

FastDfs.cpp

  1. //
  2. // Created by wanghaitao on 2021/2/5.
  3. //
  4. #include "FastDfs.h"
  5. #include "Exceptions.h"
  6. #include "make_log.h"
  7. #include "tracker_proto.h"
  8. static const char *FastDfs_DEFAULT_CONF_FILENAME = "/etc/fdfs/client.conf";
  9. static const char *Log_Dir = "FastDfs";
  10. static const int Max_Meta_Date_num=5;
  11. FastDfs::FastDfs(const char * conf_fileName) {
  12. if (conf_fileName == nullptr)
  13. conf_fileName = FastDfs_DEFAULT_CONF_FILENAME;
  14. int code;
  15. if ((code = fdfs_client_init_ex(&tracker_group, conf_fileName)) != 0) {
  16. throw FastDfsException(code);
  17. }
  18. }
  19. FastDfs::~FastDfs() {
  20. fdfs_client_destroy_ex(&tracker_group);
  21. }
  22. void FastDfs::file_upload_by_filename(const char *local_filename, char *remote_filename) {
  23. if (local_filename == nullptr) {
  24. throw FastDfsException("on upload by filename: local filename should not be null");
  25. }
  26. if (remote_filename == nullptr) {
  27. throw FastDfsException("on upload by filename: remote filename should not be null");
  28. }
  29. char group_name[FDFS_GROUP_NAME_MAX_LEN + 1];
  30. ConnectionInfo *pTrackerServer;
  31. int code;
  32. int store_path_index;
  33. ConnectionInfo storageServer;
  34. code = ignore_signal_pipe();
  35. if (code != 0) {
  36. LOG(Log_Dir, "filenameUploadErroe", "ignore signal pipe error");
  37. throw FastDfsException(code);
  38. }
  39. // 连tracker,然后连storage
  40. pTrackerServer = tracker_get_connection_ex(&tracker_group);
  41. if (pTrackerServer == nullptr) {
  42. code = errno != 0 ? errno : ECONNREFUSED;
  43. LOG(Log_Dir, "filenameUploadErroe", "connect to track server error, error info: %s", strerror(code));
  44. throw FastDfsException(code);
  45. }
  46. *group_name = '\0';
  47. if ((code = tracker_query_storage_store(pTrackerServer, \
  48. &storageServer, group_name, &store_path_index)) != 0) {
  49. LOG(Log_Dir, "filenameUploadErroe", "tracker_query_storage fail, error info: %s\n", strerror(code));
  50. throw FastDfsException(code);
  51. }
  52. // 传文件
  53. code = storage_upload_by_filename1_ex(pTrackerServer,
  54. &storageServer, store_path_index,
  55. STORAGE_PROTO_CMD_UPLOAD_APPENDER_FILE, local_filename,
  56. nullptr, nullptr, 0, group_name, remote_filename);
  57. tracker_disconnect_server_ex(pTrackerServer, true);
  58. if (code != 0) {
  59. LOG(Log_Dir, "filenameUploadErroe", "upload file fail, error info: %s\n", strerror(code));
  60. throw FastDfsException(code);
  61. }
  62. }
  63. void FastDfs::file_upload_by_buffer(const char *buffer,const int file_size, const char *local_filename, char *remote_filename,
  64. const FDFSMetaData * meta_data,const int meta_count) {
  65. if (local_filename == nullptr) {
  66. throw FastDfsException("on upload by buffer: local filename should not be null");
  67. }
  68. if (remote_filename == nullptr) {
  69. throw FastDfsException("on upload by buffer: remote filename should not be null");
  70. }
  71. if (buffer == nullptr) {
  72. throw FastDfsException("on upload by buffer: buffer should not be null");
  73. }
  74. char group_name[FDFS_GROUP_NAME_MAX_LEN + 1];
  75. ConnectionInfo *pTrackerServer;
  76. int code;
  77. int store_path_index;
  78. ConnectionInfo storageServer;
  79. code = ignore_signal_pipe();
  80. if (code != 0) {
  81. LOG(Log_Dir, "bufferUploadError", "ignore signal pipe error");
  82. throw FastDfsException(code);
  83. }
  84. // 连tracker,然后连storage
  85. pTrackerServer = tracker_get_connection_ex(&tracker_group);
  86. if (pTrackerServer == nullptr) {
  87. code = errno != 0 ? errno : ECONNREFUSED;
  88. LOG(Log_Dir, "bufferUploadError", "connect to track server error, error info: %s", strerror(code));
  89. throw FastDfsException(code);
  90. }
  91. *group_name = '\0';
  92. if ((code = tracker_query_storage_store(pTrackerServer, \
  93. &storageServer, group_name, &store_path_index)) != 0) {
  94. LOG(Log_Dir, "bufferUploadError", "tracker_query_storage fail, error info: %s\n", strerror(code));
  95. throw FastDfsException(code);
  96. }
  97. // 生成文件扩展名
  98. const char * file_ext_name = nullptr;
  99. file_ext_name = strrchr(local_filename,'.');
  100. if(file_ext_name!= nullptr)
  101. ++file_ext_name;
  102. // 传文件
  103. code = storage_upload_by_filebuff1(pTrackerServer, &storageServer,
  104. store_path_index, buffer, file_size,
  105. file_ext_name, meta_data, meta_count, group_name, remote_filename);
  106. tracker_disconnect_server_ex(pTrackerServer, true);
  107. if (code != 0) {
  108. LOG(Log_Dir, "bufferUploadError", "upload buffer file fail, error info: %s\n", strerror(code));
  109. throw FastDfsException(code);
  110. }
  111. }
  112. void FastDfs::file_delete_by_remote_filename(const char *remote_filename) {
  113. if (remote_filename== nullptr){
  114. throw FastDfsException("remote_filename should be null");
  115. }
  116. ConnectionInfo *pTrackerServer;
  117. int code;
  118. code = ignore_signal_pipe();
  119. if (code != 0) {
  120. LOG(Log_Dir, "deleteError", "ignore signal pipe error");
  121. throw FastDfsException(code);
  122. }
  123. pTrackerServer = tracker_get_connection_ex(&tracker_group);
  124. if (pTrackerServer == nullptr) {
  125. code = errno != 0 ? errno : ECONNREFUSED;
  126. LOG(Log_Dir, "deleteError", "connect to track server error, error info: %s", strerror(code));
  127. throw FastDfsException(code);
  128. }
  129. code=storage_delete_file1(pTrackerServer, nullptr, remote_filename);
  130. tracker_disconnect_server_ex(pTrackerServer, true);
  131. if (code != 0) {
  132. LOG(Log_Dir, "deleteError", "upload buffer file fail, error info: %s\n", strerror(code));
  133. throw FastDfsException(code);
  134. }
  135. }

其他问题

storage_upload_by_filename1与 storage_upload_by_filename区别:
加1的前面带group name,不加1的不带,推荐用storage_upload_by_filebuff

图片.png

  1. ubuntu@VM-0-7-ubuntu:/usr/local/src/fastDfs_package/01_fdfs/fastdfs-5.10/client$ ./fdfs_upload_file /etc/fdfs/client.conf ./fdfs_upload_file.c
  2. M00/00/00/rBAAB2AcCTSAbqN9AAAKGKVbM_I58860.c
  3. ubuntu@VM-0-7-ubuntu:/usr/local/src/fastDfs_package/01_fdfs/fastdfs-5.10/client$ fdfs_upload_file /etc/fdfs/client.conf ./fdfs_upload_file.c
  4. group1/M00/00/00/rBAAB2AcCTqARR21AAAKGKVbM_I63529.c

其中第一个是不带1的,第二个是带1的