Full Code of happyfish100/fastdfs for AI

master 7d832c13a63c cached
529 files
7.0 MB
1.9M tokens
3425 symbols
1 requests
Download .txt
Showing preview only (7,403K chars total). Download the full file or copy to clipboard to get everything.
Repository: happyfish100/fastdfs
Branch: master
Commit: 7d832c13a63c
Files: 529
Total size: 7.0 MB

Directory structure:
gitextract_pt_qh3a1/

├── .gitignore
├── COPYING-3_0.txt
├── HISTORY
├── INSTALL
├── README.md
├── README_zh.md
├── benchmarks/
│   ├── .gitignore
│   ├── Makefile
│   ├── README.md
│   ├── benchmark_concurrent.c
│   ├── benchmark_download.c
│   ├── benchmark_large_files.c
│   ├── benchmark_metadata.c
│   ├── benchmark_small_files.c
│   ├── benchmark_upload.c
│   ├── config/
│   │   └── benchmark.conf
│   ├── results/
│   │   └── template.json
│   └── scripts/
│       ├── compare_versions.py
│       ├── generate_report.py
│       └── run_all_benchmarks.sh
├── cli/
│   ├── Makefile.in
│   ├── README.md
│   └── fdfs_cli.c
├── client/
│   ├── Makefile.in
│   ├── client_func.c
│   ├── client_func.h
│   ├── client_global.c
│   ├── client_global.h
│   ├── fdfs_append_file.c
│   ├── fdfs_appender_test.c
│   ├── fdfs_appender_test1.c
│   ├── fdfs_bulk_import.c
│   ├── fdfs_client.h
│   ├── fdfs_crc32.c
│   ├── fdfs_delete_file.c
│   ├── fdfs_download_file.c
│   ├── fdfs_file_info.c
│   ├── fdfs_link_library.sh.in
│   ├── fdfs_monitor.c
│   ├── fdfs_regenerate_filename.c
│   ├── fdfs_test.c
│   ├── fdfs_test1.c
│   ├── fdfs_upload_appender.c
│   ├── fdfs_upload_file.c
│   ├── storage_client.c
│   ├── storage_client.h
│   ├── storage_client1.h
│   ├── test/
│   │   └── Makefile.in
│   ├── tracker_client.c
│   └── tracker_client.h
├── common/
│   ├── Makefile
│   ├── fdfs_define.h
│   ├── fdfs_global.c
│   ├── fdfs_global.h
│   ├── fdfs_http_shared.c
│   ├── fdfs_http_shared.h
│   ├── mime_file_parser.c
│   └── mime_file_parser.h
├── conf/
│   ├── client.conf
│   ├── http.conf
│   ├── mime.types
│   ├── storage.conf
│   ├── storage_ids.conf
│   └── tracker.conf
├── cpp_client/
│   ├── CMakeLists.txt
│   ├── README.md
│   ├── examples/
│   │   ├── CMakeLists.txt
│   │   ├── advanced_metadata_example.cpp
│   │   ├── appender_example.cpp
│   │   ├── basic_usage.cpp
│   │   ├── batch_operations_example.cpp
│   │   ├── cancellation_example.cpp
│   │   ├── concurrent_operations_example.cpp
│   │   ├── configuration_example.cpp
│   │   ├── connection_pool_example.cpp
│   │   ├── error_handling_example.cpp
│   │   ├── file_info_example.cpp
│   │   ├── metadata_example.cpp
│   │   ├── partial_download_example.cpp
│   │   ├── performance_example.cpp
│   │   ├── slave_file_example.cpp
│   │   ├── streaming_example.cpp
│   │   └── upload_buffer_example.cpp
│   ├── include/
│   │   └── fastdfs/
│   │       ├── client.hpp
│   │       ├── errors.hpp
│   │       └── types.hpp
│   └── src/
│       ├── client.cpp
│       └── internal/
│           ├── connection.cpp
│           ├── connection.hpp
│           ├── connection_pool.cpp
│           ├── connection_pool.hpp
│           ├── operations.cpp
│           ├── operations.hpp
│           ├── protocol.cpp
│           └── protocol.hpp
├── csharp_client/
│   ├── ConnectionPool.cs
│   ├── FastDFSClient.cs
│   ├── FastDFSClientConfig.cs
│   ├── FastDFSConstants.cs
│   ├── FastDFSErrors.cs
│   ├── FastDFSTypes.cs
│   ├── ProtocolBuilder.cs
│   ├── ProtocolParser.cs
│   ├── README.md
│   └── examples/
│       ├── AdvancedMetadataExample.cs
│       ├── AppenderFileExample.cs
│       ├── BasicExample.cs
│       ├── BatchOperationsExample.cs
│       ├── CancellationExample.cs
│       ├── ConcurrentOperationsExample.cs
│       ├── ConfigurationExample.cs
│       ├── ConnectionPoolExample.cs
│       ├── ErrorHandlingExample.cs
│       ├── FileInfoExample.cs
│       ├── IntegrationExample.cs
│       ├── MetadataExample.cs
│       ├── PartialDownloadExample.cs
│       ├── PerformanceExample.cs
│       ├── SlaveFileExample.cs
│       ├── StreamingExample.cs
│       └── UploadBufferExample.cs
├── debian/
│   ├── README.Debian
│   ├── changelog
│   ├── compat
│   ├── control
│   ├── copyright
│   ├── fastdfs-config.install
│   ├── fastdfs-server.dirs
│   ├── fastdfs-server.install
│   ├── fastdfs-tool.dirs
│   ├── fastdfs-tool.install
│   ├── libfdfsclient-dev.install
│   ├── libfdfsclient.install
│   ├── rules
│   ├── source/
│   │   └── format
│   ├── substvars
│   └── watch
├── docker/
│   ├── dockerfile_local/
│   │   ├── Dockerfile
│   │   ├── README.md
│   │   ├── conf/
│   │   │   ├── client.conf
│   │   │   ├── http.conf
│   │   │   ├── mime.types
│   │   │   ├── mod_fastdfs.conf
│   │   │   ├── nginx.conf
│   │   │   ├── storage.conf
│   │   │   └── tracker.conf
│   │   └── fastdfs.sh
│   ├── dockerfile_local-v6.0.9/
│   │   ├── README.md
│   │   ├── build_image-v6.0.8/
│   │   │   ├── Dockerfile
│   │   │   ├── conf/
│   │   │   │   ├── client.conf
│   │   │   │   ├── http.conf
│   │   │   │   ├── mime.types
│   │   │   │   ├── mod_fastdfs.conf
│   │   │   │   ├── storage.conf
│   │   │   │   ├── storage_ids.conf
│   │   │   │   └── tracker.conf
│   │   │   ├── nginx_conf/
│   │   │   │   └── nginx.conf
│   │   │   ├── nginx_conf.d/
│   │   │   │   └── default.conf
│   │   │   └── start.sh
│   │   ├── build_image-v6.0.9/
│   │   │   ├── Dockerfile
│   │   │   ├── conf/
│   │   │   │   ├── client.conf
│   │   │   │   ├── http.conf
│   │   │   │   ├── mime.types
│   │   │   │   ├── mod_fastdfs.conf
│   │   │   │   ├── storage.conf
│   │   │   │   ├── storage_ids.conf
│   │   │   │   └── tracker.conf
│   │   │   ├── nginx_conf/
│   │   │   │   └── nginx.conf
│   │   │   ├── nginx_conf.d/
│   │   │   │   └── default.conf
│   │   │   └── start.sh
│   │   ├── fastdfs-conf/
│   │   │   ├── conf/
│   │   │   │   ├── client.conf
│   │   │   │   ├── http.conf
│   │   │   │   ├── mime.types
│   │   │   │   ├── mod_fastdfs.conf
│   │   │   │   ├── storage.conf
│   │   │   │   ├── storage_ids.conf
│   │   │   │   └── tracker.conf
│   │   │   ├── nginx_conf/
│   │   │   │   └── nginx.conf
│   │   │   ├── nginx_conf.d/
│   │   │   │   └── default.conf
│   │   │   └── setting_conf.sh
│   │   ├── fastdfs自定义镜像和安装手册.txt
│   │   └── qa.txt
│   └── dockerfile_network/
│       ├── Dockerfile
│       ├── README.md
│       ├── conf/
│       │   ├── client.conf
│       │   ├── http.conf
│       │   ├── mime.types
│       │   ├── mod_fastdfs.conf
│       │   ├── nginx.conf
│       │   ├── storage.conf
│       │   └── tracker.conf
│       └── fastdfs.sh
├── examples/
│   ├── c_examples/
│   │   ├── 01_basic_upload.c
│   │   ├── 02_basic_download.c
│   │   ├── 03_metadata_operations.c
│   │   ├── 04_appender_file.c
│   │   ├── 05_slave_file.c
│   │   ├── 06_batch_upload.c
│   │   ├── 07_connection_pool.c
│   │   ├── 08_error_handling.c
│   │   └── Makefile
│   └── php_examples/
│       ├── 01_basic_upload.php
│       ├── 02_basic_download.php
│       ├── 03_metadata_operations.php
│       ├── 04_appender_file.php
│       ├── 05_slave_file.php
│       ├── 06_advanced_download.php
│       ├── 07_connection_pool_error_handling.php
│       └── 08_error_handling.php
├── fastdfs.spec
├── go_client/
│   ├── .gitignore
│   ├── CONTRIBUTING.md
│   ├── IMPLEMENTATION_SUMMARY.md
│   ├── Makefile
│   ├── README.md
│   ├── appender.go
│   ├── client.go
│   ├── client_test.go
│   ├── connection.go
│   ├── errors.go
│   ├── examples/
│   │   ├── appender/
│   │   │   └── main.go
│   │   ├── basic/
│   │   │   └── main.go
│   │   ├── batch/
│   │   │   └── main.go
│   │   ├── concurrent/
│   │   │   └── main.go
│   │   ├── connection_pool/
│   │   │   └── main.go
│   │   ├── error_handling/
│   │   │   └── main.go
│   │   ├── metadata/
│   │   │   └── main.go
│   │   └── performance/
│   │       └── main.go
│   ├── go.sum
│   ├── metadata.go
│   ├── operations.go
│   ├── protocol.go
│   └── types.go
├── groovy_client/
│   ├── .gitignore
│   ├── CONTRIBUTING.md
│   ├── Makefile
│   ├── README.md
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── groovy/
│       │       └── com/
│       │           └── fastdfs/
│       │               └── client/
│       │                   ├── FastDFSClient.groovy
│       │                   ├── config/
│       │                   │   └── ClientConfig.groovy
│       │                   ├── connection/
│       │                   │   ├── Connection.groovy
│       │                   │   └── ConnectionPool.groovy
│       │                   ├── errors/
│       │                   │   └── FastDFSErrors.groovy
│       │                   ├── examples/
│       │                   │   └── BasicExample.groovy
│       │                   ├── operations/
│       │                   │   └── Operations.groovy
│       │                   ├── protocol/
│       │                   │   └── ProtocolHandler.groovy
│       │                   └── types/
│       │                       └── Types.groovy
│       └── test/
│           └── groovy/
│               └── com/
│                   └── fastdfs/
│                       └── client/
│                           ├── FastDFSClientTest.groovy
│                           └── config/
│                               └── ClientConfigTest.groovy
├── init.d/
│   ├── fdfs_storaged
│   └── fdfs_trackerd
├── javascript_client/
│   ├── .gitignore
│   ├── README.md
│   ├── examples/
│   │   ├── 01_basic_upload.js
│   │   ├── 02_metadata_operations.js
│   │   ├── 03_appender_file.js
│   │   └── 04_slave_file.js
│   ├── package.json
│   └── src/
│       ├── client.js
│       ├── connection.js
│       ├── errors.js
│       ├── index.js
│       ├── operations.js
│       ├── protocol.js
│       └── types.js
├── make.sh
├── monitoring/
│   ├── health_check/
│   │   ├── Makefile
│   │   ├── README.md
│   │   └── health_checker.c
│   └── prometheus_exporter/
│       ├── Makefile
│       ├── README.md
│       ├── fdfs_exporter.c
│       └── grafana_dashboard.json
├── php_client/
│   ├── README
│   ├── config.m4
│   ├── fastdfs_appender_test.php
│   ├── fastdfs_appender_test1.php
│   ├── fastdfs_callback_test.php
│   ├── fastdfs_client.c
│   ├── fastdfs_client.h
│   ├── fastdfs_client.ini
│   ├── fastdfs_client.spec.in
│   ├── fastdfs_test.php
│   ├── fastdfs_test1.php
│   └── fastdfs_test_slave.php
├── python_client/
│   ├── .gitignore
│   ├── LICENSE
│   ├── MANIFEST.in
│   ├── README.md
│   ├── examples/
│   │   ├── appender_example.py
│   │   ├── basic_usage.py
│   │   └── meta_example.py
│   ├── fdfs/
│   │   ├── __init__.py
│   │   ├── client.py
│   │   ├── connection.py
│   │   ├── errors.py
│   │   ├── operations.py
│   │   ├── protocol.py
│   │   └── types.py
│   ├── pyproject.toml
│   ├── requirements-dev.txt
│   ├── setup.py
│   └── tests/
│       ├── init.py
│       ├── test_client.py
│       ├── test_connection.py
│       ├── test_integration.py
│       └── test_protocol.py
├── ruby_client/
│   ├── Gemfile
│   ├── LICENSE
│   ├── README.md
│   ├── examples/
│   │   ├── basic_usage.rb
│   │   ├── metadata_example.rb
│   │   └── upload_buffer.rb
│   ├── fastdfs.gemspec
│   └── lib/
│       ├── fastdfs/
│       │   ├── client.rb
│       │   ├── client_config.rb
│       │   ├── connection_pool.rb
│       │   ├── errors.rb
│       │   ├── operations.rb
│       │   ├── protocol.rb
│       │   └── types.rb
│       └── fastdfs.rb
├── rust_client/
│   ├── .gitignore
│   ├── Cargo.toml
│   ├── LICENSE
│   ├── benches/
│   │   └── benchmark.rs
│   ├── examples/
│   │   ├── advanced_metadata_example.rs
│   │   ├── appender_example.rs
│   │   ├── basic_usage.rs
│   │   ├── batch_operations_example.rs
│   │   ├── cancellation_example.rs
│   │   ├── concurrent_operations_example.rs
│   │   ├── configuration_example.rs
│   │   ├── connection_pool_example.rs
│   │   ├── error_handling_example.rs
│   │   ├── file_info_example.rs
│   │   ├── integration_example.rs
│   │   ├── metadata_example.rs
│   │   ├── partial_download_example.rs
│   │   ├── performance_example.rs
│   │   ├── slave_file_example.rs
│   │   ├── streaming_example.rs
│   │   └── upload_buffer_example.rs
│   ├── src/
│   │   ├── client.rs
│   │   ├── connection.rs
│   │   ├── errors.rs
│   │   ├── lib.rs
│   │   ├── operations.rs
│   │   ├── protocol.rs
│   │   └── types.rs
│   └── tests/
│       ├── client_tests.rs
│       ├── connection_tests.rs
│       ├── integration_tests.rs
│       └── protocol_tests.rs
├── setup.sh
├── storage/
│   ├── Makefile.in
│   ├── fdfs_storaged.c
│   ├── fdht_client/
│   │   ├── fdht_client.c
│   │   ├── fdht_client.h
│   │   ├── fdht_define.h
│   │   ├── fdht_func.c
│   │   ├── fdht_func.h
│   │   ├── fdht_global.c
│   │   ├── fdht_global.h
│   │   ├── fdht_proto.c
│   │   ├── fdht_proto.h
│   │   ├── fdht_proto_types.h
│   │   └── fdht_types.h
│   ├── file_id_hashtable.c
│   ├── file_id_hashtable.h
│   ├── storage_bulk_import.c
│   ├── storage_bulk_import.h
│   ├── storage_dio.c
│   ├── storage_dio.h
│   ├── storage_disk_recovery.c
│   ├── storage_disk_recovery.h
│   ├── storage_dump.c
│   ├── storage_dump.h
│   ├── storage_func.c
│   ├── storage_func.h
│   ├── storage_global.c
│   ├── storage_global.h
│   ├── storage_ip_changed_dealer.c
│   ├── storage_ip_changed_dealer.h
│   ├── storage_param_getter.c
│   ├── storage_param_getter.h
│   ├── storage_service.c
│   ├── storage_service.h
│   ├── storage_sync.c
│   ├── storage_sync.h
│   ├── storage_sync_func.c
│   ├── storage_sync_func.h
│   ├── storage_types.h
│   ├── tracker_client_thread.c
│   ├── tracker_client_thread.h
│   └── trunk_mgr/
│       ├── trunk_client.c
│       ├── trunk_client.h
│       ├── trunk_free_block_checker.c
│       ├── trunk_free_block_checker.h
│       ├── trunk_mem.c
│       ├── trunk_mem.h
│       ├── trunk_shared.c
│       ├── trunk_shared.h
│       ├── trunk_sync.c
│       └── trunk_sync.h
├── systemd/
│   ├── fdfs_storaged.service
│   └── fdfs_trackerd.service
├── test/
│   ├── Makefile
│   ├── combine_result.c
│   ├── common_func.c
│   ├── common_func.h
│   ├── dfs_func.c
│   ├── dfs_func.h
│   ├── dfs_func_pc.c
│   ├── gen_files.c
│   ├── test_append.c
│   ├── test_append.sh
│   ├── test_concurrent.c
│   ├── test_concurrent.sh
│   ├── test_delete.c
│   ├── test_delete.sh
│   ├── test_download.c
│   ├── test_download.sh
│   ├── test_file_exist.c
│   ├── test_file_exist.sh
│   ├── test_fileinfo.c
│   ├── test_fileinfo.sh
│   ├── test_metadata.c
│   ├── test_metadata.sh
│   ├── test_modify.c
│   ├── test_modify.sh
│   ├── test_range_download.c
│   ├── test_range_download.sh
│   ├── test_slave.c
│   ├── test_slave.sh
│   ├── test_truncate.c
│   ├── test_truncate.sh
│   ├── test_types.h
│   ├── test_upload.c
│   ├── test_upload.sh
│   └── unit_tests/
│       ├── Makefile
│       └── test_client_api.c
├── tools/
│   ├── Makefile
│   ├── fdfs_analyze.c
│   ├── fdfs_backup.c
│   ├── fdfs_batch_delete.c
│   ├── fdfs_benchmark.c
│   ├── fdfs_capacity_plan.c
│   ├── fdfs_capacity_planner.c
│   ├── fdfs_capacity_planner.h
│   ├── fdfs_capacity_report.c
│   ├── fdfs_cleanup.c
│   ├── fdfs_cluster_mgr.c
│   ├── fdfs_compress.c
│   ├── fdfs_config_compare.c
│   ├── fdfs_config_generator.c
│   ├── fdfs_config_validator.c
│   ├── fdfs_config_validator.h
│   ├── fdfs_dedup.c
│   ├── fdfs_export.c
│   ├── fdfs_file_migrate.c
│   ├── fdfs_file_verify.c
│   ├── fdfs_health_check.c
│   ├── fdfs_import.c
│   ├── fdfs_load_balancer.c
│   ├── fdfs_log_analyzer.c
│   ├── fdfs_metadata_bulk.c
│   ├── fdfs_network_diag.c
│   ├── fdfs_network_diag.h
│   ├── fdfs_network_monitor.c
│   ├── fdfs_profiler.c
│   ├── fdfs_quota.c
│   ├── fdfs_rebalance.c
│   ├── fdfs_recover.c
│   ├── fdfs_repair.c
│   ├── fdfs_replication.c
│   ├── fdfs_replication_status.c
│   ├── fdfs_restore.c
│   ├── fdfs_search.c
│   ├── fdfs_snapshot.c
│   ├── fdfs_storage_stat.c
│   ├── fdfs_sync_check.c
│   └── fdfs_tag.c
├── tracker/
│   ├── Makefile.in
│   ├── fdfs_server_id_func.c
│   ├── fdfs_server_id_func.h
│   ├── fdfs_shared_func.c
│   ├── fdfs_shared_func.h
│   ├── fdfs_trackerd.c
│   ├── tracker_dump.c
│   ├── tracker_dump.h
│   ├── tracker_func.c
│   ├── tracker_func.h
│   ├── tracker_global.c
│   ├── tracker_global.h
│   ├── tracker_mem.c
│   ├── tracker_mem.h
│   ├── tracker_proto.c
│   ├── tracker_proto.h
│   ├── tracker_relationship.c
│   ├── tracker_relationship.h
│   ├── tracker_service.c
│   ├── tracker_service.h
│   ├── tracker_status.c
│   ├── tracker_status.h
│   └── tracker_types.h
└── typescript_client/
    ├── .eslintrc.js
    ├── .gitignore
    ├── .prettierrc
    ├── LICENSE
    ├── README.md
    ├── examples/
    │   ├── appender-example.ts
    │   ├── basic-usage.ts
    │   └── metadata-example.ts
    ├── jest.config.js
    ├── package.json
    ├── src/
    │   ├── client.ts
    │   ├── connection.ts
    │   ├── errors.ts
    │   ├── index.ts
    │   ├── operations.ts
    │   ├── protocol.ts
    │   └── types.ts
    ├── tests/
    │   ├── client.test.ts
    │   ├── connection.test.ts
    │   ├── integration.test.ts
    │   └── protocol.test.ts
    ├── tsconfig.build.json
    └── tsconfig.json

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
# Makefile.in
storage/Makefile
tracker/Makefile
client/test/Makefile
client/Makefile

# client/fdfs_link_library.sh.in 
client/fdfs_link_library.sh

# 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/test_append
test/test_concurrent
test/test_file_exist
test/test_metadata
test/test_range_download
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/

# others
*.pid
*.swp
*.swo

# ideas
CONTRIBUTION_IDEAS.md

# Allow go_client directory
!go_client/


================================================
FILE: COPYING-3_0.txt
================================================
		    GNU GENERAL PUBLIC LICENSE
		       Version 3, 29 June 2007

 Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
 Everyone is permitted to copy and distribute verbatim copies
 of this license document, but changing it is not allowed.

			    Preamble

  The GNU General Public License is a free, copyleft license for
software and other kinds of works.

  The licenses for most software and other practical works are designed
to take away your freedom to share and change the works.  By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users.  We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors.  You can apply it to
your programs, too.

  When we speak of free software, we are referring to freedom, not
price.  Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.

  To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights.  Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.

  For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received.  You must make sure that they, too, receive
or can get the source code.  And you must show them these terms so they
know their rights.

  Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.

  For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software.  For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.

  Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so.  This is fundamentally incompatible with the aim of
protecting users' freedom to change the software.  The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable.  Therefore, we
have designed this version of the GPL to prohibit the practice for those
products.  If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.

  Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary.  To prevent this, the GPL assures that
patents cannot be used to render the program non-free.

  The precise terms and conditions for copying, distribution and
modification follow.

		       TERMS AND CONDITIONS

  0. Definitions.

  "This License" refers to version 3 of the GNU General Public License.

  "Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
 
  "The Program" refers to any copyrightable work licensed under this
License.  Each licensee is addressed as "you".  "Licensees" and
"recipients" may be individuals or organizations.

  To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy.  The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.

  A "covered work" means either the unmodified Program or a work based
on the Program.

  To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy.  Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.

  To "convey" a work means any kind of propagation that enables other
parties to make or receive copies.  Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.

  An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License.  If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.

  1. Source Code.

  The "source code" for a work means the preferred form of the work
for making modifications to it.  "Object code" means any non-source
form of a work.

  A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.

  The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form.  A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.

  The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities.  However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work.  For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.

  The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.

  The Corresponding Source for a work in source code form is that
same work.

  2. Basic Permissions.

  All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met.  This License explicitly affirms your unlimited
permission to run the unmodified Program.  The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work.  This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.

  You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force.  You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright.  Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.

  Conveying under any other circumstances is permitted solely under
the conditions stated below.  Sublicensing is not allowed; section 10
makes it unnecessary.

  3. Protecting Users' Legal Rights From Anti-Circumvention Law.

  No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.

  When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.

  4. Conveying Verbatim Copies.

  You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.

  You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.

  5. Conveying Modified Source Versions.

  You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:

    a) The work must carry prominent notices stating that you modified
    it, and giving a relevant date.

    b) The work must carry prominent notices stating that it is
    released under this License and any conditions added under section
    7.  This requirement modifies the requirement in section 4 to
    "keep intact all notices".

    c) You must license the entire work, as a whole, under this
    License to anyone who comes into possession of a copy.  This
    License will therefore apply, along with any applicable section 7
    additional terms, to the whole of the work, and all its parts,
    regardless of how they are packaged.  This License gives no
    permission to license the work in any other way, but it does not
    invalidate such permission if you have separately received it.

    d) If the work has interactive user interfaces, each must display
    Appropriate Legal Notices; however, if the Program has interactive
    interfaces that do not display Appropriate Legal Notices, your
    work need not make them do so.

  A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit.  Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.

  6. Conveying Non-Source Forms.

  You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:

    a) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by the
    Corresponding Source fixed on a durable physical medium
    customarily used for software interchange.

    b) Convey the object code in, or embodied in, a physical product
    (including a physical distribution medium), accompanied by a
    written offer, valid for at least three years and valid for as
    long as you offer spare parts or customer support for that product
    model, to give anyone who possesses the object code either (1) a
    copy of the Corresponding Source for all the software in the
    product that is covered by this License, on a durable physical
    medium customarily used for software interchange, for a price no
    more than your reasonable cost of physically performing this
    conveying of source, or (2) access to copy the
    Corresponding Source from a network server at no charge.

    c) Convey individual copies of the object code with a copy of the
    written offer to provide the Corresponding Source.  This
    alternative is allowed only occasionally and noncommercially, and
    only if you received the object code with such an offer, in accord
    with subsection 6b.

    d) Convey the object code by offering access from a designated
    place (gratis or for a charge), and offer equivalent access to the
    Corresponding Source in the same way through the same place at no
    further charge.  You need not require recipients to copy the
    Corresponding Source along with the object code.  If the place to
    copy the object code is a network server, the Corresponding Source
    may be on a different server (operated by you or a third party)
    that supports equivalent copying facilities, provided you maintain
    clear directions next to the object code saying where to find the
    Corresponding Source.  Regardless of what server hosts the
    Corresponding Source, you remain obligated to ensure that it is
    available for as long as needed to satisfy these requirements.

    e) Convey the object code using peer-to-peer transmission, provided
    you inform other peers where the object code and Corresponding
    Source of the work are being offered to the general public at no
    charge under subsection 6d.

  A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.

  A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling.  In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage.  For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product.  A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.

  "Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source.  The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.

  If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information.  But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).

  The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed.  Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.

  Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.

  7. Additional Terms.

  "Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law.  If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.

  When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it.  (Additional permissions may be written to require their own
removal in certain cases when you modify the work.)  You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.

  Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:

    a) Disclaiming warranty or limiting liability differently from the
    terms of sections 15 and 16 of this License; or

    b) Requiring preservation of specified reasonable legal notices or
    author attributions in that material or in the Appropriate Legal
    Notices displayed by works containing it; or

    c) Prohibiting misrepresentation of the origin of that material, or
    requiring that modified versions of such material be marked in
    reasonable ways as different from the original version; or

    d) Limiting the use for publicity purposes of names of licensors or
    authors of the material; or

    e) Declining to grant rights under trademark law for use of some
    trade names, trademarks, or service marks; or

    f) Requiring indemnification of licensors and authors of that
    material by anyone who conveys the material (or modified versions of
    it) with contractual assumptions of liability to the recipient, for
    any liability that these contractual assumptions directly impose on
    those licensors and authors.

  All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10.  If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term.  If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.

  If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.

  Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.

  8. Termination.

  You may not propagate or modify a covered work except as expressly
provided under this License.  Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).

  However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.

  Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.

  Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License.  If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.

  9. Acceptance Not Required for Having Copies.

  You are not required to accept this License in order to receive or
run a copy of the Program.  Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance.  However,
nothing other than this License grants you permission to propagate or
modify any covered work.  These actions infringe copyright if you do
not accept this License.  Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.

  10. Automatic Licensing of Downstream Recipients.

  Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License.  You are not responsible
for enforcing compliance by third parties with this License.

  An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations.  If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.

  You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License.  For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.

  11. Patents.

  A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based.  The
work thus licensed is called the contributor's "contributor version".

  A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version.  For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.

  Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.

  In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement).  To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.

  If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients.  "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
  
  If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.

  A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License.  You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.

  Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.

  12. No Surrender of Others' Freedom.

  If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License.  If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all.  For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.

  13. Use with the GNU Affero General Public License.

  Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work.  The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.

  14. Revised Versions of this License.

  The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time.  Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.

  Each version is given a distinguishing version number.  If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation.  If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.

  If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.

  Later license versions may give you additional or different
permissions.  However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.

  15. Disclaimer of Warranty.

  THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW.  EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU.  SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.

  16. Limitation of Liability.

  IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

  17. Interpretation of Sections 15 and 16.

  If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.

		     END OF TERMS AND CONDITIONS

	    How to Apply These Terms to Your New Programs

  If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.

  To do so, attach the following notices to the program.  It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.

    <one line to give the program's name and a brief idea of what it does.>
    Copyright (C) <year>  <name of author>

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

Also add information on how to contact you by electronic and paper mail.

  If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:

    <program>  Copyright (C) <year>  <name of author>
    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".

  You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.

  The GNU General Public License does not permit incorporating your program
into proprietary programs.  If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library.  If this is what you want to do, use the GNU Lesser General
Public License instead of this License.  But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.



================================================
FILE: HISTORY
================================================

Version 6.15.4  2026-03-07
 * download_file offset and bytes's logic is consistent with the range of HTTP

Version 6.15.3  2025-12-23
 * storage dio queue use fc_queue instead of common_blocked_queue

Version 6.15.2  2025-11-15
 * move finish_callback from fast_task_info to TrackerClientInfo
 * use libfastcommon V1.83 and libserverframe 1.2.11

Version 6.15.1  2025-11-06
 * query file info support combined flags:
   FDFS_QUERY_FINFO_FLAGS_NOT_CALC_CRC32 and FDFS_QUERY_FINFO_FLAGS_KEEP_SILENCE

Version 6.15.0  2025-10-26
 * storage sync support multi-threads
 * conf/tracker.conf support config response_ip_addr_size
 * use libfastcommon V1.81 and libserverframe 1.2.9

Version 6.14.0  2025-09-26
 * access log use libserverframe
 * log config items in tracker.conf and storage.conf changed
 * use libfastcommon V1.80 and libserverframe 1.2.9

Version 6.13.2  2025-09-13
 * use libfastcommon V1.80 and libserverframe 1.2.8

Version 6.13.1  2025-09-06
 * fdfs_monitor output reserved and available space
 * write to storage_stat.dat more gracefully

Version 6.13.0  2025-08-31
 * use libfastcommon V1.79 and libserverframe 1.2.8
 * Merge pull request #753 from lystormenvoy/store_path_readonly
 * performance opt.: replace sprintf and snprintf as necessary
 * bugfixed: MUST memset connection info to 0
 * remove useless HTTP relative codes and config items
 * storage servers support read write separation,
   typical scene: cross data center disaster backup

Version 6.12.4  2025-06-19
 * normalize ip addresses from storage_ids.conf

Version 6.12.3  2025-03-28
 * fdfs_upload_file.c: support IPv6 address

Version 6.12.2  2024-09-16
 * use libfastcommon V1.75 and libserverframe 1.2.5

Version 6.12.1  2024-03-06
 * adapt to libserverframe 1.2.3
 * bugfixed: notify_leader_changed support IPv6 correctly
 * log square quoted IPv6 address

Version 6.12.0  2024-02-12
 * bugfixed: parse ip and port use parseAddress instead of splitEx
 * bugfixed: fdfs_server_info_to_string support IPv6 correctly
 * check filename duplicate by hashtable instead of file system access

Version 6.11.0  2023-12-10
 * support IPv6, config item: address_family in tracker.conf and storage.conf
   use libfastcommon V1.71 and libserverframe 1.2.1
 * storage.conf can specify the storage server ID for NAT network

Version 6.10.0  2023-09-07
 * use libfastcommon V1.70 and libserverframe 1.2.0

Version 6.9.5  2023-06-05
 * fix possible out-of-bounds issues with array access
 * fix realloc mistakes to avoid memory leaks
 * add ExecStartPost=/bin/sleep 0.1 to systemd service files
 * fdht_client/fdht_func.c: fixed compile error

Version 6.9.4  2023-02-15
 * use epoll edge trigger to resolve github issues #608
 * bugfixed: report connections' current_count and max_count correctly

Version 6.9.3  2022-12-24
 * use prctl to set pthread name under Linux

Version 6.9.2  2022-11-28
 * space size such as total_mb and free_mb use int64_t instead of int
 * bugfixed: log connection ip_addr and port correctly
 * output port with format %u instead %d

Version 6.9.1  2022-11-25
 * bugfixed: clear task extra data correctly when the connection broken

Version 6.09  2022-09-14
 * use libfastcommon V1.60 and libserverframe 1.1.19
 * use atomic counter instead of mutex lock

Version 6.08  2022-06-21
 * use libfastcommon V1.56
   NOTE: you MUST upgrade libfastcommon to V1.56 or later

Version 6.07  2020-12-31
 * 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 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.

  NOTE: you MUST upgrade libfastcommon to V1.41 or later
        the tracker and storage server must upgrade together

 * storage server get IP from tracker server
 * storage server report current tracker IP to the tracker server when join
 * 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
 * php_ext fix zend_object_store_get_object call in php5.5
 * make.sh uses macros define in /usr/include/fastcommon/_os_define.h
 * correct CRC32, you must upgrade libfastcommon to V1.38 or later

Version 5.11  2017-05-26
 * bug fixed: file_offset has no effect when use trunk file
 * add storage access log header
 * http.conf add parameter http.multi_range.enabed

Version 5.10  2017-03-29
 * use fc_safe_read instead of read, and fc_safe_write instead of write
   you must upgrade libfastcommon to V1.35 or later
 * fix getFileContentEx read bytes,
   you must upgrade libfastcommon to V1.36 or later
 * do NOT sync storage server info to tracker leader
 * adjust parameter store_server when use_trunk_file is true
 * clear sync src id when tracker response ENOENT
 * log more info when fdfs_recv_header / fdfs_recv_response fail

Version 5.09  2016-12-29
 * bug fixed: list_all_groups expand buffer auto for so many groups
 * tracker.conf add parameters: min_buff_size and max_buff_size
 * php extension fix free object bug in PHP 7

Version 5.08  2016-04-08
 * install library to $(TARGET_PREFIX)/lib anyway
 * php extension compiled in PHP 7
 * dio thread use blocked_queue and php extension use php7_ext_wrapper.h,
   you must upgrade libfastcommon to V1.25 or later
 * remove common/linux_stack_trace.[hc]

Version 5.07  2015-09-13
 * schedule task add the "second" field
 * make.sh changed, you must upgrade libfastcommon to V1.21 or later
 * bug fixed: storage_disk_recovery.c skip the first file (binlog first line)
 * bug fixed: should close connection after fetch binlog
 * fdfs_storaged.c: advance the position of daemon_init
 * set log rotate time format
 * bug fixed: must check store_path_index

Version 5.06  2015-05-12
 * compile passed in mac OS Darwin
 * correct scripts in subdir init.d
 * check item thread_stack_size in storage.conf, you must
   upgrade libfastcommon to V1.14 or later

Version 5.05  2014-11-22
 * tracker_mem.c log more info
 * remove useless global variable: g_network_tv
 * storage can fetch it's group_name from tracker server

Version 5.04  2014-09-16
 * add fastdfs.spec for build RPM on Linux
 * depend on libfastcommon
 * in multi tracker servers case, when receive higher status like
   online / active and the storage status is wait_sync or syncing,
   the tracker adjust storage status to newer, and the storage rejoin
   to the tracker server
 * fdfs_monitor support delete empty group
 * bug fixed: two tracker leaders occur in rare case
 * add connection stats
 * delete old log files, add parameter: log_file_keep_days

Version 5.03  2014-08-10
 * network send and recv retry when error EINTR happen
 * support mac OS Darwin
 * use newest logger from libfastcommon
 * patches by liangry@ucweb.com
 * bug fixed: can't sync large files cause by v5.02
 * use newest files from libfastcommon
 * change TRACKER_SYNC_STATUS_FILE_INTERVAL from 3600 to 300
 * socket send and recv ignore erno EINTR

Version 5.02  2014-07-20
 * corect README spell mistake
 * bug fixed: can't deal sync truncate file exception
 * remove tracker_global.c extern keyword to tracker_global.h
 * change log level from ERROR to DEBUG when IOEVENT_ERROR
 * php callback should use INIT_ZVAL to init zval variable
 * add function short2buff and buff2short
 * add get_url_content_ex to support buffer passed by caller
 * logger can set rotate time format
 * logger can log header line
 * #include <stdbool.h> to use C99 bool
 * logger can delete old rotated files
 * bug fixed: connection pool should NOT increase counter when connect fail
 * logger.c do NOT call fsync after write

Version 5.01  2014-02-02
 * trunk binlog be compressed when trunk init
 * bug fixed: sync trunk binlog file to other storage servers immediately when
   the trunk server init done
 * move ioevent_loop.[hc] and fast_task_queue.[hc] from tracker/ to common/
 * hash table support locks
 * hash talbe support new functions: hash_inc and hash_inc_ex

Version 5.00  2013-12-23
 * discard libevent, use epoll in Linux, kqueue in FreeBSD, port in SunOS directly
 * do_notify_leader_changed force close connection when target is myself
 * modify the INSTALL file and tracker/Makefile.in

Version 4.08  2013-11-30
 * bug fixed: FDFS_DOWNLOAD_SERVER_ROUND_ROBIN change to FDFS_STORE_SERVER_ROUND_ROBIN
 * dio_init use memset to init buffer
 * disable linger setting (setsockopt with option SO_LINGER)
 * change log level from error to warning when file not exist on storage server

Version 4.07  2013-06-02
 * make.sh add -lpthread by ldconfig check
 * support multi accept threads
 * tracker and storage server close client connection when recv invalid package
 * client/storage_client.c: file_exist with silence flag
 * tracker and storage process support start, stop and restart command
 * tracker/tracker_proto.c fdfs_recv_header: logDebug change to logError

Version 4.06  2013-01-24
 * fdfs_upload_file tool enhancement
 * fdfs_download_file tool support offset and download size
 * trunk file upload support sub paths rotating correctly
 * add function: fdfs_http_get_file_extension
 * sync truncate file operation anyway

Version 4.05  2012-12-30
 * client/fdfs_upload_file.c can specify storage ip port and store path index
 * add connection pool
 * client load storage ids config
 * common/ini_file_reader.c does NOT call chdir
 * keep the mtime of file same
 * use g_current_time instead of call time function
 * remove embed HTTP support

Version 4.04  2012-12-02
 * bug fixed: get storage server id when storage daemon init
 * storage id in filename use global variable
 * dynamic alloc memory 8 bytes alignment
 * fast_task_queue support memory pool chain

Version 4.03  2012-11-18
 * trunk_mgr/trunk_mem.c: log error and add more debug info
 * file id generated by storage server can include storage server ID

Version 4.02  2012-10-30
 * validate file_ext_name and prefix_name when upload file
 * storage.conf add parameter: file_sync_skip_invalid_record
 * add offset debug info when sync file fail
 * bug fixed: log to binlog also if the file exists when sync file
 * tracker and storage error log support rotate
 * support rotate log by file size
 * rotate log when receive HUP signal
 * fdfs_monitor support set trunk server
 * bug fixed: tracker_mem.c correct double mutex lock

Version 4.01  2012-10-21
 * trunk_mgr/trunk_mem.c: trunk init flag check more strictly
 * file signature for checking file duplicate support MD5
 * slave file support both symbol link and direct file
 * tracker server log trunk server change logs

Version 4.00  2012-10-06
 * identify storage server by ID instead of IP address
 * tracker.conf: storage reserved space can use ratio such as 10%
 * storage server support access log
 * appender file and trunk file also use rand number in file id
 * bug fixed: test_upload.c: char file_id[64] change to: char file_id[128]
 * set pipe reading fd with attribute O_NOATIME
 * bug fixed: correct php extension call_user_function TSRMLS_DC with TSRMLS_CC

Version 3.11  2012-08-04
 * setsockopt set linger.l_linger to micro-seconds in FreeBSD and seconds 
   in others
 * trunk binlog reader skip incorrect records
 * bug fixed: single disk recovery support symbol link and trunk file
 * storage generate filename enhancement
 * ETIME change to ETIMEDOUT for FreeBSD
 * tracker_mem.c: load storage server ignore empty ip address

Version 3.10  2012-07-22
 * check and init trunk file more gracefully
 * remove unused-but-set-variable
 * bug fixed: return correct group name when g_check_file_duplicate is true
 * bug fixed: php extension call_user_function replace TSRMLS_CC with TSRMLS_DC
 * large the interval of tracker re-select trunk server
 * trunk free block check duplicate using avl tree
 * trunk file sync overwrite the dest file anyway
 * common/avl_tree.c: free data when delete
 * tracker.conf add parameter: trunk_init_reload_from_binlog, when this flag 
   is set to true, load all free trunk blocks from the trunk binlog
 * trunk status control only by trunk_mem.c and memcmp struct FDFSTrunkFullInfo
   avoid memory alignment problem
 * auto remove the too old temp file

Version 3.09  2012-07-08
 * make.sh avoid override config files of /etc/fdfs/
 * common/logger.c: function log_init can be called more than once
 * php extension logInfo change to logDebug
 * c client logInfo change to logDebug
 * storage_dio.c log info more properly
 * delete the trunk space which be occupied
 * tracker.conf add parameter: trunk_init_check_occupying, when this flag 
   is set to true, do not add the trunk nodes which be occupied
 * another method to get local ip addresses

Version 3.08  2012-05-27
 * FAST_MAX_LOCAL_IP_ADDRS change from 4 to 16
 * appender file support modify
 * appender file support truncate

Version 3.07  2012-05-13
 * tracker/tracker_mem.c: check storage ip address is not empty
 * remove direct IO support
 * trunk binlog sync optimization
 * php extension compile passed in PHP 5.4.0
 * get local ip addresses enhancement
 * trunk server select the storage server whose binglog file size is max
 * sync trunk binlog file correctly when trunk server changed

Version 3.06  2012-01-22
 * add common/avl_tree.h and common/avl_tree.c
 * organize trunk free blocks using AVL tree
 * find the trunk server for each group when current tracker be a leader
 * common/sched_thread.c can add schedule entry dynamicly
 * support creating trunk file advancely

Version 3.05  2011-12-20
 * remove compile warnings
 * storage server's store_path_count can be more than that of group
 * bug fixed: common/fast_mblock.c malloc bytes are not enough
 * make.sh support OS: HP-UX

Version 3.04  2011-11-25
 * bug fixed: duplicate files only save one entry ok with trunk file mode
 * bug fixed: sync correctly with more binlog files
 * fdfs_file_info query file info from storage server
 * bug fixed: php extension compile error using gcc 4.6.1 as:
   variable 'store_path_index' set but not used
 * bug fixed: delete the metadata of trunked file correctly
 * bug fixed: append file ok when check duplicate is on
 * storage/trunk_mgr/trunk_shared.[hc]: trunk_file_stat_func do not 
   use function pointer
 * bug fixed: storage/trunk_mgr/trunk_shared.c base64_decode_auto 
   overflow 1 byte
 * bug fixed: delete slave file correctly
 * bug fixed: remove debug info
 * md5 function name changed to avoid conflict

Version 3.03  2011-10-16
 * ignore existed link when sync link file
 * http token checking support persistent token
 * add functions: storage_file_exist and storage_file_exist1
 * php minfo add fastdfs version info
 * make.sh changed
 * client move libevent dependency

Version 3.02  2011-09-18
 * bug fixed: tracker_mem_check_add_tracker_servers add tracker server 
   correctly
 * php client compile ok with php 5.2.17
 * re-select trunk server ok

Version 3.01  2011-07-31
 * bug fixed: tracker_get_connection_ex and tracker_get_connection_r_ex 
   connect two times with multi tracker servers
 * bug fixed: tracker_mem_check_add_tracker_servers condition not correct
 * all logError add source filename and line
 * php extension support upload file callback
 * php extension support download file callback

Version 3.00  2011-06-19
 * mass small files optimization
 * add fixed block memory pool: common/fast_mblock.c
 * bug fixed: tracker_mem.c do NOT clear g_groups fields
 * bug fixed: slave file and appender file download ok
 * bug fixed: tracker / storage run by group / user, set file owner
 * tracker server support leader
 * client support static library
 * client_func.h add functions fdfs_tracker_group_equals and 
   fdfs_get_file_ext_name
 * bug fixed: test/dfs_func_pc.c compile ok
 * storage server check free space enough when upload a file

Version 2.09  2011-02-19
 * bug fixed: write_to_binlog_index then increase g_binlog_index (feedback 
   by koolcoy)
 * disk read / write supports direct mode (avoid caching by the file system)

Version 2.08  2011-01-30
 * bug fixed: fdfs_trackerd.c set g_tracker_thread_count to 0
 * add cmd TRACKER_PROTO_CMD_SERVER_LIST_ONE_GROUP to support list one group
 * support disk recovery automatically
 * support total_upload_bytes, success_upload_bytes, total_download_bytes and 
   success_download_bytes etc. 18 stat fields
 * tracker data file storage_groups.dat changes to storage_groups_new.dat, and 
   storage_servers.dat changes to storage_servers_new.dat
 * support file append, add tests: fdfs_appender_test and fdfs_appender_test1
 * storage_dio.c: dio_deal_task split to several functions
 * tracker http check thread exit normally
 * function fdfs_get_file_info_ex changed, add function fdfs_get_file_info_ex1
 * fix some type cast error when compile with c++
 * client add tools: fdfs_upload_appender and fdfs_append_file

Version 2.07  2011-01-09
 * slave file's prefix name can be empty
 * FDFS_MAX_GROUPS change from 64 to 512
 * file size field in the file id changed: high 32 bits is random integer 
   when the file size < 2GB and the highest bit set to 1
 * tracker_service.c: in function list_group_storages, use strcpy 
   intead of memcpy
 * php extension add function fastdfs_tracker_delete_storage
 * client add tool: fdfs_file_info to get file info, including file size,
   create timestamp, source storage ip address and crc32 signature
 * fdfs_upload_file.c: omit more error info when the local file not exist

Version 2.06  2010-12-26
 * sync file op: do not sync the file which exists on dest storage server
   and the file size are same 
 * bug fixed: sync copy file will clear the existed file on dest storage
   server (truncate the file size to 0), this bug caused by V2.04
 * bug fixed: make temp file discard system function mkstemp, 
   use file sequence No. with pthread_mutex_lock
 * bug fixed: function fastdfs_tracker_list_groups, when parameter group_name
   is null or empty string, return all groups info
 * bug fixed: upload a file extends 2GB will fail
 * bug fixed: tracker to tracker sync system data files, in function: 
   tracker_mem_get_tracker_server, pTrackerStatus not be set properly

Version 2.05  2010-12-05
 * client/fdfs_monitor.c: add sync delay time
 * tracker/fast_task_queue.c: pTask->data = pTask->arg + arg_size; 
   change to: pTask->data = (char *)pTask->arg + arg_size;
 * bug fixed: storage_sync.c line 237 cause core dump in Ubuntu 10.04
 * upload file test use mmap, support more test_upload processes
 * client add three tools: fdfs_upload_file, fdfs_download_file and 
   fdfs_delete_file

Version 2.04  2010-11-19
 * storage.conf: tracker server ip can NOT be 127.0.0.1
 * do not catch signal SIGABRT
 * strerror change to STRERROR macro
 * sync copy file use temp filename first, rename to the correct filename 
   when sync done
 * file id use 4 bytes CRC32 signature instead of random number
 * add file: client/fdfs_crc32.c
 * one of file hash code signature function change from APHash_ex 
   to simple_hash_ex
 * bug fixed: when fdfs_storaged quit, maybe write to binlog file fail,
   the error info is "Bad file descriptor"

Version 2.03  2010-11-08
 * bug fixed: core dump when http.need_find_content_type=false and 
   http.anti_steal.check_token=true
 * storage server add join_time field (create timestamp of this storage)
 * tracker server fetch system files from other tracker server when 
   first storage server join in (tracker to tracker sync system files)
 * tracker server changes the old ip address to the new address when the 
   storage server ip address changed
 * tracker to tracker sync system data files in some case, multi tracker
   server supported well

Version 2.02  2010-10-28
 * get parameters function from tracker server changed, 
   add parameter: storage_sync_file_max_delay
 * local ip functions move to common/local_ip_func.c
 * when query all storage servers to store, do not increase the current
   write server index
 * struct FDFSHTTPParams add field: need_find_content_type
 * symbol link client library to /usr/lib64 in 64 bits OS
 * storage_client.c: deal file extension name correctly

Version 2.01  2010-10-17
 * client/fdfs_monitor.c can specify tracker server
 * micro STORAGE_STORE_PATH_PREFIX_CHAR change to 
   FDFS_STORAGE_STORE_PATH_PREFIX_CHAR
 * php extension can set log filename
 * php extension add function: fastdfs_client_version
 * bug fixed: client/tracker_client.c tracker_get_connection_ex NULL pointer
 * set max core dump file size to at least 256MB when DEBUG_FLAG is on, 
   make sure to generate core file when core dump with DEBUG_FLAG on
 * upload file can get available storage server list of the group, 
   add command TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITHOUT_GROUP_ALL and
   TRACKER_PROTO_CMD_SERVICE_QUERY_STORE_WITH_GROUP_ALL
 * bug fixed: storage core dump in some case

Version 2.00  2010-08-22
 * tracker network io use libevent instead of traditional io model
 * storage network io use libevent instead of traditional io model
 * storage disk read/write use separate threads
 * tracker_mem.c malloc single group and storage struct, remove referer
 * make install copy config files
 * tracker.conf add two parameters: storage_sync_file_max_delay and 
   storage_sync_file_max_time
 * client tracker_get_connection increase server_index correctly
 * storage sync to storage server adds active test
 * test programs compile ok

Version 1.29  2010-06-30
 * add files: tracker_dump.h and tracker_dump.c, tracker dump global vars
 * add files: storage_dump.h and storage_dump.c, storage dump global vars
 * sockopt.c: tcprecvfile and tcpdiscard add parameter total_recv_bytes
 * storage server add fields: storage_port and storage_http_port
 * auto rename synced remark files when the port of all storage servers 
   in a group changed to another port
 * connect server support timeout, adding connect_timeout parameter in 
   config file
 * log_init set log to cache to false (no cache)

Version 1.28  2010-05-30
 * tracker_servive.c: set current_write_group anyway when current group
   out of space
 * logger support context (multi instance)
 * get storage servers by filename: if the file created one day ago (the create 
   timestamp of the file < current_time - 86400), any active storage server matches
 * add files: common/pthread_func.h and common/pthread_func.c
 * common/sched_thread.h, remove statement: extern bool g_continue_flag;
 * client add libfastcommon
 * global variables: g_base_path, g_network_timeout, g_version change to 
   g_fdfs_base_path, g_fdfs_network_timeout, g_fdfs_version
 * common/fdfs_base64.h/c change name to common/base64.h/c
 * make.sh use TARGET_PREFIX instead of TARGET_PATH
 * protocol add ACTIVE_TEST, tracker and storage both support
 * php client, bug fixed: fastdfs_connect_server, the sock must init to -1
 * bug fixed: storage status not correct with multi tracker servers
 * sync storage mark file and stat file to disk properly

Version 1.27  2010-04-10
 * storage.conf: add if_alias_prefix parameter to get the ip address of the 
   local host
 * storage http support domain name
 * php extension add some parameters in fastdfs_client.ini
 * make.sh compile use debug mode
 * type off_t change to int64_t
 * redirect stdout and stderr to log file
 * php extension list_groups add fields: version and http_domain

Version 1.26  2010-02-28
 * remove compile warning of logError
 * ini reader support section
 * bug fixed: tracker/tracker_mem.c sync storage server status
 * use storage server http server port anyway
 * bug fixed: ini reader can support relative config filename
 * function enhancement: tracker server can check storage HTTP server alive

Version 1.25  2010-02-04
 * storage_sync.c if source file not exist when sync a file, change from 
   logWarning to logDebug
 * filename buff size change from 64 to 128
 * bug fixed: c client and php client, log not inited cause core dump when 
   call log functions
 * can print stack trace when process core dumped in Linux server
 * bug fixed: tracker/tracker_mem.c load storage servers fail with many groups
   and storage servers
 * common/sockopt.c remove debug info
 * storage stat add fields: version
 * auto adjust when storage server ip address changed
 * bug fixed: when add a new storage server, other storage servers' status keep
   the same, not changed
 * add macros, compile passed in cygwin, thanks Seapeak
 * write to system data file using lock
 * common/ini_file_reader.c: use one context parameter, not two parameters
 * storage status sync modified (the code of tracker and storage both changed)
 * when recv kill signal, worker thread quit more quickly, daemon process 
   fdfs_trackerd and fdfs_storage quit very quickly when recv kill signal
 * remove compile warning info of logError
 * tracker server start more quickly with many groups and storage servers
 * bug fixed: correct off_t printf format

Version 1.24  2010-01-06
 * call php_fdfs_close with TSRMLS_CC as php_fdfs_close(i_obj TSRMLS_CC)
 * storage server to storage server report ip address as tracker client
 * bug fixed: sendfile exceeds 2GB file in Linux
 * bug fixed: delete storage server 
 * storage stat add fields: up_time and src_ip_addr
 * big static or struct memeber char array buffer change to malloc in order to
   decrease stack size
 * FDFS_WRITE_BUFF_SIZE  change from 512KB to 256KB
 * bug fixed: client/storage_client.c, meta data miss when upload file
 * decrease thread_stack_size default value in config files: tracker.conf 
   and storage.conf

Version 1.23  2009-11-29
 * remove unuseless variable "sleep_secs" in tracker_report_thread_entrance
 * storage can bind an address when connect to other servers (as a client)
 * common/md5.h fix UINT4 typedef wrong type in 64 bit OS
 * client/fdfs_test.c: print the source ip address decoded from the remote 
   filename
 * client add function fdfs_get_file_info
 * php extension add functions: fastdfs_http_gen_token and fastdfs_get_file_info
 * server process will exit when the http service starts fail
 * support file group, a master file with many slave files whose file id can be 
   combined from master file id and prefix
 * php client support uploading slave file
 * ip address in filename change from host byte order to network byte order
 * storage sync performance enhancement, using read buffer of 64KB to avoid 
   reading binlog file repeatly
 * storage add prototol cmd: STORAGE_PROTO_CMD_QUERY_FILE_INFO
 * FDFS_FILE_EXT_NAME_MAX_LEN changed from 5 to 6
 * get file info support slave file
 * storage server for uploading file support priority

Version 1.22  2009-10-12
 * bug fixed: common/shared_func.c allow_hosts array maybe overflow in some case
 * tracker/tracker_mem.c: protocol TRACKER_PROTO_CMD_SERVICE_QUERY_FETCH_ALL, 
   return at least a storage server when active storage 
   server count of the group > 0
 * bug fixed: when client connection disconnected, always log debug or error info
 * make.sh: default not install FastDFS services in Linux server
 * common/sockopt.c: setsockopt level SOL_TCP only supported in Linux
 * common/http_func.c: do not use function strsep because strsep is not portable
 * client upload file support callback function
 * client support multi tracker groups (multi FastDFS clusters)
 * bug fixed: thread_stack_size not correct when the param thread_stack_size 
   not set in the config file
 * supply php extension (directory name: php_client)
 * c client reconnect server (tracker or storage) when network IO error
 * c client: make tracker server index counter thread safely

Version 1.21  2009-09-19
 * bug fixed: when source storage server synced file to new storage server done,
   it's status changed to ONLINE (should keep as ACTIVE, report by zhouzezhong)
 * add thread_stack_size in config file, default value is 1MB (report by chhxo)
 * tracker and storage server use setsockopt to keep alive 
   (report by zhouzezhong)
 * bug fixed: storage server with multi-path, upload file fail when the free 
   space of each path <= reserved space (the total free space > reserved space,
   report by zhouzezhong)
 * storage_sync.c: when connect fail, do not change the dest storage server '
   status to offline
 * tracker_service.c and storage_service.c change log level from WARNING to DEBUG 
   when client connection disconnected (report by Jney402)
 * bug fixed: tracker_client.c correct store_path_index return by tracker server
   (report by happy_fastdfs)
 * bug fixed: tracker_service.c when store_lookup set to 2 (load balance), use 
   another pthread lock to avoid long time lock waiting
   (report by happy_fastdfs)
 * add service shell scripts in directory: init.d 
   (services will auto installed on Linux, report by hugwww)

Version 1.20  2009-09-05
 * base64 use context, functions changed
 * common/ini_file_reader.c: fix memory leak
 * tracker server support HTTP protocol, one thread mode
 * storage server support HTTP protocol, one thread mode
 * fix bug: storage server rebuild, auto sync data correctly
 * fix bug: sync data fail (correct storage server status)
 * when storage server idle time exceeds check_active_interval seconds, 
   set it's status to offline
 * tracker counter thread safely

Version 1.19  2009-07-23
 * use poll instead of select in sockopt.c
 * hash.c use chain impl by self
 * use FastDHT 1.09 client code
 * ini reader support HTTP protocol, conf file can be an url
 * correct test dir compile error
 * use non-block socket to increase network IO performance
 * add cmd TRACKER_PROTO_CMD_SERVICE_QUERY_FETCH_ALL: query all storage servers 
   from which the file can be dowloaded
 * while (1) ... break; changed to do ... while (0);

Version 1.18  2009-05-24
 * restart.sh only kill the programs match the program name and all parameters
 * correct get local ip addresses
 * common files do not use global vars like g_network_timeout and g_base_path
 * download file support offset and download bytes
 * hash function change type from unsigned int to signed int
 * file size in file name support 64 bits, old bytes is 4, new bytes is 8

Version 1.17  2009-03-19
  * add test programs at sub directory test/
  * common/shared_func.c: rindex change to strrchr, add #include <netinet/in.h>
  * support SunOS (Solaris), compile passed on SunOS 5.10
  * support AIX, compile passed on AIX 5.3
  * sys call statfs change to statvfs
  * use scheduling thread to sync binlog buff / cache to disk, add parameter
   "sync_binlog_buff_interval" to conf file storage.conf
  * use FastDHT v1.07 client code

Version 1.16  2009-02-14
  * client can specify group name when upload file
  * tracker_service.c: cmd dispatch changed to "switch ... case" 
    not "if ... else if"
  * storage_service.c: call fdfs_quit before tracker_disconnect_server

Version 1.15  2009-01-28
  * use FastDHT v1.04 client code
  * use FastDHT client thread safely

Version 1.14  2009-01-18
  * storage/storage_sync.c: 
    old: if (reader.sync_row_count % 1000 == 0)
    new: if (reader.scan_row_count % 2000 == 0)
  * little adjustment for common files can be used by FastDHT
  * sched_thread.h /.c add global variable g_schedule_flag to quit normally
  * shared_func.h / .c add function get_time_item_from_conf
  * sched_thread.h /.c support time_base of task
  * hash.h / .c add function CRC32, add hash function to support stream hash
  * add FastDHT client files in storage/fdht_client/
  * create symbol link when the file content is duplicate, 
    add item "check_file_duplicate" to conf file storage.conf
  * use FastDHT v1.02 client code
  * auto delete invalid entry in FastDHT when the source file does not exist

Version 1.13  2008-11-29
  * re-calculate group 's free space when one of it's storage servers' 
    free space increase
  * add parameters: sync_interval, sync_start_time and sync_end_time to 
    storage.conf
  * performance enhancement: log to buffer, flush to disk every interval seconds
  * standard fds closed by daemon_init: 0(stdin), 1(stdout) and 2(stderr)
  * fix bug: pthread_kill sometimes cause core dump when program terminated
  * fix bug: sync.c open next binlog cause loop call

Version 1.12  2008-11-12
  * storage server support multi path (mount point)
  * upload file support file ext name, add source storage ip address to filename
  * add delete command to delete the invalid storage server
  * add client functions which combine group name and filename to file id,
    add anothor client test program: fdfs_test1.c to use file id
  * client download file support callback function
  * add protocol cmd TRACKER_PROTO_CMD_SERVICE_QUERY_UPDATE, 
    and client API add tracker_query_storage_update
  * add protocol cmd TRACKER_PROTO_CMD_STORAGE_SYNC_REPORT to report last 
    synced timestamp as dest server
  * fix sync old data files to new server bug
  * fcntl change to pthread_mutex_lock

Version 1.11  2008-10-04
  * kill report and sync threads when recv terminate signal
  * add item "store_server" in tracker.conf, by default use the first 
    storage server to store uploaded files
  * ini_file_reader.c changed: a conf file can include other conf files
  * some adjustment:
    some macro name changed
    add common_define.h
    remove fdfs_define.c
    fdfs_os_bits.h change to _os_bits.h

Version 1.10  2008-09-20
  * performance optimizing: use thread pool, create all work threads at startup
  * trim function op in shared_func.c
  * add Makefile template Makefile.in, delete Makefile and Makefile.freebsd
    change make.sh to support all unix systems (passed in Linux and FreeBSD)

Version 1.9  2008-09-14
  * security enhancement: support allow hosts which can connect to the server
  * server can be run by the specified group and user, set by the config file
  * change make.sh and add file common/fdfs_os_bits.h, 
    remove the warning info of printf format for int64_t param in 64 bits system
  * storage_client.c changed: auto connect to storage server when not connected
  * change some macro name and function name in tracker/tracker_proto.h

Version 1.8  2008-09-07
  * communication protocol changed to support large file exceed 2GB:
     # all integer field is 8 bytes big-endian
     # group name fixed length: FDFS_GROUP_NAME_MAX_LEN bytes
  * storage stat numbers (such as total_upload_count, success_upload_count) 
    use int64_t (8 bytes integer)
  * ini_file_reader.c add function iniGetInt64Value
  * sockopt.c add function tcpsetnonblockopt
  * shared_func.c add function set_nonblock

Version 1.7  2008-08-31
  * performance optimizing: 
     # change fopen to syscall open
     # increase the efficiency of socket functions tcpsenddata and tcprecvdata
  * change the return value of socket funtions such as tcpsenddata, 
    tcprecvdata and connectserverbyip
      old return value: result=1 for success, result != 1 fail
      new return value: result=0 for success, result != 0 fail, return the error code
  * log function enhancement: 
     # support log level
     # parameter "log_level" added to server config file
     # keep the log file opened to increase performance
  * fix log format and parameter mismatched bug (check by printf)
  * log CRIT message to log file when program exit unexpectedly
  * Makefile add compile flag -D_FILE_OFFSET_BITS=64 to support large files
  * change the type of file_size and file_offset to off_t
  * change signal to sigaction
  * fix client Makefile to compile library correctly
  * restart.sh modified: use external command "expr" to replace shell command "let"

Version 1.6  2008-08-24
  * add restart daemon shell script: restart.sh
  * use setrlimit to increase max open files if necessary
  * security enhancement: the format of data filename must be: HH/HH/filename,
    eg. B9/F4/SLI2NAAMRPR9r8.d
  * fix bug: errno is not correct where the downloaded file does not exist,
             communication is broken when the download file is a directory

Version 1.5  2008-08-17
  * add client function storage_download_file_to_file
  * use pthread_attr_setstacksize to increase thread stack size to 1 MB
  * use sendfile syscall to send file in Linux and FreeBSD
  * fix bug: add O_TRUNC flag when open file to write
  * remove warning info compiled by gcc 4.2
  * fcntl set lock.l_len to 0

Version 1.4  2008-08-10
  * storage server recv file method change 
     old method: recv the whole file content/buff before write to file
     new method: write to file once recv a certain bytes file buff, eg. 128KB buff size
  * storage client and storage server send file method change 
     old method: get the whole file content/buff, then send to storage server
     new method: send file to storage server more times. get a certain bytes file buff, then send to storage server
  * upload file package remove the one pad byte field
  * remove storage status FDFS_STORAGE_STATUS_DEACTIVE and add FDFS_STORAGE_STATUS_DELETED

Version 1.3  2008-08-03
  * fix bug: when meta data is empty, get meta data return error
  * support java client
    # memset response header to 0
    # add group_name to upload file response package

Version 1.2  2008-07-27
  * add client function storage_set_metadata to support setting metadata(overwrite or merge)

Version 1.1  2008-07-20
  * implement storage disk report
  * storing load balance between storage groups(volumes) when set store_lookup to 2

Version 1.0  2008-07-12
  * first version



================================================
FILE: INSTALL
================================================
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.
Chinese language: http://www.fastken.com/

# 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:

   git clone https://github.com/happyfish100/libfastcommon.git
   cd libfastcommon; git checkout V1.0.84
   ./make.sh clean && ./make.sh && ./make.sh install


# step 2. download libserverframe source codes and install it,
#   github address:  https://github.com/happyfish100/libserverframe.git
#   gitee address:   https://gitee.com/fastdfs100/libserverframe.git
# command lines as:

   git clone https://github.com/happyfish100/libserverframe.git
   cd libserverframe; git checkout V1.2.12
   ./make.sh clean && ./make.sh && ./make.sh install

# step 3. 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:

   git clone https://github.com/happyfish100/fastdfs.git
   cd fastdfs; git checkout V6.15.4
   ./make.sh clean && ./make.sh && ./make.sh install


# step 4. 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 5. 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 6. run the server programs
# start the tracker server:
/usr/bin/fdfs_trackerd /etc/fdfs/tracker.conf restart

# start the storage server:
/usr/bin/fdfs_storaged /etc/fdfs/storage.conf restart

# (optional) in Linux, you can start fdfs_trackerd and fdfs_storaged as a service
# the default base_path is /opt/fastdfs, if you changed it, you MUST change the
# PIDFile of /usr/lib/systemd/system/fdfs_trackerd.service and
# /usr/lib/systemd/system/fdfs_storaged.service
/sbin/service fdfs_trackerd restart
/sbin/service fdfs_storaged restart

# step 7. (optional) run monitor program
# such as:
/usr/bin/fdfs_monitor /etc/fdfs/client.conf


# step 8. (optional) run the test program
# such as:
/usr/bin/fdfs_test <client_conf_filename> <operation>
/usr/bin/fdfs_test1 <client_conf_filename> <operation>

# 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

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
---------------------------------------------------
|  item name            |  type  | default | Must |
---------------------------------------------------
| base_path             | string |         |  Y   |
---------------------------------------------------
| disabled              | boolean| false   |  N   |
---------------------------------------------------
| bind_addr             | string |         |  N   |
---------------------------------------------------
| network_timeout       | int    | 30(s)   |  N   |
---------------------------------------------------
| max_connections       | int    | 256     |  N   |
---------------------------------------------------
| log_level             | string | info    |  N   |
---------------------------------------------------
| run_by_group          | string |         |  N   |
---------------------------------------------------
| run_by_user           | string |         |  N   |
---------------------------------------------------
| allow_hosts           | string |   *     |  N   |
---------------------------------------------------
| sync_log_buff_interval| int    |  10(s)  |  N   |
---------------------------------------------------
| thread_stack_size     | string |  1M     |  N   |
---------------------------------------------------
memo:
   * base_path is the base path of sub dirs: 
     data and logs. base_path must exist and it's sub dirs will 
     be automatically created if not exist.
       $base_path/data: store data files
       $base_path/logs: store log files
   * log_level is the standard log level as syslog, case insensitive
     # emerg: for emergency
     # alert
     # crit: for critical
     # error
     # warn: for warning
     # notice
     # info
     # debug
   * allow_hosts can occur more than once, host can be hostname or ip address,
     "*" means match all ip addresses, can use range like this: 10.0.1.[1-15,20]
      or host[01-08,20-25].domain.com, for example:
        allow_hosts=10.0.1.[1-15,20]
        allow_hosts=host[01-08,20-25].domain.com

2. tracker server items
---------------------------------------------------
|  item name            |  type  | default | Must |
---------------------------------------------------
| port                  | int    | 22000   |  N   |
---------------------------------------------------
| store_lookup          | int    |  0      |  N   |
---------------------------------------------------
| store_group           | string |         |  N   |
---------------------------------------------------
| store_server          | int    |  0      |  N   |
---------------------------------------------------
| store_path            | int    |  0      |  N   |
---------------------------------------------------
| download_server       | int    |  0      |  N   |
---------------------------------------------------
| reserved_storage_space| string |  1GB    |  N   |
---------------------------------------------------

memo: 
  * the value of store_lookup is:
    0: round robin (default)
    1: specify group
    2: load balance (supported since V1.1)
  * store_group is the name of group to store files.
    when store_lookup set to 1(specify group), 
    store_group must be set to a specified group name.
  * reserved_storage_space is the reserved storage space for system 
    or other applications. if the free(available) space of any storage
    server in a group <= reserved_storage_space, no file can be uploaded
    to this group (since V1.1)
    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)

3. storage server items
-------------------------------------------------
|  item name          |  type  | default | Must |
-------------------------------------------------
| group_name          | string |         |  Y   |
-------------------------------------------------
| tracker_server      | string |         |  Y   |
-------------------------------------------------
| port                | int    | 23000   |  N   |
-------------------------------------------------
| heart_beat_interval | int    |  30(s)  |  N   |
-------------------------------------------------
| stat_report_interval| int    | 300(s)  |  N   |
-------------------------------------------------
| sync_wait_msec      | int    | 100(ms) |  N   |
-------------------------------------------------
| sync_interval       | int    |   0(ms) |  N   |
-------------------------------------------------
| sync_start_time     | string |  00:00  |  N   |
-------------------------------------------------
| sync_end_time       | string |  23:59  |  N   |
-------------------------------------------------
| store_path_count    | int    |   1     |  N   |
-------------------------------------------------
| store_path0         | string |base_path|  N   |
-------------------------------------------------
| store_path#         | string |         |  N   |
-------------------------------------------------
|subdir_count_per_path| int    |   256   |  N   |
-------------------------------------------------
|check_file_duplicate | boolean|    0    |  N   |
-------------------------------------------------
| key_namespace       | string |         |  N   |
-------------------------------------------------
| keep_alive          | boolean|    0    |  N   |
-------------------------------------------------
| sync_binlog_buff_interval| int |   60s |  N   |
-------------------------------------------------

memo:
  * tracker_server can occur more than once, and tracker_server format is
    "host:port", host can be hostname or ip address.
  * store_path#, # for digital, based 0
  * check_file_duplicate: when set to true, must work with FastDHT server, 
    more detail please see INSTALL of FastDHT. FastDHT download page: 
    http://code.google.com/p/fastdht/downloads/list
  * key_namespace: FastDHT key namespace, can't be empty when 
    check_file_duplicate is true. the key namespace should short as possible
 


================================================
FILE: README.md
================================================
FastDFS is an open source high performance distributed file system. Its major
functions include: file storing, file syncing and file accessing (file uploading
and file downloading), and it can resolve the high capacity and load balancing
problem. FastDFS should meet the requirement of the website whose service based
on files such as photo sharing site and video sharing site.

### FastDFS Features

* grouped storage servers, simple and flexible
* peer-to-peer structure, no single point of failure
* The file ID is generated by FastDFS and serves as a credential for file access
  FastDFS does not require the traditional name server or meta server
* support large, medium, and small files well; supports the merged storage for small files
  and can store a massive number of small files
* the storage server supports multiple disks and supports data recovery for the single disk
* provide a nginx extension module that can seamlessly integrate with nginx
* support IPv6, NAT network and cross data center or hybrid cloud deployment
* support read-write separation and cross data center disaster backup
* provide truncate, append and modify APIs for appender files
* supports multi-threaded file upload and download, support resume from a broken point

### Architecture Interpretation

FastDFS has two roles: tracker and storage. The tracker takes charge of
scheduling and load balancing for file access. The storage store files and it's
function is file management including: file storing, file syncing, providing file
access interface. It also manage the meta data which are attributes representing
as key value pair of the file. For example: width=1024, the key is "width" and
the value is "1024".

The tracker and storage contain one or more servers. The servers in the tracker
or storage cluster can be added to or removed from the cluster by any time without
affecting the online services. The servers in the tracker cluster are peer to peer.

The storage servers organizing by the file group to obtain high capacity.
The storage system contains one or more groups whose files are independent among
these groups. The capacity of the whole storage system equals to the sum of all
groups' capacity. A file group contains one or more storage servers whose files
are same among these servers. The servers in a file group backup each other,
and all these servers are load balancing. When adding a storage server to a
group, files already existing in this group are replicated to this new server
automatically, and when this replication done, system will switch this server
online to providing storage services.

When the whole storage capacity is insufficient, you can add one or more
groups to expand the storage capacity. To do this, you need to add one or
more storage servers.

The identification of a file is composed of two parts: the group name and
the file name.

Client test code use client library please refer to the directory: client/test.

### Client SDK

* C Language: client/ subdir under FastDFS source code, header files default installation path is /usr/include/fastdfs/
* PHP extension: php_client/ subdir under FastDFS source code
* [Java SDK: https://github.com/happyfish100/fastdfs-client-java](https://github.com/happyfish100/fastdfs-client-java)
* [Go SDK: https://github.com/qifengzhang007/fastdfs_client_go](https://github.com/qifengzhang007/fastdfs_client_go)

For [FastDFS installation and configuration documentation](https://github.com/happyfish100/fastdfs/wiki), please refer to [the Wiki](https://github.com/happyfish100/fastdfs/wiki);
For more FastDFS related articles, please subscribe the Wechat/Weixin public account (Chinese Language): fastdfs

### See also

FastDFS is a lightweight object storage solution. If you need a general distributed
file system for databases, K8s and virtual machines (such as KVM), you can learn about
[FastCFS](https://github.com/happyfish100/FastCFS) which achieves strong data consistency
and high performance.

We provide technical support service and customized development. Welcome to use WeChat or email for discuss.

email: 384681(at)qq(dot)com


================================================
FILE: README_zh.md
================================================
  FastDFS是一款开源的分布式文件系统,功能主要包括:文件存储、文件同步、文件访问(文件上传、文件下载)等,解决了文件大容量存储和高性能访问的问题。FastDFS特别适合以文件为载体的在线服务,如图片、视频、文档等等服务。

  FastDFS作为一款轻量级分布式文件系统,版本V6.13代码量约7.4万行。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特点

* 分组存储,简单灵活;
* 对等结构,不存在单点;
* 文件ID由FastDFS生成,作为文件访问凭证。FastDFS不需要传统的name server或meta server;
* 大、中、小文件均可以很好支持;支持小文件合并存储,可以存储海量小文件;
* 一台storage支持多块磁盘,支持单盘数据恢复;
* 提供了nginx扩展模块,可以和nginx无缝衔接;
* 支持IPv6,支持NAT网络,支持跨机房或混合云部署方式;
* 支持读写分离,支持跨机房灾备;
* 提供了对appender类型文件truncate、append和modify接口;
* 支持多线程方式上传(仅适用于appender类型文件,通过truncate + modify实现)和下载文件,支持断点续传;
* 存储服务器上可以保存文件附加属性。

  FastDFS安装和配置文档参见 [Wiki](https://gitee.com/fastdfs100/fastdfs/wikis/Home);FastDFS更多更详细的功能和特性介绍,请参阅FastDFS微信公众号的其他文章,搜索公众号:fastdfs。

### 客户端SDK

* C语言:源码目录下的 client/,头文件默认安装到 /usr/include/fastdfs/
* PHP扩展:源码目录下的 php_client/
* [Java SDK:https://gitee.com/fastdfs100/fastdfs-client-java](https://gitee.com/fastdfs100/fastdfs-client-java)
* [Go SDK: https://gitee.com/daitougege/fastdfs_client_go](https://gitee.com/daitougege/fastdfs_client_go)

### 其他

  FastDFS是轻量级的对象存储解决方案,如果你在数据库、K8s和虚拟机(如KVM)等场景,需要使用通用分布式文件系统,可以了解一下保证数据强一致性且高性能的 [FastCFS](https://gitee.com/fastdfs100/FastCFS)。

  我们提供商业技术支持和定制化开发,欢迎微信或邮件洽谈。

  email: 384681(at)qq(dot)com


================================================
FILE: benchmarks/.gitignore
================================================
# Compiled binaries
benchmark_upload
benchmark_download
benchmark_concurrent
benchmark_small_files
benchmark_large_files
benchmark_metadata

# Object files
*.o
*.so
*.a

# Results
results/*.json
results/*.csv
results/*.log
!results/template.json

# Reports
*.html
*.pdf
!report_template.html

# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
venv/
env/
ENV/

# IDE
.vscode/
.idea/
*.swp
*.swo
*~

# OS
.DS_Store
Thumbs.db

# Temporary files
*.tmp
*.bak
*.backup


================================================
FILE: benchmarks/Makefile
================================================
# FastDFS Benchmark Suite Makefile

CC = gcc
CFLAGS = -Wall -Wextra -O2 -pthread -I../client -I../common
LDFLAGS = -L../client -L../common -lfdfsclient -lfastcommon -lpthread -lm

# Source files
UPLOAD_SRC = benchmark_upload.c
DOWNLOAD_SRC = benchmark_download.c
CONCURRENT_SRC = benchmark_concurrent.c
SMALL_FILES_SRC = benchmark_small_files.c
LARGE_FILES_SRC = benchmark_large_files.c
METADATA_SRC = benchmark_metadata.c

# Output binaries
UPLOAD_BIN = benchmark_upload
DOWNLOAD_BIN = benchmark_download
CONCURRENT_BIN = benchmark_concurrent
SMALL_FILES_BIN = benchmark_small_files
LARGE_FILES_BIN = benchmark_large_files
METADATA_BIN = benchmark_metadata

# All targets
ALL_BINS = $(UPLOAD_BIN) $(DOWNLOAD_BIN) $(CONCURRENT_BIN) \
           $(SMALL_FILES_BIN) $(LARGE_FILES_BIN) $(METADATA_BIN)

.PHONY: all clean install help test

# Default target
all: $(ALL_BINS)
	@echo ""
	@echo "✓ All benchmarks compiled successfully!"
	@echo ""
	@echo "Run 'make test' to verify the build"
	@echo "Run 'make install' to install benchmarks"
	@echo "Run './scripts/run_all_benchmarks.sh' to run all benchmarks"

# Individual benchmark targets
$(UPLOAD_BIN): $(UPLOAD_SRC)
	@echo "Compiling $@..."
	$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)

$(DOWNLOAD_BIN): $(DOWNLOAD_SRC)
	@echo "Compiling $@..."
	$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)

$(CONCURRENT_BIN): $(CONCURRENT_SRC)
	@echo "Compiling $@..."
	$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)

$(SMALL_FILES_BIN): $(SMALL_FILES_SRC)
	@echo "Compiling $@..."
	$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)

$(LARGE_FILES_BIN): $(LARGE_FILES_SRC)
	@echo "Compiling $@..."
	$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)

$(METADATA_BIN): $(METADATA_SRC)
	@echo "Compiling $@..."
	$(CC) $(CFLAGS) -o $@ $< $(LDFLAGS)

# Clean build artifacts
clean:
	@echo "Cleaning build artifacts..."
	rm -f $(ALL_BINS)
	rm -f *.o
	rm -f results/*.json
	@echo "✓ Clean complete"

# Install benchmarks to system
install: all
	@echo "Installing benchmarks to /usr/local/bin..."
	@mkdir -p /usr/local/bin
	@for bin in $(ALL_BINS); do \
		install -m 755 $$bin /usr/local/bin/; \
		echo "  Installed $$bin"; \
	done
	@echo "✓ Installation complete"

# Test that benchmarks can run
test: all
	@echo "Testing benchmarks..."
	@for bin in $(ALL_BINS); do \
		echo "  Testing $$bin..."; \
		./$$bin --help > /dev/null 2>&1 && echo "    ✓ $$bin OK" || echo "    ✗ $$bin FAILED"; \
	done
	@echo "✓ Tests complete"

# Show help
help:
	@echo "FastDFS Benchmark Suite - Makefile"
	@echo ""
	@echo "Targets:"
	@echo "  all              - Build all benchmarks (default)"
	@echo "  clean            - Remove build artifacts"
	@echo "  install          - Install benchmarks to /usr/local/bin"
	@echo "  test             - Test that benchmarks can run"
	@echo "  help             - Show this help message"
	@echo ""
	@echo "Individual benchmarks:"
	@echo "  $(UPLOAD_BIN)"
	@echo "  $(DOWNLOAD_BIN)"
	@echo "  $(CONCURRENT_BIN)"
	@echo "  $(SMALL_FILES_BIN)"
	@echo "  $(LARGE_FILES_BIN)"
	@echo "  $(METADATA_BIN)"
	@echo ""
	@echo "Usage:"
	@echo "  make              # Build all benchmarks"
	@echo "  make clean        # Clean build artifacts"
	@echo "  make install      # Install to system"
	@echo "  make test         # Test benchmarks"
	@echo ""

# Dependencies (simplified - in real project would use proper dependency tracking)
$(UPLOAD_BIN): $(UPLOAD_SRC)
$(DOWNLOAD_BIN): $(DOWNLOAD_SRC)
$(CONCURRENT_BIN): $(CONCURRENT_SRC)
$(SMALL_FILES_BIN): $(SMALL_FILES_SRC)
$(LARGE_FILES_BIN): $(LARGE_FILES_SRC)
$(METADATA_BIN): $(METADATA_SRC)


================================================
FILE: benchmarks/README.md
================================================
# FastDFS Benchmarking & Performance Testing Suite

## Overview

Comprehensive performance testing suite for FastDFS that measures throughput, IOPS, latency percentiles, and resource utilization. Use it to establish baselines, identify bottlenecks, compare versions, and optimize your FastDFS deployment.

## Features

✅ **6 Specialized Benchmarks**: Upload, Download, Concurrent, Small Files, Large Files, Metadata  
✅ **Multi-threaded Testing**: Simulate concurrent user loads  
✅ **Comprehensive Metrics**: Throughput (MB/s), IOPS, Latency (p50/p95/p99), Success Rates  
✅ **Automated Execution**: Run all benchmarks with a single command  
✅ **Beautiful HTML Reports**: Generate professional performance reports  
✅ **Version Comparison**: Compare performance across FastDFS versions  
✅ **No External Dependencies**: Python scripts use only standard library (no pip install needed)

## Directory Structure

```
benchmarks/
├── README.md                   # This file
├── benchmark_upload.c          # Upload performance testing
├── benchmark_download.c        # Download performance testing
├── benchmark_concurrent.c      # Concurrent operations testing
├── benchmark_small_files.c     # Small file optimization testing
├── benchmark_large_files.c     # Large file performance
├── benchmark_metadata.c        # Metadata operations benchmark
├── results/                    # Benchmark results storage
│   └── template.json           # Result template
├── scripts/                    # Automation scripts
│   ├── run_all_benchmarks.sh   # Run all benchmarks
│   ├── generate_report.py      # Generate HTML/PDF reports
│   └── compare_versions.py     # Compare versions
└── config/                     # Configuration files
    └── benchmark.conf          # Benchmark configuration
```

## Prerequisites

- **FastDFS**: Installed and running (tracker + storage servers)
- **GCC Compiler**: For building C benchmarks
- **Make**: Build automation tool
- **Python 3.7+**: For report generation (no external packages needed)

**Platform Support**: Linux (recommended), macOS, Windows (use WSL)

## Quick Start (5 Minutes)

### 1. Build

```bash
cd benchmarks
make
```

### 2. Configure

Edit `config/benchmark.conf` and set your tracker server:

```ini
tracker_server = YOUR_TRACKER_IP:22122
```

### 3. Run Benchmarks

**Run all benchmarks:**
```bash
./scripts/run_all_benchmarks.sh
```

**Or run individual benchmark:**
```bash
./benchmark_upload --tracker 127.0.0.1:22122 --threads 10 --files 1000
```

### 4. Generate Report

```bash
python scripts/generate_report.py \
  --input results/benchmark_*.json \
  --output report.html
```

Open `report.html` in your browser to view results.

### 5. Compare Versions (Optional)

```bash
python scripts/compare_versions.py \
  --baseline results/v1.json \
  --current results/v2.json \
  --output comparison.html
```

## Benchmark Details

### 1. Upload Benchmark
Tests file upload performance with configurable concurrency.

```bash
./benchmark_upload --tracker 127.0.0.1:22122 --threads 10 --files 1000 --size 1048576
```

**Key Options**: `--threads`, `--files`, `--size`, `--warmup`  
**Use For**: Write performance, storage backend testing

### 2. Download Benchmark
Tests file download performance with multiple concurrent downloads.

```bash
./benchmark_download --tracker 127.0.0.1:22122 --threads 10 --iterations 1000
```

**Key Options**: `--threads`, `--iterations`, `--file-list`, `--prepare`  
**Use For**: Read performance, network bandwidth testing

### 3. Concurrent Operations
Simulates real-world mixed workload (upload/download/delete).

```bash
./benchmark_concurrent --tracker 127.0.0.1:22122 --users 50 --duration 300 --mix "50:45:5"
```

**Key Options**: `--users`, `--duration`, `--mix` (upload:download:delete ratio)  
**Use For**: Stress testing, capacity planning

### 4. Small Files Benchmark
Optimized for testing small file performance (<100KB).

```bash
./benchmark_small_files --tracker 127.0.0.1:22122 --threads 20 --count 10000
```

**Key Options**: `--threads`, `--count`, `--min-size`, `--max-size`  
**Use For**: High IOPS testing, metadata overhead measurement

### 5. Large Files Benchmark
Tests large file handling (>100MB).

```bash
./benchmark_large_files --tracker 127.0.0.1:22122 --threads 5 --count 10
```

**Key Options**: `--threads`, `--count`, `--min-size`, `--max-size`  
**Use For**: Streaming performance, disk I/O testing

### 6. Metadata Operations
Tests metadata query, update, and delete operations.

```bash
./benchmark_metadata --tracker 127.0.0.1:22122 --threads 10 --operations 10000
```

**Key Options**: `--threads`, `--operations`, `--mix` (query:update:delete ratio)  
**Use For**: Metadata performance, database backend testing

**Tip**: Run `./benchmark_* --help` for all available options.

## Understanding Results

### Key Metrics

**Throughput (MB/s)** - Data transfer rate (higher is better)  
- Good: >100 MB/s for modern systems

**IOPS** - Operations per second (higher is better)  
- Good: >1000 for small files, >100 for large files

**Latency (ms)** - Response time (lower is better)  
- **p50 (Median)**: 50% of requests complete within this time
- **p95**: 95% of requests complete within this time  
- **p99**: 99% of requests complete within this time
- Good: p95 < 50ms for small files

**Success Rate (%)** - Percentage of successful operations  
- Should be >99%

### Performance Indicators

✅ **Good Performance**
- High throughput (>100 MB/s)
- High IOPS (>1000 for small files)
- Low latency (p95 < 50ms)
- Success rate > 99%

⚠️ **Performance Issues**
- Low throughput → Check network, disk I/O
- High latency → Check system load, network latency
- Low success rate → Check logs, system resources

## Result Format

Benchmark results are stored in JSON format:

```json
{
  "benchmark": "upload",
  "timestamp": "2024-01-15T10:30:00Z",
  "version": "6.12.1",
  "config": {
    "threads": 10,
    "files": 1000,
    "file_size": 1048576
  },
  "metrics": {
    "throughput_mbps": 125.5,
    "iops": 1250,
    "latency_ms": {
      "mean": 8.2,
      "p50": 7.5,
      "p95": 15.3,
      "p99": 22.1,
      "max": 45.6
    },
    "success_rate": 99.8,
    "duration_seconds": 80.5
  },
  "resources": {
    "cpu_percent": 45.2,
    "memory_mb": 256.8,
    "network_mbps": 130.2
  }
}
```

## Common Use Cases

### 1. Baseline Performance Test
```bash
./scripts/run_all_benchmarks.sh --output results/baseline.json
```

### 2. Stress Testing
```bash
./benchmark_concurrent --users 100 --duration 300 --mix "50:45:5"
```

### 3. Version Comparison
```bash
# Before upgrade
./scripts/run_all_benchmarks.sh -o results/v6.11.json

# After upgrade
./scripts/run_all_benchmarks.sh -o results/v6.12.json

# Compare
python scripts/compare_versions.py \
  --baseline results/v6.11.json \
  --current results/v6.12.json \
  --output comparison.html
```

### 4. CI/CD Integration
```bash
#!/bin/bash
./scripts/run_all_benchmarks.sh --output results/ci_${BUILD_ID}.json
# Add threshold checks for automated validation
```

## Best Practices

1. **Warm-up Phase**: Enable warm-up to stabilize performance
   ```bash
   ./benchmark_upload --warmup 10 ...
   ```

2. **Isolated Environment**: Run on dedicated test systems (not production)

3. **Multiple Runs**: Run each test 3-5 times and average results

4. **Monitor Resources**: Watch CPU, memory, disk, network during tests
   ```bash
   # In separate terminal
   watch -n 1 'top -b -n 1 | head -20'
   iostat -x 1
   ```

5. **Document Conditions**: Record system state, configuration, and results

## Troubleshooting

### Build Issues

**Error: `fdfs_client.h: No such file or directory`**
```bash
# Update include paths in Makefile
CFLAGS = -I/path/to/fastdfs/client -I/path/to/fastdfs/common
```

**Error: `cannot find -lfdfsclient`**
```bash
# Set library path
export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH
```

### Runtime Issues

**Connection Refused**
- Check if tracker is running: `ps aux | grep fdfs_trackerd`
- Verify tracker address and port
- Test connectivity: `telnet tracker_ip 22122`
- Check firewall: `sudo iptables -L`

**Out of Memory**
- Reduce threads: `--threads 5`
- Reduce file size: `--size 524288`
- Reduce file count: `--files 100`
- Increase system memory

**Too Many Open Files**
```bash
# Increase file descriptor limit
ulimit -n 65536
```

### Performance Issues

**Low Throughput**
```bash
# Check network bandwidth
iperf3 -c tracker_server

# Check disk I/O
iostat -x 1

# Check CPU
top
```

**High Latency**
```bash
# Check network latency
ping tracker_server

# Check system load
uptime
vmstat 1
```

**Low Success Rate**
```bash
# Check FastDFS logs
tail -f /var/log/fastdfs/trackerd.log
tail -f /var/log/fastdfs/storaged.log

# Check system resources
free -h
df -h
```

### Windows/WSL Issues

**Build on Windows**
```powershell
# Install WSL
wsl --install

# In WSL terminal
cd /mnt/d/dev/bit/74/fastdfs/benchmarks
make
```

**Missing Build Tools in WSL**
```bash
sudo apt-get update
sudo apt-get install -y build-essential gcc make
```

## Advanced Configuration

Customize `config/benchmark.conf` for default settings:

```ini
# Connection settings
tracker_server = 127.0.0.1:22122
connect_timeout = 30
network_timeout = 60

# Upload benchmark defaults
[upload]
threads = 10
file_count = 1000
file_size = 1048576
warmup_enabled = true

# Concurrent benchmark defaults
[concurrent]
concurrent_users = 50
duration = 300
operation_mix = 50:45:5
```

## Architecture

- **6 C Benchmark Programs**: ~1,666 lines of multi-threaded C code
- **3 Python Scripts**: Report generation using only standard library (no pip install)
- **Thread-safe Statistics**: Mutex-protected metrics collection
- **JSON Output**: Machine-readable results for integration
- **No External Dependencies**: Python uses only standard library

## FAQ

**Q: Do I need to install Python packages?**  
A: No! All Python scripts use only the standard library.

**Q: Can I run this on Windows?**  
A: Yes, use WSL (Windows Subsystem for Linux).

**Q: How long do benchmarks take?**  
A: Quick test: ~5 minutes. Full suite: ~30-60 minutes.

**Q: Can I run on production?**  
A: Not recommended. Benchmarks generate load that may impact production.

**Q: What FastDFS version is required?**  
A: Designed for FastDFS 6.x, compatible with 5.x.

## Contributing

To add new benchmarks:
1. Create `benchmark_newtest.c` following existing structure
2. Add to Makefile
3. Output results in JSON format
4. Update this README
5. Test thoroughly

## License

This benchmarking suite follows the same license as FastDFS.

## Support

- **FastDFS GitHub**: https://github.com/happyfish100/fastdfs
- **FastDFS Wiki**: https://github.com/happyfish100/fastdfs/wiki
- **Issues**: https://github.com/happyfish100/fastdfs/issues


================================================
FILE: benchmarks/benchmark_concurrent.c
================================================
/**
 * FastDFS Concurrent Operations Benchmark
 * 
 * Simulates multiple concurrent users performing mixed operations
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
#include <getopt.h>
#include <errno.h>
#include <signal.h>
#include "fdfs_client.h"

#define MAX_USERS 1024
#define MAX_FILENAME_LEN 256
#define MAX_UPLOADED_FILES 10000

typedef enum {
    OP_UPLOAD,
    OP_DOWNLOAD,
    OP_DELETE
} operation_type_t;

typedef struct {
    char group_name[FDFS_GROUP_NAME_MAX_LEN + 1];
    char remote_filename[MAX_FILENAME_LEN];
} uploaded_file_t;

typedef struct {
    int user_id;
    int duration_seconds;
    char *tracker_server;
    int upload_ratio;
    int download_ratio;
    int delete_ratio;
    int think_time_ms;
    int file_size;
    
    // Results
    int upload_count;
    int download_count;
    int delete_count;
    int upload_success;
    int download_success;
    int delete_success;
    double total_bytes_uploaded;
    double total_bytes_downloaded;
} user_context_t;

// Global configuration
static int g_user_count = 10;
static int g_duration = 60;
static char g_tracker_server[256] = "127.0.0.1:22122";
static int g_upload_ratio = 50;
static int g_download_ratio = 45;
static int g_delete_ratio = 5;
static int g_think_time = 100;
static int g_file_size = 1048576;
static int g_verbose = 0;
static volatile int g_running = 1;

// Global file pool
static uploaded_file_t g_uploaded_files[MAX_UPLOADED_FILES];
static int g_uploaded_count = 0;
static pthread_mutex_t g_file_pool_mutex = PTHREAD_MUTEX_INITIALIZER;

// Global statistics
static pthread_mutex_t g_stats_mutex = PTHREAD_MUTEX_INITIALIZER;
static int g_total_uploads = 0;
static int g_total_downloads = 0;
static int g_total_deletes = 0;
static int g_successful_uploads = 0;
static int g_successful_downloads = 0;
static int g_successful_deletes = 0;

/**
 * Get current time in microseconds
 */
static double get_time_us() {
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return tv.tv_sec * 1000000.0 + tv.tv_usec;
}

/**
 * Generate random data
 */
static char* generate_random_data(int size) {
    char *data = (char*)malloc(size);
    if (data == NULL) {
        return NULL;
    }
    
    for (int i = 0; i < size; i++) {
        data[i] = (char)(rand() % 256);
    }
    
    return data;
}

/**
 * Add file to global pool
 */
static void add_to_file_pool(const char *group_name, const char *remote_filename) {
    pthread_mutex_lock(&g_file_pool_mutex);
    
    if (g_uploaded_count < MAX_UPLOADED_FILES) {
        strncpy(g_uploaded_files[g_uploaded_count].group_name, group_name, 
                FDFS_GROUP_NAME_MAX_LEN);
        strncpy(g_uploaded_files[g_uploaded_count].remote_filename, remote_filename, 
                MAX_FILENAME_LEN - 1);
        g_uploaded_count++;
    }
    
    pthread_mutex_unlock(&g_file_pool_mutex);
}

/**
 * Get random file from pool
 */
static int get_random_file(char *group_name, char *remote_filename) {
    pthread_mutex_lock(&g_file_pool_mutex);
    
    if (g_uploaded_count == 0) {
        pthread_mutex_unlock(&g_file_pool_mutex);
        return -1;
    }
    
    int idx = rand() % g_uploaded_count;
    strncpy(group_name, g_uploaded_files[idx].group_name, FDFS_GROUP_NAME_MAX_LEN);
    strncpy(remote_filename, g_uploaded_files[idx].remote_filename, MAX_FILENAME_LEN - 1);
    
    pthread_mutex_unlock(&g_file_pool_mutex);
    return 0;
}

/**
 * Remove file from pool
 */
static void remove_from_file_pool(const char *group_name, const char *remote_filename) {
    pthread_mutex_lock(&g_file_pool_mutex);
    
    for (int i = 0; i < g_uploaded_count; i++) {
        if (strcmp(g_uploaded_files[i].group_name, group_name) == 0 &&
            strcmp(g_uploaded_files[i].remote_filename, remote_filename) == 0) {
            // Move last element to this position
            if (i < g_uploaded_count - 1) {
                g_uploaded_files[i] = g_uploaded_files[g_uploaded_count - 1];
            }
            g_uploaded_count--;
            break;
        }
    }
    
    pthread_mutex_unlock(&g_file_pool_mutex);
}

/**
 * Select operation based on ratios
 */
static operation_type_t select_operation(int upload_ratio, int download_ratio, int delete_ratio) {
    int total = upload_ratio + download_ratio + delete_ratio;
    int r = rand() % total;
    
    if (r < upload_ratio) {
        return OP_UPLOAD;
    } else if (r < upload_ratio + download_ratio) {
        return OP_DOWNLOAD;
    } else {
        return OP_DELETE;
    }
}

/**
 * Perform upload operation
 */
static int perform_upload(user_context_t *ctx, char *file_data) {
    char group_name[FDFS_GROUP_NAME_MAX_LEN + 1];
    char remote_filename[MAX_FILENAME_LEN];
    
    int result = fdfs_upload_by_buffer(file_data, ctx->file_size, NULL,
                                      group_name, remote_filename);
    
    if (result == 0) {
        ctx->upload_success++;
        ctx->total_bytes_uploaded += ctx->file_size;
        add_to_file_pool(group_name, remote_filename);
        return 0;
    }
    
    return -1;
}

/**
 * Perform download operation
 */
static int perform_download(user_context_t *ctx) {
    char group_name[FDFS_GROUP_NAME_MAX_LEN + 1];
    char remote_filename[MAX_FILENAME_LEN];
    char *buffer = NULL;
    int64_t file_size = 0;
    
    if (get_random_file(group_name, remote_filename) != 0) {
        return -1;
    }
    
    int result = fdfs_download_file_to_buffer(group_name, remote_filename,
                                             &buffer, &file_size);
    
    if (result == 0 && buffer != NULL) {
        ctx->download_success++;
        ctx->total_bytes_downloaded += file_size;
        free(buffer);
        return 0;
    }
    
    return -1;
}

/**
 * Perform delete operation
 */
static int perform_delete(user_context_t *ctx) {
    char group_name[FDFS_GROUP_NAME_MAX_LEN + 1];
    char remote_filename[MAX_FILENAME_LEN];
    
    if (get_random_file(group_name, remote_filename) != 0) {
        return -1;
    }
    
    int result = fdfs_delete_file(group_name, remote_filename);
    
    if (result == 0) {
        ctx->delete_success++;
        remove_from_file_pool(group_name, remote_filename);
        return 0;
    }
    
    return -1;
}

/**
 * User simulation thread
 */
static void* user_thread(void *arg) {
    user_context_t *ctx = (user_context_t*)arg;
    char *file_data = NULL;
    
    // Initialize client
    if (fdfs_client_init(ctx->tracker_server) != 0) {
        fprintf(stderr, "User %d: Failed to initialize FDFS client\n", ctx->user_id);
        return NULL;
    }
    
    // Generate file data once
    file_data = generate_random_data(ctx->file_size);
    if (file_data == NULL) {
        fprintf(stderr, "User %d: Failed to generate file data\n", ctx->user_id);
        fdfs_client_destroy();
        return NULL;
    }
    
    // Initialize counters
    ctx->upload_count = 0;
    ctx->download_count = 0;
    ctx->delete_count = 0;
    ctx->upload_success = 0;
    ctx->download_success = 0;
    ctx->delete_success = 0;
    ctx->total_bytes_uploaded = 0;
    ctx->total_bytes_downloaded = 0;
    
    time_t start_time = time(NULL);
    
    // Run until duration expires
    while (g_running && (time(NULL) - start_time) < ctx->duration_seconds) {
        operation_type_t op = select_operation(ctx->upload_ratio, 
                                              ctx->download_ratio, 
                                              ctx->delete_ratio);
        
        switch (op) {
            case OP_UPLOAD:
                ctx->upload_count++;
                perform_upload(ctx, file_data);
                break;
                
            case OP_DOWNLOAD:
                ctx->download_count++;
                perform_download(ctx);
                break;
                
            case OP_DELETE:
                ctx->delete_count++;
                perform_delete(ctx);
                break;
        }
        
        // Think time
        if (ctx->think_time_ms > 0) {
            usleep(ctx->think_time_ms * 1000);
        }
    }
    
    // Cleanup
    free(file_data);
    fdfs_client_destroy();
    
    // Update global statistics
    pthread_mutex_lock(&g_stats_mutex);
    g_total_uploads += ctx->upload_count;
    g_total_downloads += ctx->download_count;
    g_total_deletes += ctx->delete_count;
    g_successful_uploads += ctx->upload_success;
    g_successful_downloads += ctx->download_success;
    g_successful_deletes += ctx->delete_success;
    pthread_mutex_unlock(&g_stats_mutex);
    
    return NULL;
}

/**
 * Signal handler
 */
static void signal_handler(int signum) {
    g_running = 0;
}

/**
 * Print results
 */
static void print_results(double duration) {
    double upload_throughput = (g_successful_uploads > 0) ? 
        g_successful_uploads / duration : 0;
    double download_throughput = (g_successful_downloads > 0) ? 
        g_successful_downloads / duration : 0;
    double total_ops = g_total_uploads + g_total_downloads + g_total_deletes;
    double ops_per_sec = total_ops / duration;
    
    printf("{\n");
    printf("  \"benchmark\": \"concurrent\",\n");
    printf("  \"timestamp\": \"%ld\",\n", time(NULL));
    printf("  \"configuration\": {\n");
    printf("    \"users\": %d,\n", g_user_count);
    printf("    \"duration\": %d,\n", g_duration);
    printf("    \"operation_mix\": \"%d:%d:%d\",\n", 
           g_upload_ratio, g_download_ratio, g_delete_ratio);
    printf("    \"think_time_ms\": %d,\n", g_think_time);
    printf("    \"file_size\": %d\n", g_file_size);
    printf("  },\n");
    printf("  \"metrics\": {\n");
    printf("    \"operations\": {\n");
    printf("      \"total\": %.0f,\n", total_ops);
    printf("      \"per_second\": %.2f,\n", ops_per_sec);
    printf("      \"uploads\": {\n");
    printf("        \"total\": %d,\n", g_total_uploads);
    printf("        \"successful\": %d,\n", g_successful_uploads);
    printf("        \"success_rate\": %.2f,\n", 
               (g_total_uploads > 0) ? (double)g_successful_uploads / g_total_uploads * 100 : 0);
    printf("        \"per_second\": %.2f\n", upload_throughput);
    printf("      },\n");
    printf("      \"downloads\": {\n");
    printf("        \"total\": %d,\n", g_total_downloads);
    printf("        \"successful\": %d,\n", g_successful_downloads);
    printf("        \"success_rate\": %.2f,\n", 
               (g_total_downloads > 0) ? (double)g_successful_downloads / g_total_downloads * 100 : 0);
    printf("        \"per_second\": %.2f\n", download_throughput);
    printf("      },\n");
    printf("      \"deletes\": {\n");
    printf("        \"total\": %d,\n", g_total_deletes);
    printf("        \"successful\": %d,\n", g_successful_deletes);
    printf("        \"success_rate\": %.2f\n", 
               (g_total_deletes > 0) ? (double)g_successful_deletes / g_total_deletes * 100 : 0);
    printf("      }\n");
    printf("    },\n");
    printf("    \"duration_seconds\": %.2f,\n", duration);
    printf("    \"files_in_pool\": %d\n", g_uploaded_count);
    printf("  }\n");
    printf("}\n");
}

/**
 * Print usage
 */
static void print_usage(const char *program) {
    printf("Usage: %s [OPTIONS]\n", program);
    printf("\nOptions:\n");
    printf("  -u, --users NUM        Number of concurrent users (default: 10)\n");
    printf("  -d, --duration SEC     Test duration in seconds (default: 60)\n");
    printf("  -m, --mix RATIO        Operation mix upload:download:delete (default: 50:45:5)\n");
    printf("  -t, --think-time MS    Think time between operations (default: 100)\n");
    printf("  -s, --size BYTES       File size in bytes (default: 1048576)\n");
    printf("  -T, --tracker SERVER   Tracker server (default: 127.0.0.1:22122)\n");
    printf("  -v, --verbose          Enable verbose output\n");
    printf("  -h, --help             Show this help message\n");
}

/**
 * Main function
 */
int main(int argc, char *argv[]) {
    pthread_t threads[MAX_USERS];
    user_context_t contexts[MAX_USERS];
    
    // Parse command line arguments
    static struct option long_options[] = {
        {"users", required_argument, 0, 'u'},
        {"duration", required_argument, 0, 'd'},
        {"mix", required_argument, 0, 'm'},
        {"think-time", required_argument, 0, 't'},
        {"size", required_argument, 0, 's'},
        {"tracker", required_argument, 0, 'T'},
        {"verbose", no_argument, 0, 'v'},
        {"help", no_argument, 0, 'h'},
        {0, 0, 0, 0}
    };
    
    int opt;
    while ((opt = getopt_long(argc, argv, "u:d:m:t:s:T:vh", long_options, NULL)) != -1) {
        switch (opt) {
            case 'u':
                g_user_count = atoi(optarg);
                break;
            case 'd':
                g_duration = atoi(optarg);
                break;
            case 'm':
                sscanf(optarg, "%d:%d:%d", &g_upload_ratio, &g_download_ratio, &g_delete_ratio);
                break;
            case 't':
                g_think_time = atoi(optarg);
                break;
            case 's':
                g_file_size = atoi(optarg);
                break;
            case 'T':
                strncpy(g_tracker_server, optarg, sizeof(g_tracker_server) - 1);
                break;
            case 'v':
                g_verbose = 1;
                break;
            case 'h':
                print_usage(argv[0]);
                return 0;
            default:
                print_usage(argv[0]);
                return 1;
        }
    }
    
    // Setup signal handler
    signal(SIGINT, signal_handler);
    signal(SIGTERM, signal_handler);
    
    printf("FastDFS Concurrent Operations Benchmark\n");
    printf("========================================\n");
    printf("Concurrent users: %d\n", g_user_count);
    printf("Duration: %d seconds\n", g_duration);
    printf("Operation mix: %d:%d:%d (upload:download:delete)\n", 
           g_upload_ratio, g_download_ratio, g_delete_ratio);
    printf("Think time: %d ms\n", g_think_time);
    printf("File size: %d bytes\n", g_file_size);
    printf("Tracker: %s\n\n", g_tracker_server);
    
    srand(time(NULL));
    
    // Initialize contexts
    for (int i = 0; i < g_user_count; i++) {
        contexts[i].user_id = i;
        contexts[i].duration_seconds = g_duration;
        contexts[i].tracker_server = g_tracker_server;
        contexts[i].upload_ratio = g_upload_ratio;
        contexts[i].download_ratio = g_download_ratio;
        contexts[i].delete_ratio = g_delete_ratio;
        contexts[i].think_time_ms = g_think_time;
        contexts[i].file_size = g_file_size;
    }
    
    // Start benchmark
    printf("Starting benchmark...\n");
    double start_time = get_time_us();
    
    // Create threads
    for (int i = 0; i < g_user_count; i++) {
        if (pthread_create(&threads[i], NULL, user_thread, &contexts[i]) != 0) {
            fprintf(stderr, "Error: Failed to create thread %d\n", i);
            return 1;
        }
    }
    
    // Wait for threads
    for (int i = 0; i < g_user_count; i++) {
        pthread_join(threads[i], NULL);
    }
    
    double end_time = get_time_us();
    double total_time = (end_time - start_time) / 1000000.0;
    
    // Print results
    printf("\nBenchmark complete!\n\n");
    print_results(total_time);
    
    return 0;
}


================================================
FILE: benchmarks/benchmark_download.c
================================================
/**
 * FastDFS Download Performance Benchmark
 * 
 * Measures download throughput, IOPS, and latency percentiles
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
#include <getopt.h>
#include <errno.h>
#include "fdfs_client.h"
#include "logger.h"

#define MAX_THREADS 1024
#define MAX_FILES 100000
#define MAX_FILENAME_LEN 256

typedef struct {
    char group_name[FDFS_GROUP_NAME_MAX_LEN + 1];
    char remote_filename[MAX_FILENAME_LEN];
    int file_size;
} file_info_t;

typedef struct {
    int thread_id;
    int iterations;
    char *tracker_server;
    file_info_t *files;
    int file_count;
    
    // Results
    int successful_downloads;
    int failed_downloads;
    double *latencies;
    int latency_count;
    double total_bytes;
    double total_time;
} thread_context_t;

typedef struct {
    double mean;
    double median;
    double p50;
    double p75;
    double p90;
    double p95;
    double p99;
    double p999;
    double min;
    double max;
    double stddev;
} latency_stats_t;

// Global configuration
static int g_thread_count = 1;
static int g_iterations = 100;
static char g_tracker_server[256] = "127.0.0.1:22122";
static char g_file_list[256] = "";
static int g_warmup_enabled = 1;
static int g_warmup_duration = 10;
static int g_verbose = 0;
static int g_prepare_files = 1;
static int g_prepare_count = 100;
static int g_prepare_size = 1048576;

// Global file list
static file_info_t *g_files = NULL;
static int g_file_count = 0;

// Global statistics
static pthread_mutex_t g_stats_mutex = PTHREAD_MUTEX_INITIALIZER;
static int g_total_downloads = 0;
static int g_successful_downloads = 0;
static int g_failed_downloads = 0;
static double g_total_bytes = 0;
static double *g_all_latencies = NULL;
static int g_latency_count = 0;

/**
 * Get current time in microseconds
 */
static double get_time_us() {
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return tv.tv_sec * 1000000.0 + tv.tv_usec;
}

/**
 * Generate random data
 */
static char* generate_random_data(int size) {
    char *data = (char*)malloc(size);
    if (data == NULL) {
        return NULL;
    }
    
    for (int i = 0; i < size; i++) {
        data[i] = (char)(rand() % 256);
    }
    
    return data;
}

/**
 * Prepare test files by uploading them
 */
static int prepare_test_files() {
    printf("Preparing %d test files...\n", g_prepare_count);
    
    if (fdfs_client_init(g_tracker_server) != 0) {
        fprintf(stderr, "Failed to initialize FDFS client\n");
        return -1;
    }
    
    g_files = (file_info_t*)malloc(g_prepare_count * sizeof(file_info_t));
    if (g_files == NULL) {
        fprintf(stderr, "Failed to allocate file info array\n");
        fdfs_client_destroy();
        return -1;
    }
    
    char *file_data = generate_random_data(g_prepare_size);
    if (file_data == NULL) {
        fprintf(stderr, "Failed to generate file data\n");
        free(g_files);
        fdfs_client_destroy();
        return -1;
    }
    
    g_file_count = 0;
    for (int i = 0; i < g_prepare_count; i++) {
        int result = fdfs_upload_by_buffer(file_data, g_prepare_size, NULL,
                                          g_files[g_file_count].group_name,
                                          g_files[g_file_count].remote_filename);
        
        if (result == 0) {
            g_files[g_file_count].file_size = g_prepare_size;
            g_file_count++;
            
            if ((i + 1) % 10 == 0) {
                printf("  Uploaded %d/%d files\r", i + 1, g_prepare_count);
                fflush(stdout);
            }
        } else {
            fprintf(stderr, "\nFailed to upload file %d: %s\n", i, strerror(errno));
        }
    }
    
    printf("\nPrepared %d test files successfully.\n\n", g_file_count);
    
    free(file_data);
    fdfs_client_destroy();
    
    return g_file_count > 0 ? 0 : -1;
}

/**
 * Load file list from file
 */
static int load_file_list(const char *filename) {
    FILE *fp = fopen(filename, "r");
    if (fp == NULL) {
        fprintf(stderr, "Failed to open file list: %s\n", filename);
        return -1;
    }
    
    // Count lines
    int count = 0;
    char line[512];
    while (fgets(line, sizeof(line), fp) != NULL) {
        count++;
    }
    
    if (count == 0) {
        fprintf(stderr, "File list is empty\n");
        fclose(fp);
        return -1;
    }
    
    // Allocate array
    g_files = (file_info_t*)malloc(count * sizeof(file_info_t));
    if (g_files == NULL) {
        fprintf(stderr, "Failed to allocate file info array\n");
        fclose(fp);
        return -1;
    }
    
    // Read file info
    rewind(fp);
    g_file_count = 0;
    while (fgets(line, sizeof(line), fp) != NULL && g_file_count < count) {
        // Parse: group_name/remote_filename size
        char *token = strtok(line, " \t\n");
        if (token == NULL) continue;
        
        // Split group and filename
        char *slash = strchr(token, '/');
        if (slash == NULL) continue;
        
        int group_len = slash - token;
        strncpy(g_files[g_file_count].group_name, token, group_len);
        g_files[g_file_count].group_name[group_len] = '\0';
        
        strcpy(g_files[g_file_count].remote_filename, slash + 1);
        
        // Get file size
        token = strtok(NULL, " \t\n");
        g_files[g_file_count].file_size = token ? atoi(token) : 0;
        
        g_file_count++;
    }
    
    fclose(fp);
    printf("Loaded %d files from %s\n\n", g_file_count, filename);
    
    return 0;
}

/**
 * Compare function for qsort
 */
static int compare_double(const void *a, const void *b) {
    double diff = *(double*)a - *(double*)b;
    return (diff > 0) ? 1 : (diff < 0) ? -1 : 0;
}

/**
 * Calculate latency statistics
 */
static void calculate_latency_stats(double *latencies, int count, latency_stats_t *stats) {
    if (count == 0) {
        memset(stats, 0, sizeof(latency_stats_t));
        return;
    }
    
    qsort(latencies, count, sizeof(double), compare_double);
    
    stats->min = latencies[0];
    stats->max = latencies[count - 1];
    stats->p50 = stats->median = latencies[(int)(count * 0.50)];
    stats->p75 = latencies[(int)(count * 0.75)];
    stats->p90 = latencies[(int)(count * 0.90)];
    stats->p95 = latencies[(int)(count * 0.95)];
    stats->p99 = latencies[(int)(count * 0.99)];
    stats->p999 = latencies[(int)(count * 0.999)];
    
    double sum = 0;
    for (int i = 0; i < count; i++) {
        sum += latencies[i];
    }
    stats->mean = sum / count;
    
    double variance = 0;
    for (int i = 0; i < count; i++) {
        double diff = latencies[i] - stats->mean;
        variance += diff * diff;
    }
    stats->stddev = sqrt(variance / count);
}

/**
 * Download thread function
 */
static void* download_thread(void *arg) {
    thread_context_t *ctx = (thread_context_t*)arg;
    char *buffer = NULL;
    int64_t file_size = 0;
    int result;
    
    // Initialize client
    if (fdfs_client_init(ctx->tracker_server) != 0) {
        fprintf(stderr, "Thread %d: Failed to initialize FDFS client\n", ctx->thread_id);
        return NULL;
    }
    
    // Allocate latency array
    ctx->latencies = (double*)malloc(ctx->iterations * sizeof(double));
    if (ctx->latencies == NULL) {
        fprintf(stderr, "Thread %d: Failed to allocate latency array\n", ctx->thread_id);
        fdfs_client_destroy();
        return NULL;
    }
    
    ctx->latency_count = 0;
    ctx->successful_downloads = 0;
    ctx->failed_downloads = 0;
    ctx->total_bytes = 0;
    
    double thread_start = get_time_us();
    
    // Download files
    for (int i = 0; i < ctx->iterations; i++) {
        // Select random file
        int file_idx = rand() % ctx->file_count;
        file_info_t *file = &ctx->files[file_idx];
        
        double start_time = get_time_us();
        
        // Download file
        result = fdfs_download_file_to_buffer(file->group_name, file->remote_filename,
                                             &buffer, &file_size);
        
        double end_time = get_time_us();
        double latency_ms = (end_time - start_time) / 1000.0;
        
        if (result == 0 && buffer != NULL) {
            ctx->successful_downloads++;
            ctx->total_bytes += file_size;
            ctx->latencies[ctx->latency_count++] = latency_ms;
            
            free(buffer);
            buffer = NULL;
            
            if (g_verbose && (i % 100 == 0)) {
                printf("Thread %d: Downloaded %d/%d files (%.2f ms)\n", 
                       ctx->thread_id, i + 1, ctx->iterations, latency_ms);
            }
        } else {
            ctx->failed_downloads++;
            if (g_verbose) {
                fprintf(stderr, "Thread %d: Download failed: %s\n", 
                        ctx->thread_id, strerror(errno));
            }
        }
    }
    
    double thread_end = get_time_us();
    ctx->total_time = (thread_end - thread_start) / 1000000.0;
    
    // Cleanup
    fdfs_client_destroy();
    
    // Update global statistics
    pthread_mutex_lock(&g_stats_mutex);
    g_successful_downloads += ctx->successful_downloads;
    g_failed_downloads += ctx->failed_downloads;
    g_total_bytes += ctx->total_bytes;
    pthread_mutex_unlock(&g_stats_mutex);
    
    return NULL;
}

/**
 * Print results in JSON format
 */
static void print_results(double total_time, latency_stats_t *stats) {
    double throughput_mbps = (g_total_bytes / (1024 * 1024)) / total_time;
    double iops = g_successful_downloads / total_time;
    double success_rate = (double)g_successful_downloads / g_total_downloads * 100.0;
    
    printf("{\n");
    printf("  \"benchmark\": \"download\",\n");
    printf("  \"timestamp\": \"%ld\",\n", time(NULL));
    printf("  \"configuration\": {\n");
    printf("    \"threads\": %d,\n", g_thread_count);
    printf("    \"iterations\": %d,\n", g_iterations);
    printf("    \"file_count\": %d,\n", g_file_count);
    printf("    \"tracker_server\": \"%s\"\n", g_tracker_server);
    printf("  },\n");
    printf("  \"metrics\": {\n");
    printf("    \"throughput_mbps\": %.2f,\n", throughput_mbps);
    printf("    \"iops\": %.2f,\n", iops);
    printf("    \"latency_ms\": {\n");
    printf("      \"mean\": %.2f,\n", stats->mean);
    printf("      \"median\": %.2f,\n", stats->median);
    printf("      \"p50\": %.2f,\n", stats->p50);
    printf("      \"p75\": %.2f,\n", stats->p75);
    printf("      \"p90\": %.2f,\n", stats->p90);
    printf("      \"p95\": %.2f,\n", stats->p95);
    printf("      \"p99\": %.2f,\n", stats->p99);
    printf("      \"p999\": %.2f,\n", stats->p999);
    printf("      \"min\": %.2f,\n", stats->min);
    printf("      \"max\": %.2f,\n", stats->max);
    printf("      \"stddev\": %.2f\n", stats->stddev);
    printf("    },\n");
    printf("    \"operations\": {\n");
    printf("      \"total\": %d,\n", g_total_downloads);
    printf("      \"successful\": %d,\n", g_successful_downloads);
    printf("      \"failed\": %d,\n", g_failed_downloads);
    printf("      \"success_rate\": %.2f\n", success_rate);
    printf("    },\n");
    printf("    \"duration_seconds\": %.2f,\n", total_time);
    printf("    \"total_mb\": %.2f\n", g_total_bytes / (1024 * 1024));
    printf("  }\n");
    printf("}\n");
}

/**
 * Print usage information
 */
static void print_usage(const char *program) {
    printf("Usage: %s [OPTIONS]\n", program);
    printf("\nOptions:\n");
    printf("  -t, --threads NUM      Number of concurrent threads (default: 1)\n");
    printf("  -i, --iterations NUM   Number of download iterations (default: 100)\n");
    printf("  -T, --tracker SERVER   Tracker server (default: 127.0.0.1:22122)\n");
    printf("  -f, --file-list FILE   File containing list of files to download\n");
    printf("  -p, --prepare NUM      Prepare NUM test files (default: 100)\n");
    printf("  -s, --size BYTES       Size of prepared files (default: 1048576)\n");
    printf("  -w, --warmup SECONDS   Warmup duration (default: 10, 0 to disable)\n");
    printf("  -v, --verbose          Enable verbose output\n");
    printf("  -h, --help             Show this help message\n");
}

/**
 * Main function
 */
int main(int argc, char *argv[]) {
    pthread_t threads[MAX_THREADS];
    thread_context_t contexts[MAX_THREADS];
    
    // Parse command line arguments
    static struct option long_options[] = {
        {"threads", required_argument, 0, 't'},
        {"iterations", required_argument, 0, 'i'},
        {"tracker", required_argument, 0, 'T'},
        {"file-list", required_argument, 0, 'f'},
        {"prepare", required_argument, 0, 'p'},
        {"size", required_argument, 0, 's'},
        {"warmup", required_argument, 0, 'w'},
        {"verbose", no_argument, 0, 'v'},
        {"help", no_argument, 0, 'h'},
        {0, 0, 0, 0}
    };
    
    int opt;
    while ((opt = getopt_long(argc, argv, "t:i:T:f:p:s:w:vh", long_options, NULL)) != -1) {
        switch (opt) {
            case 't':
                g_thread_count = atoi(optarg);
                break;
            case 'i':
                g_iterations = atoi(optarg);
                break;
            case 'T':
                strncpy(g_tracker_server, optarg, sizeof(g_tracker_server) - 1);
                break;
            case 'f':
                strncpy(g_file_list, optarg, sizeof(g_file_list) - 1);
                g_prepare_files = 0;
                break;
            case 'p':
                g_prepare_count = atoi(optarg);
                break;
            case 's':
                g_prepare_size = atoi(optarg);
                break;
            case 'w':
                g_warmup_duration = atoi(optarg);
                break;
            case 'v':
                g_verbose = 1;
                break;
            case 'h':
                print_usage(argv[0]);
                return 0;
            default:
                print_usage(argv[0]);
                return 1;
        }
    }
    
    printf("FastDFS Download Performance Benchmark\n");
    printf("=======================================\n");
    printf("Threads: %d\n", g_thread_count);
    printf("Iterations per thread: %d\n", g_iterations / g_thread_count);
    printf("Total downloads: %d\n", g_iterations);
    printf("Tracker: %s\n\n", g_tracker_server);
    
    srand(time(NULL));
    
    // Prepare or load files
    if (g_prepare_files) {
        if (prepare_test_files() != 0) {
            return 1;
        }
    } else {
        if (load_file_list(g_file_list) != 0) {
            return 1;
        }
    }
    
    if (g_file_count == 0) {
        fprintf(stderr, "Error: No files available for download\n");
        return 1;
    }
    
    // Allocate global latency array
    g_all_latencies = (double*)malloc(g_iterations * sizeof(double));
    if (g_all_latencies == NULL) {
        fprintf(stderr, "Error: Failed to allocate latency array\n");
        free(g_files);
        return 1;
    }
    
    // Initialize thread contexts
    int iterations_per_thread = g_iterations / g_thread_count;
    int remaining_iterations = g_iterations % g_thread_count;
    
    for (int i = 0; i < g_thread_count; i++) {
        contexts[i].thread_id = i;
        contexts[i].iterations = iterations_per_thread + (i < remaining_iterations ? 1 : 0);
        contexts[i].tracker_server = g_tracker_server;
        contexts[i].files = g_files;
        contexts[i].file_count = g_file_count;
    }
    
    // Start benchmark
    printf("Starting benchmark...\n");
    double start_time = get_time_us();
    
    // Create threads
    for (int i = 0; i < g_thread_count; i++) {
        if (pthread_create(&threads[i], NULL, download_thread, &contexts[i]) != 0) {
            fprintf(stderr, "Error: Failed to create thread %d\n", i);
            free(g_files);
            free(g_all_latencies);
            return 1;
        }
    }
    
    // Wait for threads
    for (int i = 0; i < g_thread_count; i++) {
        pthread_join(threads[i], NULL);
    }
    
    double end_time = get_time_us();
    double total_time = (end_time - start_time) / 1000000.0;
    
    // Collect latencies
    g_latency_count = 0;
    for (int i = 0; i < g_thread_count; i++) {
        for (int j = 0; j < contexts[i].latency_count; j++) {
            g_all_latencies[g_latency_count++] = contexts[i].latencies[j];
        }
        free(contexts[i].latencies);
    }
    
    // Calculate statistics
    latency_stats_t stats;
    calculate_latency_stats(g_all_latencies, g_latency_count, &stats);
    
    // Print results
    printf("\nBenchmark complete!\n\n");
    print_results(total_time, &stats);
    
    // Cleanup
    free(g_files);
    free(g_all_latencies);
    
    return 0;
}


================================================
FILE: benchmarks/benchmark_large_files.c
================================================
/**
 * FastDFS Large Files Performance Benchmark
 * 
 * Tests performance with large files (>100MB)
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
#include <getopt.h>
#include "fdfs_client.h"

#define MAX_THREADS 64
#define MIN_FILE_SIZE 104857600  // 100MB
#define MAX_FILE_SIZE 1073741824 // 1GB

typedef struct {
    int thread_id;
    int file_count;
    int min_size;
    int max_size;
    char *tracker_server;
    
    // Results
    int successful;
    int failed;
    double total_bytes;
    double total_time;
    double *latencies;
    int latency_count;
} thread_context_t;

// Global configuration
static int g_thread_count = 5;
static int g_file_count = 100;
static int g_min_size = MIN_FILE_SIZE;
static int g_max_size = MAX_FILE_SIZE;
static char g_tracker_server[256] = "127.0.0.1:22122";
static int g_verbose = 1;

// Global statistics
static pthread_mutex_t g_stats_mutex = PTHREAD_MUTEX_INITIALIZER;
static int g_total_successful = 0;
static int g_total_failed = 0;
static double g_total_bytes = 0;

/**
 * Get current time in microseconds
 */
static double get_time_us() {
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return tv.tv_sec * 1000000.0 + tv.tv_usec;
}

/**
 * Generate random data in chunks to avoid memory issues
 */
static char* generate_large_file_data(int size) {
    char *data = (char*)malloc(size);
    if (data == NULL) return NULL;
    
    // Fill in chunks to avoid stack overflow
    int chunk_size = 1024 * 1024; // 1MB chunks
    for (int offset = 0; offset < size; offset += chunk_size) {
        int current_chunk = (offset + chunk_size > size) ? (size - offset) : chunk_size;
        for (int i = 0; i < current_chunk; i++) {
            data[offset + i] = (char)(rand() % 256);
        }
    }
    
    return data;
}

/**
 * Compare function for qsort
 */
static int compare_double(const void *a, const void *b) {
    double diff = *(double*)a - *(double*)b;
    return (diff > 0) ? 1 : (diff < 0) ? -1 : 0;
}

/**
 * Upload thread
 */
static void* upload_thread(void *arg) {
    thread_context_t *ctx = (thread_context_t*)arg;
    char group_name[FDFS_GROUP_NAME_MAX_LEN + 1];
    char remote_filename[256];
    
    if (fdfs_client_init(ctx->tracker_server) != 0) {
        fprintf(stderr, "Thread %d: Failed to initialize client\n", ctx->thread_id);
        return NULL;
    }
    
    ctx->latencies = (double*)malloc(ctx->file_count * sizeof(double));
    if (ctx->latencies == NULL) {
        fdfs_client_destroy();
        return NULL;
    }
    
    ctx->successful = 0;
    ctx->failed = 0;
    ctx->total_bytes = 0;
    ctx->latency_count = 0;
    
    double thread_start = get_time_us();
    
    for (int i = 0; i < ctx->file_count; i++) {
        // Random file size
        int file_size = ctx->min_size + (rand() % (ctx->max_size - ctx->min_size + 1));
        
        printf("Thread %d: Generating file %d/%d (%.2f MB)...\n", 
               ctx->thread_id, i + 1, ctx->file_count, file_size / (1024.0 * 1024.0));
        
        char *data = generate_large_file_data(file_size);
        if (data == NULL) {
            fprintf(stderr, "Thread %d: Failed to allocate %d bytes\n", 
                    ctx->thread_id, file_size);
            ctx->failed++;
            continue;
        }
        
        printf("Thread %d: Uploading file %d/%d...\n", 
               ctx->thread_id, i + 1, ctx->file_count);
        
        double start = get_time_us();
        int result = fdfs_upload_by_buffer(data, file_size, NULL, 
                                          group_name, remote_filename);
        double end = get_time_us();
        double latency_sec = (end - start) / 1000000.0;
        
        if (result == 0) {
            ctx->successful++;
            ctx->total_bytes += file_size;
            ctx->latencies[ctx->latency_count++] = latency_sec;
            
            double throughput = (file_size / (1024.0 * 1024.0)) / latency_sec;
            printf("Thread %d: File %d uploaded successfully (%.2f MB/s)\n", 
                   ctx->thread_id, i + 1, throughput);
        } else {
            ctx->failed++;
            fprintf(stderr, "Thread %d: Upload failed for file %d\n", 
                    ctx->thread_id, i + 1);
        }
        
        free(data);
    }
    
    double thread_end = get_time_us();
    ctx->total_time = (thread_end - thread_start) / 1000000.0;
    
    fdfs_client_destroy();
    
    pthread_mutex_lock(&g_stats_mutex);
    g_total_successful += ctx->successful;
    g_total_failed += ctx->failed;
    g_total_bytes += ctx->total_bytes;
    pthread_mutex_unlock(&g_stats_mutex);
    
    return NULL;
}

/**
 * Print results
 */
static void print_results(double total_time, double *all_latencies, int latency_count) {
    if (latency_count > 0) {
        qsort(all_latencies, latency_count, sizeof(double), compare_double);
    }
    
    double mean = 0;
    for (int i = 0; i < latency_count; i++) {
        mean += all_latencies[i];
    }
    if (latency_count > 0) mean /= latency_count;
    
    double throughput_mbps = (g_total_bytes / (1024 * 1024)) / total_time;
    double avg_file_size_mb = (g_total_bytes / g_total_successful) / (1024 * 1024);
    
    printf("{\n");
    printf("  \"benchmark\": \"large_files\",\n");
    printf("  \"timestamp\": \"%ld\",\n", time(NULL));
    printf("  \"configuration\": {\n");
    printf("    \"threads\": %d,\n", g_thread_count);
    printf("    \"file_count\": %d,\n", g_file_count);
    printf("    \"min_size_mb\": %.2f,\n", g_min_size / (1024.0 * 1024.0));
    printf("    \"max_size_mb\": %.2f\n", g_max_size / (1024.0 * 1024.0));
    printf("  },\n");
    printf("  \"metrics\": {\n");
    printf("    \"throughput_mbps\": %.2f,\n", throughput_mbps);
    printf("    \"latency_seconds\": {\n");
    printf("      \"mean\": %.2f,\n", mean);
    if (latency_count > 0) {
        printf("      \"p50\": %.2f,\n", all_latencies[(int)(latency_count * 0.50)]);
        printf("      \"p95\": %.2f,\n", all_latencies[(int)(latency_count * 0.95)]);
        printf("      \"p99\": %.2f,\n", all_latencies[(int)(latency_count * 0.99)]);
        printf("      \"min\": %.2f,\n", all_latencies[0]);
        printf("      \"max\": %.2f\n", all_latencies[latency_count - 1]);
    } else {
        printf("      \"p50\": 0,\n");
        printf("      \"p95\": 0,\n");
        printf("      \"p99\": 0,\n");
        printf("      \"min\": 0,\n");
        printf("      \"max\": 0\n");
    }
    printf("    },\n");
    printf("    \"operations\": {\n");
    printf("      \"successful\": %d,\n", g_total_successful);
    printf("      \"failed\": %d,\n", g_total_failed);
    printf("      \"success_rate\": %.2f\n", 
           (g_total_successful + g_total_failed > 0) ? 
           (double)g_total_successful / (g_total_successful + g_total_failed) * 100 : 0);
    printf("    },\n");
    printf("    \"duration_seconds\": %.2f,\n", total_time);
    printf("    \"total_gb\": %.2f,\n", g_total_bytes / (1024 * 1024 * 1024));
    printf("    \"avg_file_size_mb\": %.2f\n", avg_file_size_mb);
    printf("  }\n");
    printf("}\n");
}

/**
 * Print usage
 */
static void print_usage(const char *program) {
    printf("Usage: %s [OPTIONS]\n", program);
    printf("\nOptions:\n");
    printf("  -t, --threads NUM      Number of threads (default: 5)\n");
    printf("  -c, --count NUM        Number of files (default: 100)\n");
    printf("  -m, --min-size BYTES   Minimum file size (default: 104857600)\n");
    printf("  -M, --max-size BYTES   Maximum file size (default: 1073741824)\n");
    printf("  -T, --tracker SERVER   Tracker server (default: 127.0.0.1:22122)\n");
    printf("  -v, --verbose          Verbose output\n");
    printf("  -h, --help             Show help\n");
}

/**
 * Main function
 */
int main(int argc, char *argv[]) {
    pthread_t threads[MAX_THREADS];
    thread_context_t contexts[MAX_THREADS];
    
    static struct option long_options[] = {
        {"threads", required_argument, 0, 't'},
        {"count", required_argument, 0, 'c'},
        {"min-size", required_argument, 0, 'm'},
        {"max-size", required_argument, 0, 'M'},
        {"tracker", required_argument, 0, 'T'},
        {"verbose", no_argument, 0, 'v'},
        {"help", no_argument, 0, 'h'},
        {0, 0, 0, 0}
    };
    
    int opt;
    while ((opt = getopt_long(argc, argv, "t:c:m:M:T:vh", long_options, NULL)) != -1) {
        switch (opt) {
            case 't': g_thread_count = atoi(optarg); break;
            case 'c': g_file_count = atoi(optarg); break;
            case 'm': g_min_size = atoi(optarg); break;
            case 'M': g_max_size = atoi(optarg); break;
            case 'T': strncpy(g_tracker_server, optarg, sizeof(g_tracker_server) - 1); break;
            case 'v': g_verbose = 1; break;
            case 'h': print_usage(argv[0]); return 0;
            default: print_usage(argv[0]); return 1;
        }
    }
    
    printf("FastDFS Large Files Benchmark\n");
    printf("==============================\n");
    printf("Threads: %d\n", g_thread_count);
    printf("Files: %d\n", g_file_count);
    printf("Size range: %.2f - %.2f MB\n", 
           g_min_size / (1024.0 * 1024.0), g_max_size / (1024.0 * 1024.0));
    printf("Tracker: %s\n\n", g_tracker_server);
    
    srand(time(NULL));
    
    int files_per_thread = g_file_count / g_thread_count;
    int remaining = g_file_count % g_thread_count;
    
    for (int i = 0; i < g_thread_count; i++) {
        contexts[i].thread_id = i;
        contexts[i].file_count = files_per_thread + (i < remaining ? 1 : 0);
        contexts[i].min_size = g_min_size;
        contexts[i].max_size = g_max_size;
        contexts[i].tracker_server = g_tracker_server;
    }
    
    printf("Starting benchmark...\n");
    double start_time = get_time_us();
    
    for (int i = 0; i < g_thread_count; i++) {
        pthread_create(&threads[i], NULL, upload_thread, &contexts[i]);
    }
    
    for (int i = 0; i < g_thread_count; i++) {
        pthread_join(threads[i], NULL);
    }
    
    double end_time = get_time_us();
    double total_time = (end_time - start_time) / 1000000.0;
    
    // Collect all latencies
    double *all_latencies = (double*)malloc(g_file_count * sizeof(double));
    int latency_count = 0;
    
    for (int i = 0; i < g_thread_count; i++) {
        for (int j = 0; j < contexts[i].latency_count; j++) {
            all_latencies[latency_count++] = contexts[i].latencies[j];
        }
        free(contexts[i].latencies);
    }
    
    printf("\nBenchmark complete!\n\n");
    print_results(total_time, all_latencies, latency_count);
    
    free(all_latencies);
    return 0;
}


================================================
FILE: benchmarks/benchmark_metadata.c
================================================
/**
 * FastDFS Metadata Operations Benchmark
 * 
 * Tests performance of metadata query, update, and delete operations
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
#include <getopt.h>
#include "fdfs_client.h"

#define MAX_THREADS 1024
#define MAX_FILES 10000
#define MAX_METADATA_COUNT 10

typedef struct {
    char group_name[FDFS_GROUP_NAME_MAX_LEN + 1];
    char remote_filename[256];
} file_info_t;

typedef struct {
    int thread_id;
    int operation_count;
    char *tracker_server;
    file_info_t *files;
    int file_count;
    int query_ratio;
    int update_ratio;
    int delete_ratio;
    
    // Results
    int query_count;
    int update_count;
    int delete_count;
    int query_success;
    int update_success;
    int delete_success;
    double *query_latencies;
    double *update_latencies;
    double *delete_latencies;
    int query_latency_count;
    int update_latency_count;
    int delete_latency_count;
} thread_context_t;

// Global configuration
static int g_thread_count = 10;
static int g_operation_count = 10000;
static char g_tracker_server[256] = "127.0.0.1:22122";
static int g_query_ratio = 70;
static int g_update_ratio = 20;
static int g_delete_ratio = 10;
static int g_prepare_files = 100;
static int g_verbose = 0;

// Global file list
static file_info_t *g_files = NULL;
static int g_file_count = 0;

// Global statistics
static pthread_mutex_t g_stats_mutex = PTHREAD_MUTEX_INITIALIZER;
static int g_total_queries = 0;
static int g_total_updates = 0;
static int g_total_deletes = 0;
static int g_successful_queries = 0;
static int g_successful_updates = 0;
static int g_successful_deletes = 0;

/**
 * Get current time in microseconds
 */
static double get_time_us() {
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return tv.tv_sec * 1000000.0 + tv.tv_usec;
}

/**
 * Generate random data
 */
static char* generate_random_data(int size) {
    char *data = (char*)malloc(size);
    if (data == NULL) return NULL;
    
    for (int i = 0; i < size; i++) {
        data[i] = (char)(rand() % 256);
    }
    return data;
}

/**
 * Prepare test files
 */
static int prepare_test_files() {
    printf("Preparing %d test files with metadata...\n", g_prepare_files);
    
    if (fdfs_client_init(g_tracker_server) != 0) {
        fprintf(stderr, "Failed to initialize FDFS client\n");
        return -1;
    }
    
    g_files = (file_info_t*)malloc(g_prepare_files * sizeof(file_info_t));
    if (g_files == NULL) {
        fdfs_client_destroy();
        return -1;
    }
    
    char *file_data = generate_random_data(1024);
    if (file_data == NULL) {
        free(g_files);
        fdfs_client_destroy();
        return -1;
    }
    
    g_file_count = 0;
    for (int i = 0; i < g_prepare_files; i++) {
        int result = fdfs_upload_by_buffer(file_data, 1024, NULL,
                                          g_files[g_file_count].group_name,
                                          g_files[g_file_count].remote_filename);
        
        if (result == 0) {
            // Set initial metadata
            FDFSMetaData meta_list[3];
            snprintf(meta_list[0].name, sizeof(meta_list[0].name), "author");
            snprintf(meta_list[0].value, sizeof(meta_list[0].value), "benchmark");
            snprintf(meta_list[1].name, sizeof(meta_list[1].name), "version");
            snprintf(meta_list[1].value, sizeof(meta_list[1].value), "1.0");
            snprintf(meta_list[2].name, sizeof(meta_list[2].name), "timestamp");
            snprintf(meta_list[2].value, sizeof(meta_list[2].value), "%ld", time(NULL));
            
            fdfs_set_metadata(g_files[g_file_count].group_name,
                            g_files[g_file_count].remote_filename,
                            meta_list, 3, FDFS_METADATA_OVERWRITE);
            
            g_file_count++;
            
            if ((i + 1) % 10 == 0) {
                printf("  Prepared %d/%d files\r", i + 1, g_prepare_files);
                fflush(stdout);
            }
        }
    }
    
    printf("\nPrepared %d test files successfully.\n\n", g_file_count);
    
    free(file_data);
    fdfs_client_destroy();
    
    return g_file_count > 0 ? 0 : -1;
}

/**
 * Compare function for qsort
 */
static int compare_double(const void *a, const void *b) {
    double diff = *(double*)a - *(double*)b;
    return (diff > 0) ? 1 : (diff < 0) ? -1 : 0;
}

/**
 * Perform metadata query
 */
static int perform_query(file_info_t *file, double *latency) {
    FDFSMetaData *meta_list = NULL;
    int meta_count = 0;
    
    double start = get_time_us();
    int result = fdfs_get_metadata(file->group_name, file->remote_filename,
                                   &meta_list, &meta_count);
    double end = get_time_us();
    *latency = (end - start) / 1000.0;
    
    if (result == 0 && meta_list != NULL) {
        free(meta_list);
        return 0;
    }
    
    return -1;
}

/**
 * Perform metadata update
 */
static int perform_update(file_info_t *file, double *latency) {
    FDFSMetaData meta_list[2];
    snprintf(meta_list[0].name, sizeof(meta_list[0].name), "updated");
    snprintf(meta_list[0].value, sizeof(meta_list[0].value), "%ld", time(NULL));
    snprintf(meta_list[1].name, sizeof(meta_list[1].name), "counter");
    snprintf(meta_list[1].value, sizeof(meta_list[1].value), "%d", rand() % 1000);
    
    double start = get_time_us();
    int result = fdfs_set_metadata(file->group_name, file->remote_filename,
                                   meta_list, 2, FDFS_METADATA_MERGE);
    double end = get_time_us();
    *latency = (end - start) / 1000.0;
    
    return result;
}

/**
 * Perform metadata delete
 */
static int perform_delete(file_info_t *file, double *latency) {
    FDFSMetaData meta_list[1];
    snprintf(meta_list[0].name, sizeof(meta_list[0].name), "counter");
    meta_list[0].value[0] = '\0';
    
    double start = get_time_us();
    int result = fdfs_set_metadata(file->group_name, file->remote_filename,
                                   meta_list, 1, FDFS_METADATA_OVERWRITE);
    double end = get_time_us();
    *latency = (end - start) / 1000.0;
    
    return result;
}

/**
 * Metadata operations thread
 */
static void* metadata_thread(void *arg) {
    thread_context_t *ctx = (thread_context_t*)arg;
    
    if (fdfs_client_init(ctx->tracker_server) != 0) {
        fprintf(stderr, "Thread %d: Failed to initialize client\n", ctx->thread_id);
        return NULL;
    }
    
    // Allocate latency arrays
    ctx->query_latencies = (double*)malloc(ctx->operation_count * sizeof(double));
    ctx->update_latencies = (double*)malloc(ctx->operation_count * sizeof(double));
    ctx->delete_latencies = (double*)malloc(ctx->operation_count * sizeof(double));
    
    ctx->query_count = 0;
    ctx->update_count = 0;
    ctx->delete_count = 0;
    ctx->query_success = 0;
    ctx->update_success = 0;
    ctx->delete_success = 0;
    ctx->query_latency_count = 0;
    ctx->update_latency_count = 0;
    ctx->delete_latency_count = 0;
    
    int total_ratio = ctx->query_ratio + ctx->update_ratio + ctx->delete_ratio;
    
    for (int i = 0; i < ctx->operation_count; i++) {
        int file_idx = rand() % ctx->file_count;
        file_info_t *file = &ctx->files[file_idx];
        
        int op = rand() % total_ratio;
        double latency = 0;
        
        if (op < ctx->query_ratio) {
            // Query operation
            ctx->query_count++;
            if (perform_query(file, &latency) == 0) {
                ctx->query_success++;
                ctx->query_latencies[ctx->query_latency_count++] = latency;
            }
        } else if (op < ctx->query_ratio + ctx->update_ratio) {
            // Update operation
            ctx->update_count++;
            if (perform_update(file, &latency) == 0) {
                ctx->update_success++;
                ctx->update_latencies[ctx->update_latency_count++] = latency;
            }
        } else {
            // Delete operation
            ctx->delete_count++;
            if (perform_delete(file, &latency) == 0) {
                ctx->delete_success++;
                ctx->delete_latencies[ctx->delete_latency_count++] = latency;
            }
        }
        
        if (g_verbose && (i % 1000 == 0)) {
            printf("Thread %d: %d/%d operations\r", ctx->thread_id, i, ctx->operation_count);
            fflush(stdout);
        }
    }
    
    fdfs_client_destroy();
    
    // Update global statistics
    pthread_mutex_lock(&g_stats_mutex);
    g_total_queries += ctx->query_count;
    g_total_updates += ctx->update_count;
    g_total_deletes += ctx->delete_count;
    g_successful_queries += ctx->query_success;
    g_successful_updates += ctx->update_success;
    g_successful_deletes += ctx->delete_success;
    pthread_mutex_unlock(&g_stats_mutex);
    
    return NULL;
}

/**
 * Calculate and print statistics
 */
static void print_latency_stats(const char *op_name, double *latencies, int count) {
    if (count == 0) {
        printf("    \"%s\": { \"count\": 0 }", op_name);
        return;
    }
    
    qsort(latencies, count, sizeof(double), compare_double);
    
    double mean = 0;
    for (int i = 0; i < count; i++) {
        mean += latencies[i];
    }
    mean /= count;
    
    printf("    \"%s\": {\n", op_name);
    printf("      \"count\": %d,\n", count);
    printf("      \"mean_ms\": %.2f,\n", mean);
    printf("      \"p50_ms\": %.2f,\n", latencies[(int)(count * 0.50)]);
    printf("      \"p95_ms\": %.2f,\n", latencies[(int)(count * 0.95)]);
    printf("      \"p99_ms\": %.2f,\n", latencies[(int)(count * 0.99)]);
    printf("      \"min_ms\": %.2f,\n", latencies[0]);
    printf("      \"max_ms\": %.2f\n", latencies[count - 1]);
    printf("    }");
}

/**
 * Print results
 */
static void print_results(double total_time, thread_context_t *contexts) {
    // Collect all latencies
    int max_ops = g_operation_count;
    double *all_query_latencies = (double*)malloc(max_ops * sizeof(double));
    double *all_update_latencies = (double*)malloc(max_ops * sizeof(double));
    double *all_delete_latencies = (double*)malloc(max_ops * sizeof(double));
    
    int query_count = 0, update_count = 0, delete_count = 0;
    
    for (int i = 0; i < g_thread_count; i++) {
        for (int j = 0; j < contexts[i].query_latency_count; j++) {
            all_query_latencies[query_count++] = contexts[i].query_latencies[j];
        }
        for (int j = 0; j < contexts[i].update_latency_count; j++) {
            all_update_latencies[update_count++] = contexts[i].update_latencies[j];
        }
        for (int j = 0; j < contexts[i].delete_latency_count; j++) {
            all_delete_latencies[delete_count++] = contexts[i].delete_latencies[j];
        }
    }
    
    printf("{\n");
    printf("  \"benchmark\": \"metadata\",\n");
    printf("  \"timestamp\": \"%ld\",\n", time(NULL));
    printf("  \"configuration\": {\n");
    printf("    \"threads\": %d,\n", g_thread_count);
    printf("    \"operation_count\": %d,\n", g_operation_count);
    printf("    \"operation_mix\": \"%d:%d:%d\"\n", 
           g_query_ratio, g_update_ratio, g_delete_ratio);
    printf("  },\n");
    printf("  \"metrics\": {\n");
    printf("    \"total_operations\": %d,\n", 
           g_total_queries + g_total_updates + g_total_deletes);
    printf("    \"ops_per_second\": %.2f,\n", 
           (g_total_queries + g_total_updates + g_total_deletes) / total_time);
    printf("    \"duration_seconds\": %.2f,\n", total_time);
    printf("    \"operations\": {\n");
    printf("      \"query\": {\n");
    printf("        \"total\": %d,\n", g_total_queries);
    printf("        \"successful\": %d,\n", g_successful_queries);
    printf("        \"success_rate\": %.2f\n", 
           (g_total_queries > 0) ? (double)g_successful_queries / g_total_queries * 100 : 0);
    printf("      },\n");
    printf("      \"update\": {\n");
    printf("        \"total\": %d,\n", g_total_updates);
    printf("        \"successful\": %d,\n", g_successful_updates);
    printf("        \"success_rate\": %.2f\n", 
           (g_total_updates > 0) ? (double)g_successful_updates / g_total_updates * 100 : 0);
    printf("      },\n");
    printf("      \"delete\": {\n");
    printf("        \"total\": %d,\n", g_total_deletes);
    printf("        \"successful\": %d,\n", g_successful_deletes);
    printf("        \"success_rate\": %.2f\n", 
           (g_total_deletes > 0) ? (double)g_successful_deletes / g_total_deletes * 100 : 0);
    printf("      }\n");
    printf("    },\n");
    printf("    \"latency\": {\n");
    print_latency_stats("query", all_query_latencies, query_count);
    printf(",\n");
    print_latency_stats("update", all_update_latencies, update_count);
    printf(",\n");
    print_latency_stats("delete", all_delete_latencies, delete_count);
    printf("\n    }\n");
    printf("  }\n");
    printf("}\n");
    
    free(all_query_latencies);
    free(all_update_latencies);
    free(all_delete_latencies);
}

/**
 * Print usage
 */
static void print_usage(const char *program) {
    printf("Usage: %s [OPTIONS]\n", program);
    printf("\nOptions:\n");
    printf("  -t, --threads NUM      Number of threads (default: 10)\n");
    printf("  -o, --operations NUM   Number of operations (default: 10000)\n");
    printf("  -m, --mix RATIO        Operation mix query:update:delete (default: 70:20:10)\n");
    printf("  -p, --prepare NUM      Number of files to prepare (default: 100)\n");
    printf("  -T, --tracker SERVER   Tracker server (default: 127.0.0.1:22122)\n");
    printf("  -v, --verbose          Verbose output\n");
    printf("  -h, --help             Show help\n");
}

/**
 * Main function
 */
int main(int argc, char *argv[]) {
    pthread_t threads[MAX_THREADS];
    thread_context_t contexts[MAX_THREADS];
    
    static struct option long_options[] = {
        {"threads", required_argument, 0, 't'},
        {"operations", required_argument, 0, 'o'},
        {"mix", required_argument, 0, 'm'},
        {"prepare", required_argument, 0, 'p'},
        {"tracker", required_argument, 0, 'T'},
        {"verbose", no_argument, 0, 'v'},
        {"help", no_argument, 0, 'h'},
        {0, 0, 0, 0}
    };
    
    int opt;
    while ((opt = getopt_long(argc, argv, "t:o:m:p:T:vh", long_options, NULL)) != -1) {
        switch (opt) {
            case 't': g_thread_count = atoi(optarg); break;
            case 'o': g_operation_count = atoi(optarg); break;
            case 'm': sscanf(optarg, "%d:%d:%d", &g_query_ratio, &g_update_ratio, &g_delete_ratio); break;
            case 'p': g_prepare_files = atoi(optarg); break;
            case 'T': strncpy(g_tracker_server, optarg, sizeof(g_tracker_server) - 1); break;
            case 'v': g_verbose = 1; break;
            case 'h': print_usage(argv[0]); return 0;
            default: print_usage(argv[0]); return 1;
        }
    }
    
    printf("FastDFS Metadata Operations Benchmark\n");
    printf("======================================\n");
    printf("Threads: %d\n", g_thread_count);
    printf("Operations: %d\n", g_operation_count);
    printf("Operation mix: %d:%d:%d (query:update:delete)\n", 
           g_query_ratio, g_update_ratio, g_delete_ratio);
    printf("Tracker: %s\n\n", g_tracker_server);
    
    srand(time(NULL));
    
    // Prepare test files
    if (prepare_test_files() != 0) {
        return 1;
    }
    
    int ops_per_thread = g_operation_count / g_thread_count;
    int remaining = g_operation_count % g_thread_count;
    
    for (int i = 0; i < g_thread_count; i++) {
        contexts[i].thread_id = i;
        contexts[i].operation_count = ops_per_thread + (i < remaining ? 1 : 0);
        contexts[i].tracker_server = g_tracker_server;
        contexts[i].files = g_files;
        contexts[i].file_count = g_file_count;
        contexts[i].query_ratio = g_query_ratio;
        contexts[i].update_ratio = g_update_ratio;
        contexts[i].delete_ratio = g_delete_ratio;
    }
    
    printf("Starting benchmark...\n");
    double start_time = get_time_us();
    
    for (int i = 0; i < g_thread_count; i++) {
        pthread_create(&threads[i], NULL, metadata_thread, &contexts[i]);
    }
    
    for (int i = 0; i < g_thread_count; i++) {
        pthread_join(threads[i], NULL);
    }
    
    double end_time = get_time_us();
    double total_time = (end_time - start_time) / 1000000.0;
    
    printf("\nBenchmark complete!\n\n");
    print_results(total_time, contexts);
    
    // Cleanup
    for (int i = 0; i < g_thread_count; i++) {
        free(contexts[i].query_latencies);
        free(contexts[i].update_latencies);
        free(contexts[i].delete_latencies);
    }
    free(g_files);
    
    return 0;
}


================================================
FILE: benchmarks/benchmark_small_files.c
================================================
/**
 * FastDFS Small Files Performance Benchmark
 * 
 * Tests performance with small files (<1MB) to identify optimization opportunities
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
#include <getopt.h>
#include "fdfs_client.h"

#define MAX_THREADS 1024
#define MIN_FILE_SIZE 1024      // 1KB
#define MAX_FILE_SIZE 102400    // 100KB

typedef struct {
    int thread_id;
    int file_count;
    int min_size;
    int max_size;
    char *tracker_server;
    
    // Results
    int successful;
    int failed;
    double total_bytes;
    double total_time;
    double *latencies;
    int latency_count;
} thread_context_t;

// Global configuration
static int g_thread_count = 20;
static int g_file_count = 10000;
static int g_min_size = MIN_FILE_SIZE;
static int g_max_size = MAX_FILE_SIZE;
static char g_tracker_server[256] = "127.0.0.1:22122";
static int g_verbose = 0;

// Global statistics
static pthread_mutex_t g_stats_mutex = PTHREAD_MUTEX_INITIALIZER;
static int g_total_successful = 0;
static int g_total_failed = 0;
static double g_total_bytes = 0;

/**
 * Get current time in microseconds
 */
static double get_time_us() {
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return tv.tv_sec * 1000000.0 + tv.tv_usec;
}

/**
 * Generate random data
 */
static char* generate_random_data(int size) {
    char *data = (char*)malloc(size);
    if (data == NULL) return NULL;
    
    for (int i = 0; i < size; i++) {
        data[i] = (char)(rand() % 256);
    }
    return data;
}

/**
 * Compare function for qsort
 */
static int compare_double(const void *a, const void *b) {
    double diff = *(double*)a - *(double*)b;
    return (diff > 0) ? 1 : (diff < 0) ? -1 : 0;
}

/**
 * Upload thread
 */
static void* upload_thread(void *arg) {
    thread_context_t *ctx = (thread_context_t*)arg;
    char group_name[FDFS_GROUP_NAME_MAX_LEN + 1];
    char remote_filename[256];
    
    if (fdfs_client_init(ctx->tracker_server) != 0) {
        fprintf(stderr, "Thread %d: Failed to initialize client\n", ctx->thread_id);
        return NULL;
    }
    
    ctx->latencies = (double*)malloc(ctx->file_count * sizeof(double));
    if (ctx->latencies == NULL) {
        fdfs_client_destroy();
        return NULL;
    }
    
    ctx->successful = 0;
    ctx->failed = 0;
    ctx->total_bytes = 0;
    ctx->latency_count = 0;
    
    double thread_start = get_time_us();
    
    for (int i = 0; i < ctx->file_count; i++) {
        // Random file size
        int file_size = ctx->min_size + (rand() % (ctx->max_size - ctx->min_size + 1));
        char *data = generate_random_data(file_size);
        if (data == NULL) {
            ctx->failed++;
            continue;
        }
        
        double start = get_time_us();
        int result = fdfs_upload_by_buffer(data, file_size, NULL, 
                                          group_name, remote_filename);
        double end = get_time_us();
        
        if (result == 0) {
            ctx->successful++;
            ctx->total_bytes += file_size;
            ctx->latencies[ctx->latency_count++] = (end - start) / 1000.0;
        } else {
            ctx->failed++;
        }
        
        free(data);
        
        if (g_verbose && (i % 1000 == 0)) {
            printf("Thread %d: %d/%d files\r", ctx->thread_id, i, ctx->file_count);
            fflush(stdout);
        }
    }
    
    double thread_end = get_time_us();
    ctx->total_time = (thread_end - thread_start) / 1000000.0;
    
    fdfs_client_destroy();
    
    pthread_mutex_lock(&g_stats_mutex);
    g_total_successful += ctx->successful;
    g_total_failed += ctx->failed;
    g_total_bytes += ctx->total_bytes;
    pthread_mutex_unlock(&g_stats_mutex);
    
    return NULL;
}

/**
 * Print results
 */
static void print_results(double total_time, double *all_latencies, int latency_count) {
    qsort(all_latencies, latency_count, sizeof(double), compare_double);
    
    double mean = 0;
    for (int i = 0; i < latency_count; i++) {
        mean += all_latencies[i];
    }
    mean /= latency_count;
    
    double throughput_mbps = (g_total_bytes / (1024 * 1024)) / total_time;
    double iops = g_total_successful / total_time;
    
    printf("{\n");
    printf("  \"benchmark\": \"small_files\",\n");
    printf("  \"timestamp\": \"%ld\",\n", time(NULL));
    printf("  \"configuration\": {\n");
    printf("    \"threads\": %d,\n", g_thread_count);
    printf("    \"file_count\": %d,\n", g_file_count);
    printf("    \"min_size\": %d,\n", g_min_size);
    printf("    \"max_size\": %d\n", g_max_size);
    printf("  },\n");
    printf("  \"metrics\": {\n");
    printf("    \"throughput_mbps\": %.2f,\n", throughput_mbps);
    printf("    \"iops\": %.2f,\n", iops);
    printf("    \"latency_ms\": {\n");
    printf("      \"mean\": %.2f,\n", mean);
    printf("      \"p50\": %.2f,\n", all_latencies[(int)(latency_count * 0.50)]);
    printf("      \"p95\": %.2f,\n", all_latencies[(int)(latency_count * 0.95)]);
    printf("      \"p99\": %.2f,\n", all_latencies[(int)(latency_count * 0.99)]);
    printf("      \"min\": %.2f,\n", all_latencies[0]);
    printf("      \"max\": %.2f\n", all_latencies[latency_count - 1]);
    printf("    },\n");
    printf("    \"operations\": {\n");
    printf("      \"successful\": %d,\n", g_total_successful);
    printf("      \"failed\": %d,\n", g_total_failed);
    printf("      \"success_rate\": %.2f\n", 
           (double)g_total_successful / (g_total_successful + g_total_failed) * 100);
    printf("    },\n");
    printf("    \"duration_seconds\": %.2f,\n", total_time);
    printf("    \"total_mb\": %.2f,\n", g_total_bytes / (1024 * 1024));
    printf("    \"avg_file_size_kb\": %.2f\n", 
           (g_total_bytes / g_total_successful) / 1024);
    printf("  }\n");
    printf("}\n");
}

/**
 * Print usage
 */
static void print_usage(const char *program) {
    printf("Usage: %s [OPTIONS]\n", program);
    printf("\nOptions:\n");
    printf("  -t, --threads NUM      Number of threads (default: 20)\n");
    printf("  -c, --count NUM        Number of files (default: 10000)\n");
    printf("  -m, --min-size BYTES   Minimum file size (default: 1024)\n");
    printf("  -M, --max-size BYTES   Maximum file size (default: 102400)\n");
    printf("  -T, --tracker SERVER   Tracker server (default: 127.0.0.1:22122)\n");
    printf("  -v, --verbose          Verbose output\n");
    printf("  -h, --help             Show help\n");
}

/**
 * Main function
 */
int main(int argc, char *argv[]) {
    pthread_t threads[MAX_THREADS];
    thread_context_t contexts[MAX_THREADS];
    
    static struct option long_options[] = {
        {"threads", required_argument, 0, 't'},
        {"count", required_argument, 0, 'c'},
        {"min-size", required_argument, 0, 'm'},
        {"max-size", required_argument, 0, 'M'},
        {"tracker", required_argument, 0, 'T'},
        {"verbose", no_argument, 0, 'v'},
        {"help", no_argument, 0, 'h'},
        {0, 0, 0, 0}
    };
    
    int opt;
    while ((opt = getopt_long(argc, argv, "t:c:m:M:T:vh", long_options, NULL)) != -1) {
        switch (opt) {
            case 't': g_thread_count = atoi(optarg); break;
            case 'c': g_file_count = atoi(optarg); break;
            case 'm': g_min_size = atoi(optarg); break;
            case 'M': g_max_size = atoi(optarg); break;
            case 'T': strncpy(g_tracker_server, optarg, sizeof(g_tracker_server) - 1); break;
            case 'v': g_verbose = 1; break;
            case 'h': print_usage(argv[0]); return 0;
            default: print_usage(argv[0]); return 1;
        }
    }
    
    printf("FastDFS Small Files Benchmark\n");
    printf("==============================\n");
    printf("Threads: %d\n", g_thread_count);
    printf("Files: %d\n", g_file_count);
    printf("Size range: %d - %d bytes\n", g_min_size, g_max_size);
    printf("Tracker: %s\n\n", g_tracker_server);
    
    srand(time(NULL));
    
    int files_per_thread = g_file_count / g_thread_count;
    int remaining = g_file_count % g_thread_count;
    
    for (int i = 0; i < g_thread_count; i++) {
        contexts[i].thread_id = i;
        contexts[i].file_count = files_per_thread + (i < remaining ? 1 : 0);
        contexts[i].min_size = g_min_size;
        contexts[i].max_size = g_max_size;
        contexts[i].tracker_server = g_tracker_server;
    }
    
    printf("Starting benchmark...\n");
    double start_time = get_time_us();
    
    for (int i = 0; i < g_thread_count; i++) {
        pthread_create(&threads[i], NULL, upload_thread, &contexts[i]);
    }
    
    for (int i = 0; i < g_thread_count; i++) {
        pthread_join(threads[i], NULL);
    }
    
    double end_time = get_time_us();
    double total_time = (end_time - start_time) / 1000000.0;
    
    // Collect all latencies
    double *all_latencies = (double*)malloc(g_file_count * sizeof(double));
    int latency_count = 0;
    
    for (int i = 0; i < g_thread_count; i++) {
        for (int j = 0; j < contexts[i].latency_count; j++) {
            all_latencies[latency_count++] = contexts[i].latencies[j];
        }
        free(contexts[i].latencies);
    }
    
    printf("\nBenchmark complete!\n\n");
    print_results(total_time, all_latencies, latency_count);
    
    free(all_latencies);
    return 0;
}


================================================
FILE: benchmarks/benchmark_upload.c
================================================
/**
 * FastDFS Upload Performance Benchmark
 * 
 * Measures upload throughput, IOPS, and latency percentiles
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <time.h>
#include <sys/time.h>
#include <unistd.h>
#include <getopt.h>
#include <errno.h>
#include "fdfs_client.h"
#include "logger.h"

#define MAX_THREADS 1024
#define MAX_LATENCIES 1000000
#define DEFAULT_FILE_SIZE 1048576  // 1MB

typedef struct {
    int thread_id;
    int files_to_upload;
    int file_size;
    char *tracker_server;
    
    // Results
    int successful_uploads;
    int failed_uploads;
    double *latencies;
    int latency_count;
    double total_bytes;
    double total_time;
} thread_context_t;

typedef struct {
    double mean;
    double median;
    double p50;
    double p75;
    double p90;
    double p95;
    double p99;
    double p999;
    double min;
    double max;
    double stddev;
} latency_stats_t;

// Global configuration
static int g_thread_count = 1;
static int g_file_count = 100;
static int g_file_size = DEFAULT_FILE_SIZE;
static char g_tracker_server[256] = "127.0.0.1:22122";
static char g_config_file[256] = "config/benchmark.conf";
static int g_warmup_enabled = 1;
static int g_warmup_duration = 10;
static int g_verbose = 0;

// Global statistics
static pthread_mutex_t g_stats_mutex = PTHREAD_MUTEX_INITIALIZER;
static int g_total_uploads = 0;
static int g_successful_uploads = 0;
static int g_failed_uploads = 0;
static double g_total_bytes = 0;
static double *g_all_latencies = NULL;
static int g_latency_count = 0;

/**
 * Get current time in microseconds
 */
static double get_time_us() {
    struct timeval tv;
    gettimeofday(&tv, NULL);
    return tv.tv_sec * 1000000.0 + tv.tv_usec;
}

/**
 * Generate random data for file upload
 */
static char* generate_random_data(int size) {
    char *data = (char*)malloc(size);
    if (data == NULL) {
        return NULL;
    }
    
    for (int i = 0; i < size; i++) {
        data[i] = (char)(rand() % 256);
    }
    
    return data;
}

/**
 * Compare function for qsort (for percentile calculation)
 */
static int compare_double(const void *a, const void *b) {
    double diff = *(double*)a - *(double*)b;
    return (diff > 0) ? 1 : (diff < 0) ? -1 : 0;
}

/**
 * Calculate latency statistics
 */
static void calculate_latency_stats(double *latencies, int count, latency_stats_t *stats) {
    if (count == 0) {
        memset(stats, 0, sizeof(latency_stats_t));
        return;
    }
    
    // Sort latencies
    qsort(latencies, count, sizeof(double), compare_double);
    
    // Calculate percentiles
    stats->min = latencies[0];
    stats->max = latencies[count - 1];
    stats->p50 = stats->median = latencies[(int)(count * 0.50)];
    stats->p75 = latencies[(int)(count * 0.75)];
    stats->p90 = latencies[(int)(count * 0.90)];
    stats->p95 = latencies[(int)(count * 0.95)];
    stats->p99 = latencies[(int)(count * 0.99)];
    stats->p999 = latencies[(int)(count * 0.999)];
    
    // Calculate mean
    double sum = 0;
    for (int i = 0; i < count; i++) {
        sum += latencies[i];
    }
    stats->mean = sum / count;
    
    // Calculate standard deviation
    double variance = 0;
    for (int i = 0; i < count; i++) {
        double diff = latencies[i] - stats->mean;
        variance += diff * diff;
    }
    stats->stddev = sqrt(variance / count);
}

/**
 * Upload thread function
 */
static void* upload_thread(void *arg) {
    thread_context_t *ctx = (thread_context_t*)arg;
    FDFSClient client;
    char group_name[FDFS_GROUP_NAME_MAX_LEN + 1];
    char remote_filename[256];
    char *file_data = NULL;
    int result;
    
    // Initialize client
    if (fdfs_client_init(ctx->tracker_server) != 0) {
        fprintf(stderr, "Thread %d: Failed to initialize FDFS client\n", ctx->thread_id);
        return NULL;
    }
    
    // Allocate latency array
    ctx->latencies = (double*)malloc(ctx->files_to_upload * sizeof(double));
    if (ctx->latencies == NULL) {
        fprintf(stderr, "Thread %d: Failed to allocate latency array\n", ctx->thread_id);
        fdfs_client_destroy();
        return NULL;
    }
    
    ctx->latency_count = 0;
    ctx->successful_uploads = 0;
    ctx->failed_uploads = 0;
    ctx->total_bytes = 0;
    
    // Generate file data once
    file_data = generate_random_data(ctx->file_size);
    if (file_data == NULL) {
        fprintf(stderr, "Thread %d: Failed to generate file data\n", ctx->thread_id);
        free(ctx->latencies);
        fdfs_client_destroy();
        return NULL;
    }
    
    double thread_start = get_time_us();
    
    // Upload files
    for (int i = 0; i < ctx->files_to_upload; i++) {
        double start_time = get_time_us();
        
        // Upload file
        result = fdfs_upload_by_buffer(file_data, ctx->file_size, 
                                       NULL, group_name, remote_filename);
        
        double end_time = get_time_us();
        double latency_ms = (end_time - start_time) / 1000.0;
        
        if (result == 0) {
            ctx->successful_uploads++;
            ctx->total_bytes += ctx->file_size;
            ctx->latencies[ctx->latency_count++] = latency_ms;
            
            if (g_verbose && (i % 100 == 0)) {
                printf("Thread %d: Uploaded %d/%d files (%.2f ms)\n", 
                       ctx->thread_id, i + 1, ctx->files_to_upload, latency_ms);
            }
        } else {
            ctx->failed_uploads++;
            if (g_verbose) {
                fprintf(stderr, "Thread %d: Upload failed: %s\n", 
                        ctx->thread_id, strerror(errno));
            }
        }
    }
    
    double thread_end = get_time_us();
    ctx->total_time = (thread_end - thread_start) / 1000000.0;
    
    // Cleanup
    free(file_data);
    fdfs_client_destroy();
    
    // Update global statistics
    pthread_mutex_lock(&g_stats_mutex);
    g_successful_uploads += ctx->successful_uploads;
    g_failed_uploads += ctx->failed_uploads;
    g_total_bytes += ctx->total_bytes;
    pthread_mutex_unlock(&g_stats_mutex);
    
    return NULL;
}

/**
 * Run warmup phase
 */
static void run_warmup() {
    if (!g_warmup_enabled || g_warmup_duration <= 0) {
        return;
    }
    
    printf("Running warmup phase for %d seconds...\n", g_warmup_duration);
    
    thread_context_t warmup_ctx;
    warmup_ctx.thread_id = 0;
    warmup_ctx.files_to_upload = 10;
    warmup_ctx.file_size = g_file_size;
    warmup_ctx.tracker_server = g_tracker_server;
    
    pthread_t warmup_thread;
    pthread_create(&warmup_thread, NULL, upload_thread, &warmup_ctx);
    
    sleep(g_warmup_duration);
    
    pthread_join(warmup_thread, NULL);
    
    if (warmup_ctx.latencies) {
        free(warmup_ctx.latencies);
    }
    
    printf("Warmup complete.\n\n");
}

/**
 * Print results in JSON format
 */
static void print_results(double total_time, latency_stats_t *stats) {
    double throughput_mbps = (g_total_bytes / (1024 * 1024)) / total_time;
    double iops = g_successful_uploads / total_time;
    double success_rate = (double)g_successful_uploads / g_total_uploads * 100.0;
    
    printf("{\n");
    printf("  \"benchmark\": \"upload\",\n");
    printf("  \"timestamp\": \"%ld\",\n", time(NULL));
    printf("  \"configuration\": {\n");
    printf("    \"threads\": %d,\n", g_thread_count);
    printf("    \"file_count\": %d,\n", g_file_count);
    printf("    \"file_size\": %d,\n", g_file_size);
    printf("    \"tracker_server\": \"%s\"\n", g_tracker_server);
    printf("  },\n");
    printf("  \"metrics\": {\n");
    printf("    \"throughput_mbps\": %.2f,\n", throughput_mbps);
    printf("    \"iops\": %.2f,\n", iops);
    printf("    \"latency_ms\": {\n");
    printf("      \"mean\": %.2f,\n", stats->mean);
    printf("      \"median\": %.2f,\n", stats->median);
    printf("      \"p50\": %.2f,\n", stats->p50);
    printf("      \"p75\": %.2f,\n", stats->p75);
    printf("      \"p90\": %.2f,\n", stats->p90);
    printf("      \"p95\": %.2f,\n", stats->p95);
    printf("      \"p99\": %.2f,\n", stats->p99);
    printf("      \"p999\": %.2f,\n", stats->p999);
    printf("      \"min\": %.2f,\n", stats->min);
    printf("      \"max\": %.2f,\n", stats->max);
    printf("      \"stddev\": %.2f\n", stats->stddev);
    printf("    },\n");
    printf("    \"operations\": {\n");
    printf("      \"total\": %d,\n", g_total_uploads);
    printf("      \"successful\": %d,\n", g_successful_uploads);
    printf("      \"failed\": %d,\n", g_failed_uploads);
    printf("      \"success_rate\": %.2f\n", success_rate);
    printf("    },\n");
    printf("    \"duration_seconds\": %.2f,\n", total_time);
    printf("    \"total_mb\": %.2f\n", g_total_bytes / (1024 * 1024));
    printf("  }\n");
    printf("}\n");
}

/**
 * Print usage information
 */
static void print_usage(const char *program) {
    printf("Usage: %s [OPTIONS]\n", program);
    printf("\nOptions:\n");
    printf("  -t, --threads NUM      Number of concurrent threads (default: 1)\n");
    printf("  -f, --files NUM        Number of files to upload (default: 100)\n");
    printf("  -s, --size BYTES       File size in bytes (default: 1048576)\n");
    printf("  -c, --config FILE      Configuration file (default: config/benchmark.conf)\n");
    printf("  -T, --tracker SERVER   Tracker server (default: 127.0.0.1:22122)\n");
    printf("  -w, --warmup SECONDS   Warmup duration (default: 10, 0 to disable)\n");
    printf("  -v, --verbose          Enable verbose output\n");
    printf("  -h, --help             Show this help message\n");
}

/**
 * Main function
 */
int main(int argc, char *argv[]) {
    pthread_t threads[MAX_THREADS];
    thread_context_t contexts[MAX_THREADS];
    
    // Parse command line arguments
    static struct option long_options[] = {
        {"threads", required_argument, 0, 't'},
        {"files", required_argument, 0, 'f'},
        {"size", required_argument, 0, 's'},
        {"config", required_argument, 0, 'c'},
        {"tracker", required_argument, 0, 'T'},
        {"warmup", required_argument, 0, 'w'},
        {"verbose", no_argument, 0, 'v'},
        {"help", no_argument, 0, 'h'},
        {0, 0, 0, 0}
    };
    
    int opt;
    while ((opt = getopt_long(argc, argv, "t:f:s:c:T:w:vh", long_options, NULL)) != -1) {
        switch (opt) {
            case 't':
                g_thread_count = atoi(optarg);
                break;
            case 'f':
                g_file_count = atoi(optarg);
                break;
            case 's':
                g_file_size = atoi(optarg);
                break;
            case 'c':
                strncpy(g_config_file, optarg, sizeof(g_config_file) - 1);
                break;
            case 'T':
                strncpy(g_tracker_server, optarg, sizeof(g_tracker_server) - 1);
                break;
            case 'w':
                g_warmup_duration = atoi(optarg);
                break;
            case 'v':
                g_verbose = 1;
                break;
            case 'h':
                print_usage(argv[0]);
                return 0;
            default:
                print_usage(argv[0]);
                return 1;
        }
    }
    
    // Validate parameters
    if (g_thread_count < 1 || g_thread_count > MAX_THREADS) {
        fprintf(stderr, "Error: Thread count must be between 1 and %d\n", MAX_THREADS);
        return 1;
    }
    
    if (g_file_count < 1) {
        fprintf(stderr, "Error: File count must be at least 1\n");
        return 1;
    }
    
    if (g_file_size < 1) {
        fprintf(stderr, "Error: File size must be at least 1 byte\n");
        return 1;
    }
    
    printf("FastDFS Upload Performance Benchmark\n");
    printf("=====================================\n");
    printf("Threads: %d\n", g_thread_count);
    printf("Files per thread: %d\n", g_file_count / g_thread_count);
    printf("File size: %d bytes (%.2f MB)\n", g_file_size, g_file_size / (1024.0 * 1024.0));
    printf("Total files: %d\n", g_file_count);
    printf("Tracker: %s\n\n", g_tracker_server);
    
    // Initialize random seed
    srand(time(NULL));
    
    // Run warmup
    run_warmup();
    
    // Allocate global latency array
    g_all_latencies = (double*)malloc(g_file_count * sizeof(double));
    if (g_all_latencies == NULL) {
        fprintf(stderr, "Error: Failed to allocate latency array\n");
        return 1;
    }
    
    // Initialize thread contexts
    int files_per_thread = g_file_count / g_thread_count;
    int remaining_files = g_file_count % g_thread_count;
    
    for (int i = 0; i < g_thread_count; i++) {
        contexts[i].thread_id = i;
        contexts[i].files_to_upload = files_per_thread + (i < remaining_files ? 1 : 0);
        contexts[i].file_size = g_file_size;
        contexts[i].tracker_server = g_tracker_server;
    }
    
    // Start benchmark
    printf("Starting benchmark...\n");
    double start_time = get_time_us();
    
    // Create threads
    for (int i = 0; i < g_thread_count; i++) {
        if (pthread_create(&threads[i], NULL, upload_thread, &contexts[i]) != 0) {
            fprintf(stderr, "Error: Failed to create thread %d\n", i);
            return 1;
        }
    }
    
    // Wait for threads to complete
    for (int i = 0; i < g_thread_count; i++) {
        pthread_join(threads[i], NULL);
    }
    
    double end_time = get_time_us();
    double total_time = (end_time - start_time) / 1000000.0;
    
    // Collect all latencies
    g_latency_count = 0;
    for (int i = 0; i < g_thread_count; i++) {
        for (int j = 0; j < contexts[i].latency_count; j++) {
            g_all_latencies[g_latency_count++] = contexts[i].latencies[j];
        }
        free(contexts[i].latencies);
    }
    
    // Calculate statistics
    latency_stats_t stats;
    calculate_latency_stats(g_all_latencies, g_latency_count, &stats);
    
    // Print results
    printf("\nBenchmark complete!\n\n");
    print_results(total_time, &stats);
    
    // Cleanup
    free(g_all_latencies);
    
    return 0;
}


================================================
FILE: benchmarks/config/benchmark.conf
================================================
# FastDFS Benchmark Configuration

# Tracker Server Configuration
tracker_server = 127.0.0.1:22122

# Storage Server Configuration (optional, for direct storage testing)
storage_server = 127.0.0.1:23000

# Connection Settings
connect_timeout = 30
network_timeout = 60
max_connections = 256

# Benchmark Settings
[upload]
# Number of concurrent threads
threads = 10
# Number of files to upload
file_count = 1000
# Default file size in bytes (1MB)
file_size = 1048576
# Enable warm-up phase
warmup_enabled = true
# Warm-up duration in seconds
warmup_duration = 10

[download]
# Number of concurrent threads
threads = 10
# Number of download iterations
iterations = 1000
# Enable warm-up phase
warmup_enabled = true
# Warm-up duration in seconds
warmup_duration = 10

[concurrent]
# Number of concurrent users to simulate
concurrent_users = 50
# Test duration in seconds
duration = 300
# Operation mix (upload:download:delete ratio)
operation_mix = 50:45:5
# Think time between operations (ms)
think_time = 100

[small_files]
# Number of small files to test
file_count = 10000
# Minimum file size (1KB)
min_size = 1024
# Maximum file size (100KB)
max_size = 102400
# Number of concurrent threads
threads = 20

[large_files]
# Number of large files to test
file_count = 100
# Minimum file size (100MB)
min_size = 104857600
# Maximum file size (1GB)
max_size = 1073741824
# Number of concurrent threads
threads = 5

[metadata]
# Number of metadata operations
operation_count = 10000
# Number of concurrent threads
threads = 10
# Operation types (query:update:delete ratio)
operation_types = 70:20:10

# Resource Monitoring
[monitoring]
# Enable resource monitoring
enabled = true
# Monitoring interval in seconds
interval = 1
# Metrics to collect (cpu,memory,network,disk)
metrics = cpu,memory,network,disk

# Result Settings
[results]
# Output directory for results
output_dir = results/
# Result format (json, csv, both)
format = json
# Enable detailed logging
detailed_logging = true
# Log file path
log_file = results/benchmark.log

# Report Settings
[report]
# Report format (html, pdf, both)
format = html
# Include graphs
include_graphs = true
# Include resource utilization charts
include_resources = true
# Report template
template = default

# Advanced Settings
[advanced]
# Enable latency histogram
latency_histogram = true
# Histogram buckets (ms)
histogram_buckets = 1,5,10,20,50,100,200,500,1000
# Enable per-thread statistics
per_thread_stats = false
# Enable real-time progress display
show_progress = true
# Progress update interval (seconds)
progress_interval = 5


================================================
FILE: benchmarks/results/template.json
================================================
{
  "benchmark": "template",
  "version": "1.0.0",
  "fastdfs_version": "6.12.1",
  "timestamp": "2024-01-15T10:30:00Z",
  "hostname": "benchmark-server-01",
  "system_info": {
    "os": "Linux",
    "kernel": "5.15.0",
    "cpu_model": "Intel Xeon E5-2680 v4",
    "cpu_cores": 28,
    "memory_gb": 64,
    "disk_type": "SSD",
    "network_speed_gbps": 10
  },
  "configuration": {
    "tracker_server": "127.0.0.1:22122",
    "storage_server": "127.0.0.1:23000",
    "threads": 10,
    "file_count": 1000,
    "file_size": 1048576,
    "warmup_enabled": true,
    "warmup_duration": 10
  },
  "metrics": {
    "throughput": {
      "upload_mbps": 0.0,
      "download_mbps": 0.0,
      "total_mbps": 0.0
    },
    "iops": {
      "read": 0,
      "write": 0,
      "total": 0
    },
    "latency_ms": {
      "mean": 0.0,
      "median": 0.0,
      "p50": 0.0,
      "p75": 0.0,
      "p90": 0.0,
      "p95": 0.0,
      "p99": 0.0,
      "p999": 0.0,
      "min": 0.0,
      "max": 0.0,
      "stddev": 0.0
    },
    "operations": {
      "total": 0,
      "successful": 0,
      "failed": 0,
      "timeout": 0,
      "success_rate": 0.0,
      "error_rate": 0.0,
      "timeout_rate": 0.0
    },
    "duration": {
      "total_seconds": 0.0,
      "warmup_seconds": 0.0,
      "test_seconds": 0.0
    },
    "data_transferred": {
      "total_bytes": 0,
      "total_mb": 0.0,
      "total_gb": 0.0
    }
  },
  "resource_utilization": {
    "cpu": {
      "mean_percent": 0.0,
      "max_percent": 0.0,
      "min_percent": 0.0
    },
    "memory": {
      "mean_mb": 0.0,
      "max_mb": 0.0,
      "min_mb": 0.0,
      "mean_percent": 0.0
    },
    "network": {
      "rx_mbps": 0.0,
      "tx_mbps": 0.0,
      "total_mbps": 0.0,
      "rx_packets": 0,
      "tx_packets": 0
    },
    "disk": {
      "read_mbps": 0.0,
      "write_mbps": 0.0,
      "read_iops": 0,
      "write_iops": 0,
      "utilization_percent": 0.0
    }
  },
  "latency_histogram": {
    "buckets": [1, 5, 10, 20, 50, 100, 200, 500, 1000],
    "counts": [0, 0, 0, 0, 0, 0, 0, 0, 0]
  },
  "per_thread_stats": [],
  "errors": [],
  "warnings": [],
  "notes": ""
}


================================================
FILE: benchmarks/scripts/compare_versions.py
================================================
#!/usr/bin/env python3
"""
FastDFS Version Comparison Tool

Compares performance between two FastDFS versions
"""

import json
import argparse
import sys
from pathlib import Path


def load_results(filepath):
    """Load benchmark results from JSON file"""
    try:
        with open(filepath, 'r') as f:
            return json.load(f)
    except FileNotFoundError:
        print(f"Error: File not found: {filepath}", file=sys.stderr)
        sys.exit(1)
    except json.JSONDecodeError as e:
        print(f"Error: Invalid JSON in {filepath}: {e}", file=sys.stderr)
        sys.exit(1)


def calculate_change(baseline, current):
    """Calculate percentage change"""
    if baseline == 0:
        return 0
    return ((current - baseline) / baseline) * 100


def format_change(change):
    """Format change with color indicator"""
    if change > 0:
        return f"+{change:.2f}% ⬆️"
    elif change < 0:
        return f"{change:.2f}% ⬇️"
    else:
        return "0.00% ➡️"


def compare_metrics(baseline_metrics, current_metrics, metric_name):
    """Compare a specific metric between versions"""
    baseline_val = baseline_metrics.get(metric_name, 0)
    current_val = current_metrics.get(metric_name, 0)
    change = calculate_change(baseline_val, current_val)
    
    return {
        'baseline': baseline_val,
        'current': current_val,
        'change': change,
        'change_str': format_change(change)
    }


def compare_benchmark(baseline_data, current_data, bench_name):
    """Compare a specific benchmark between versions"""
    print(f"\n{'='*80}")
    print(f"  {bench_name.upper()} BENCHMARK")
    print(f"{'='*80}")
    
    if 'metrics' not in baseline_data or 'metrics' not in current_data:
        print("  ⚠️  Insufficient data for comparison")
        return
    
    baseline_metrics = baseline_data['metrics']
    current_metrics = current_data['metrics']
    
    # Compare throughput
    if 'throughput_mbps' in baseline_metrics and 'throughput_mbps' in current_metrics:
        comp = compare_metrics(baseline_metrics, current_metrics, 'throughput_mbps')
        print(f"\n  Throughput:")
        print(f"    Baseline: {comp['baseline']:.2f} MB/s")
        print(f"    Current:  {comp['current']:.2f} MB/s")
        print(f"    Change:   {comp['change_str']}")
    
    # Compare IOPS
    if 'iops' in baseline_metrics and 'iops' in current_metrics:
        comp = compare_metrics(baseline_metrics, current_metrics, 'iops')
        print(f"\n  IOPS:")
        print(f"    Baseline: {comp['baseline']:.2f} ops/s")
        print(f"    Current:  {comp['current']:.2f} ops/s")
        print(f"    Change:   {comp['change_str']}")
    
    # Compare latency
    if 'latency_ms' in baseline_metrics and 'latency_ms' in current_metrics:
        baseline_latency = baseline_metrics['latency_ms']
        current_latency = current_metrics['la
Download .txt
gitextract_pt_qh3a1/

├── .gitignore
├── COPYING-3_0.txt
├── HISTORY
├── INSTALL
├── README.md
├── README_zh.md
├── benchmarks/
│   ├── .gitignore
│   ├── Makefile
│   ├── README.md
│   ├── benchmark_concurrent.c
│   ├── benchmark_download.c
│   ├── benchmark_large_files.c
│   ├── benchmark_metadata.c
│   ├── benchmark_small_files.c
│   ├── benchmark_upload.c
│   ├── config/
│   │   └── benchmark.conf
│   ├── results/
│   │   └── template.json
│   └── scripts/
│       ├── compare_versions.py
│       ├── generate_report.py
│       └── run_all_benchmarks.sh
├── cli/
│   ├── Makefile.in
│   ├── README.md
│   └── fdfs_cli.c
├── client/
│   ├── Makefile.in
│   ├── client_func.c
│   ├── client_func.h
│   ├── client_global.c
│   ├── client_global.h
│   ├── fdfs_append_file.c
│   ├── fdfs_appender_test.c
│   ├── fdfs_appender_test1.c
│   ├── fdfs_bulk_import.c
│   ├── fdfs_client.h
│   ├── fdfs_crc32.c
│   ├── fdfs_delete_file.c
│   ├── fdfs_download_file.c
│   ├── fdfs_file_info.c
│   ├── fdfs_link_library.sh.in
│   ├── fdfs_monitor.c
│   ├── fdfs_regenerate_filename.c
│   ├── fdfs_test.c
│   ├── fdfs_test1.c
│   ├── fdfs_upload_appender.c
│   ├── fdfs_upload_file.c
│   ├── storage_client.c
│   ├── storage_client.h
│   ├── storage_client1.h
│   ├── test/
│   │   └── Makefile.in
│   ├── tracker_client.c
│   └── tracker_client.h
├── common/
│   ├── Makefile
│   ├── fdfs_define.h
│   ├── fdfs_global.c
│   ├── fdfs_global.h
│   ├── fdfs_http_shared.c
│   ├── fdfs_http_shared.h
│   ├── mime_file_parser.c
│   └── mime_file_parser.h
├── conf/
│   ├── client.conf
│   ├── http.conf
│   ├── mime.types
│   ├── storage.conf
│   ├── storage_ids.conf
│   └── tracker.conf
├── cpp_client/
│   ├── CMakeLists.txt
│   ├── README.md
│   ├── examples/
│   │   ├── CMakeLists.txt
│   │   ├── advanced_metadata_example.cpp
│   │   ├── appender_example.cpp
│   │   ├── basic_usage.cpp
│   │   ├── batch_operations_example.cpp
│   │   ├── cancellation_example.cpp
│   │   ├── concurrent_operations_example.cpp
│   │   ├── configuration_example.cpp
│   │   ├── connection_pool_example.cpp
│   │   ├── error_handling_example.cpp
│   │   ├── file_info_example.cpp
│   │   ├── metadata_example.cpp
│   │   ├── partial_download_example.cpp
│   │   ├── performance_example.cpp
│   │   ├── slave_file_example.cpp
│   │   ├── streaming_example.cpp
│   │   └── upload_buffer_example.cpp
│   ├── include/
│   │   └── fastdfs/
│   │       ├── client.hpp
│   │       ├── errors.hpp
│   │       └── types.hpp
│   └── src/
│       ├── client.cpp
│       └── internal/
│           ├── connection.cpp
│           ├── connection.hpp
│           ├── connection_pool.cpp
│           ├── connection_pool.hpp
│           ├── operations.cpp
│           ├── operations.hpp
│           ├── protocol.cpp
│           └── protocol.hpp
├── csharp_client/
│   ├── ConnectionPool.cs
│   ├── FastDFSClient.cs
│   ├── FastDFSClientConfig.cs
│   ├── FastDFSConstants.cs
│   ├── FastDFSErrors.cs
│   ├── FastDFSTypes.cs
│   ├── ProtocolBuilder.cs
│   ├── ProtocolParser.cs
│   ├── README.md
│   └── examples/
│       ├── AdvancedMetadataExample.cs
│       ├── AppenderFileExample.cs
│       ├── BasicExample.cs
│       ├── BatchOperationsExample.cs
│       ├── CancellationExample.cs
│       ├── ConcurrentOperationsExample.cs
│       ├── ConfigurationExample.cs
│       ├── ConnectionPoolExample.cs
│       ├── ErrorHandlingExample.cs
│       ├── FileInfoExample.cs
│       ├── IntegrationExample.cs
│       ├── MetadataExample.cs
│       ├── PartialDownloadExample.cs
│       ├── PerformanceExample.cs
│       ├── SlaveFileExample.cs
│       ├── StreamingExample.cs
│       └── UploadBufferExample.cs
├── debian/
│   ├── README.Debian
│   ├── changelog
│   ├── compat
│   ├── control
│   ├── copyright
│   ├── fastdfs-config.install
│   ├── fastdfs-server.dirs
│   ├── fastdfs-server.install
│   ├── fastdfs-tool.dirs
│   ├── fastdfs-tool.install
│   ├── libfdfsclient-dev.install
│   ├── libfdfsclient.install
│   ├── rules
│   ├── source/
│   │   └── format
│   ├── substvars
│   └── watch
├── docker/
│   ├── dockerfile_local/
│   │   ├── Dockerfile
│   │   ├── README.md
│   │   ├── conf/
│   │   │   ├── client.conf
│   │   │   ├── http.conf
│   │   │   ├── mime.types
│   │   │   ├── mod_fastdfs.conf
│   │   │   ├── nginx.conf
│   │   │   ├── storage.conf
│   │   │   └── tracker.conf
│   │   └── fastdfs.sh
│   ├── dockerfile_local-v6.0.9/
│   │   ├── README.md
│   │   ├── build_image-v6.0.8/
│   │   │   ├── Dockerfile
│   │   │   ├── conf/
│   │   │   │   ├── client.conf
│   │   │   │   ├── http.conf
│   │   │   │   ├── mime.types
│   │   │   │   ├── mod_fastdfs.conf
│   │   │   │   ├── storage.conf
│   │   │   │   ├── storage_ids.conf
│   │   │   │   └── tracker.conf
│   │   │   ├── nginx_conf/
│   │   │   │   └── nginx.conf
│   │   │   ├── nginx_conf.d/
│   │   │   │   └── default.conf
│   │   │   └── start.sh
│   │   ├── build_image-v6.0.9/
│   │   │   ├── Dockerfile
│   │   │   ├── conf/
│   │   │   │   ├── client.conf
│   │   │   │   ├── http.conf
│   │   │   │   ├── mime.types
│   │   │   │   ├── mod_fastdfs.conf
│   │   │   │   ├── storage.conf
│   │   │   │   ├── storage_ids.conf
│   │   │   │   └── tracker.conf
│   │   │   ├── nginx_conf/
│   │   │   │   └── nginx.conf
│   │   │   ├── nginx_conf.d/
│   │   │   │   └── default.conf
│   │   │   └── start.sh
│   │   ├── fastdfs-conf/
│   │   │   ├── conf/
│   │   │   │   ├── client.conf
│   │   │   │   ├── http.conf
│   │   │   │   ├── mime.types
│   │   │   │   ├── mod_fastdfs.conf
│   │   │   │   ├── storage.conf
│   │   │   │   ├── storage_ids.conf
│   │   │   │   └── tracker.conf
│   │   │   ├── nginx_conf/
│   │   │   │   └── nginx.conf
│   │   │   ├── nginx_conf.d/
│   │   │   │   └── default.conf
│   │   │   └── setting_conf.sh
│   │   ├── fastdfs自定义镜像和安装手册.txt
│   │   └── qa.txt
│   └── dockerfile_network/
│       ├── Dockerfile
│       ├── README.md
│       ├── conf/
│       │   ├── client.conf
│       │   ├── http.conf
│       │   ├── mime.types
│       │   ├── mod_fastdfs.conf
│       │   ├── nginx.conf
│       │   ├── storage.conf
│       │   └── tracker.conf
│       └── fastdfs.sh
├── examples/
│   ├── c_examples/
│   │   ├── 01_basic_upload.c
│   │   ├── 02_basic_download.c
│   │   ├── 03_metadata_operations.c
│   │   ├── 04_appender_file.c
│   │   ├── 05_slave_file.c
│   │   ├── 06_batch_upload.c
│   │   ├── 07_connection_pool.c
│   │   ├── 08_error_handling.c
│   │   └── Makefile
│   └── php_examples/
│       ├── 01_basic_upload.php
│       ├── 02_basic_download.php
│       ├── 03_metadata_operations.php
│       ├── 04_appender_file.php
│       ├── 05_slave_file.php
│       ├── 06_advanced_download.php
│       ├── 07_connection_pool_error_handling.php
│       └── 08_error_handling.php
├── fastdfs.spec
├── go_client/
│   ├── .gitignore
│   ├── CONTRIBUTING.md
│   ├── IMPLEMENTATION_SUMMARY.md
│   ├── Makefile
│   ├── README.md
│   ├── appender.go
│   ├── client.go
│   ├── client_test.go
│   ├── connection.go
│   ├── errors.go
│   ├── examples/
│   │   ├── appender/
│   │   │   └── main.go
│   │   ├── basic/
│   │   │   └── main.go
│   │   ├── batch/
│   │   │   └── main.go
│   │   ├── concurrent/
│   │   │   └── main.go
│   │   ├── connection_pool/
│   │   │   └── main.go
│   │   ├── error_handling/
│   │   │   └── main.go
│   │   ├── metadata/
│   │   │   └── main.go
│   │   └── performance/
│   │       └── main.go
│   ├── go.sum
│   ├── metadata.go
│   ├── operations.go
│   ├── protocol.go
│   └── types.go
├── groovy_client/
│   ├── .gitignore
│   ├── CONTRIBUTING.md
│   ├── Makefile
│   ├── README.md
│   ├── build.gradle
│   └── src/
│       ├── main/
│       │   └── groovy/
│       │       └── com/
│       │           └── fastdfs/
│       │               └── client/
│       │                   ├── FastDFSClient.groovy
│       │                   ├── config/
│       │                   │   └── ClientConfig.groovy
│       │                   ├── connection/
│       │                   │   ├── Connection.groovy
│       │                   │   └── ConnectionPool.groovy
│       │                   ├── errors/
│       │                   │   └── FastDFSErrors.groovy
│       │                   ├── examples/
│       │                   │   └── BasicExample.groovy
│       │                   ├── operations/
│       │                   │   └── Operations.groovy
│       │                   ├── protocol/
│       │                   │   └── ProtocolHandler.groovy
│       │                   └── types/
│       │                       └── Types.groovy
│       └── test/
│           └── groovy/
│               └── com/
│                   └── fastdfs/
│                       └── client/
│                           ├── FastDFSClientTest.groovy
│                           └── config/
│                               └── ClientConfigTest.groovy
├── init.d/
│   ├── fdfs_storaged
│   └── fdfs_trackerd
├── javascript_client/
│   ├── .gitignore
│   ├── README.md
│   ├── examples/
│   │   ├── 01_basic_upload.js
│   │   ├── 02_metadata_operations.js
│   │   ├── 03_appender_file.js
│   │   └── 04_slave_file.js
│   ├── package.json
│   └── src/
│       ├── client.js
│       ├── connection.js
│       ├── errors.js
│       ├── index.js
│       ├── operations.js
│       ├── protocol.js
│       └── types.js
├── make.sh
├── monitoring/
│   ├── health_check/
│   │   ├── Makefile
│   │   ├── README.md
│   │   └── health_checker.c
│   └── prometheus_exporter/
│       ├── Makefile
│       ├── README.md
│       ├── fdfs_exporter.c
│       └── grafana_dashboard.json
├── php_client/
│   ├── README
│   ├── config.m4
│   ├── fastdfs_appender_test.php
│   ├── fastdfs_appender_test1.php
│   ├── fastdfs_callback_test.php
│   ├── fastdfs_client.c
│   ├── fastdfs_client.h
│   ├── fastdfs_client.ini
│   ├── fastdfs_client.spec.in
│   ├── fastdfs_test.php
│   ├── fastdfs_test1.php
│   └── fastdfs_test_slave.php
├── python_client/
│   ├── .gitignore
│   ├── LICENSE
│   ├── MANIFEST.in
│   ├── README.md
│   ├── examples/
│   │   ├── appender_example.py
│   │   ├── basic_usage.py
│   │   └── meta_example.py
│   ├── fdfs/
│   │   ├── __init__.py
│   │   ├── client.py
│   │   ├── connection.py
│   │   ├── errors.py
│   │   ├── operations.py
│   │   ├── protocol.py
│   │   └── types.py
│   ├── pyproject.toml
│   ├── requirements-dev.txt
│   ├── setup.py
│   └── tests/
│       ├── init.py
│       ├── test_client.py
│       ├── test_connection.py
│       ├── test_integration.py
│       └── test_protocol.py
├── ruby_client/
│   ├── Gemfile
│   ├── LICENSE
│   ├── README.md
│   ├── examples/
│   │   ├── basic_usage.rb
│   │   ├── metadata_example.rb
│   │   └── upload_buffer.rb
│   ├── fastdfs.gemspec
│   └── lib/
│       ├── fastdfs/
│       │   ├── client.rb
│       │   ├── client_config.rb
│       │   ├── connection_pool.rb
│       │   ├── errors.rb
│       │   ├── operations.rb
│       │   ├── protocol.rb
│       │   └── types.rb
│       └── fastdfs.rb
├── rust_client/
│   ├── .gitignore
│   ├── Cargo.toml
│   ├── LICENSE
│   ├── benches/
│   │   └── benchmark.rs
│   ├── examples/
│   │   ├── advanced_metadata_example.rs
│   │   ├── appender_example.rs
│   │   ├── basic_usage.rs
│   │   ├── batch_operations_example.rs
│   │   ├── cancellation_example.rs
│   │   ├── concurrent_operations_example.rs
│   │   ├── configuration_example.rs
│   │   ├── connection_pool_example.rs
│   │   ├── error_handling_example.rs
│   │   ├── file_info_example.rs
│   │   ├── integration_example.rs
│   │   ├── metadata_example.rs
│   │   ├── partial_download_example.rs
│   │   ├── performance_example.rs
│   │   ├── slave_file_example.rs
│   │   ├── streaming_example.rs
│   │   └── upload_buffer_example.rs
│   ├── src/
│   │   ├── client.rs
│   │   ├── connection.rs
│   │   ├── errors.rs
│   │   ├── lib.rs
│   │   ├── operations.rs
│   │   ├── protocol.rs
│   │   └── types.rs
│   └── tests/
│       ├── client_tests.rs
│       ├── connection_tests.rs
│       ├── integration_tests.rs
│       └── protocol_tests.rs
├── setup.sh
├── storage/
│   ├── Makefile.in
│   ├── fdfs_storaged.c
│   ├── fdht_client/
│   │   ├── fdht_client.c
│   │   ├── fdht_client.h
│   │   ├── fdht_define.h
│   │   ├── fdht_func.c
│   │   ├── fdht_func.h
│   │   ├── fdht_global.c
│   │   ├── fdht_global.h
│   │   ├── fdht_proto.c
│   │   ├── fdht_proto.h
│   │   ├── fdht_proto_types.h
│   │   └── fdht_types.h
│   ├── file_id_hashtable.c
│   ├── file_id_hashtable.h
│   ├── storage_bulk_import.c
│   ├── storage_bulk_import.h
│   ├── storage_dio.c
│   ├── storage_dio.h
│   ├── storage_disk_recovery.c
│   ├── storage_disk_recovery.h
│   ├── storage_dump.c
│   ├── storage_dump.h
│   ├── storage_func.c
│   ├── storage_func.h
│   ├── storage_global.c
│   ├── storage_global.h
│   ├── storage_ip_changed_dealer.c
│   ├── storage_ip_changed_dealer.h
│   ├── storage_param_getter.c
│   ├── storage_param_getter.h
│   ├── storage_service.c
│   ├── storage_service.h
│   ├── storage_sync.c
│   ├── storage_sync.h
│   ├── storage_sync_func.c
│   ├── storage_sync_func.h
│   ├── storage_types.h
│   ├── tracker_client_thread.c
│   ├── tracker_client_thread.h
│   └── trunk_mgr/
│       ├── trunk_client.c
│       ├── trunk_client.h
│       ├── trunk_free_block_checker.c
│       ├── trunk_free_block_checker.h
│       ├── trunk_mem.c
│       ├── trunk_mem.h
│       ├── trunk_shared.c
│       ├── trunk_shared.h
│       ├── trunk_sync.c
│       └── trunk_sync.h
├── systemd/
│   ├── fdfs_storaged.service
│   └── fdfs_trackerd.service
├── test/
│   ├── Makefile
│   ├── combine_result.c
│   ├── common_func.c
│   ├── common_func.h
│   ├── dfs_func.c
│   ├── dfs_func.h
│   ├── dfs_func_pc.c
│   ├── gen_files.c
│   ├── test_append.c
│   ├── test_append.sh
│   ├── test_concurrent.c
│   ├── test_concurrent.sh
│   ├── test_delete.c
│   ├── test_delete.sh
│   ├── test_download.c
│   ├── test_download.sh
│   ├── test_file_exist.c
│   ├── test_file_exist.sh
│   ├── test_fileinfo.c
│   ├── test_fileinfo.sh
│   ├── test_metadata.c
│   ├── test_metadata.sh
│   ├── test_modify.c
│   ├── test_modify.sh
│   ├── test_range_download.c
│   ├── test_range_download.sh
│   ├── test_slave.c
│   ├── test_slave.sh
│   ├── test_truncate.c
│   ├── test_truncate.sh
│   ├── test_types.h
│   ├── test_upload.c
│   ├── test_upload.sh
│   └── unit_tests/
│       ├── Makefile
│       └── test_client_api.c
├── tools/
│   ├── Makefile
│   ├── fdfs_analyze.c
│   ├── fdfs_backup.c
│   ├── fdfs_batch_delete.c
│   ├── fdfs_benchmark.c
│   ├── fdfs_capacity_plan.c
│   ├── fdfs_capacity_planner.c
│   ├── fdfs_capacity_planner.h
│   ├── fdfs_capacity_report.c
│   ├── fdfs_cleanup.c
│   ├── fdfs_cluster_mgr.c
│   ├── fdfs_compress.c
│   ├── fdfs_config_compare.c
│   ├── fdfs_config_generator.c
│   ├── fdfs_config_validator.c
│   ├── fdfs_config_validator.h
│   ├── fdfs_dedup.c
│   ├── fdfs_export.c
│   ├── fdfs_file_migrate.c
│   ├── fdfs_file_verify.c
│   ├── fdfs_health_check.c
│   ├── fdfs_import.c
│   ├── fdfs_load_balancer.c
│   ├── fdfs_log_analyzer.c
│   ├── fdfs_metadata_bulk.c
│   ├── fdfs_network_diag.c
│   ├── fdfs_network_diag.h
│   ├── fdfs_network_monitor.c
│   ├── fdfs_profiler.c
│   ├── fdfs_quota.c
│   ├── fdfs_rebalance.c
│   ├── fdfs_recover.c
│   ├── fdfs_repair.c
│   ├── fdfs_replication.c
│   ├── fdfs_replication_status.c
│   ├── fdfs_restore.c
│   ├── fdfs_search.c
│   ├── fdfs_snapshot.c
│   ├── fdfs_storage_stat.c
│   ├── fdfs_sync_check.c
│   └── fdfs_tag.c
├── tracker/
│   ├── Makefile.in
│   ├── fdfs_server_id_func.c
│   ├── fdfs_server_id_func.h
│   ├── fdfs_shared_func.c
│   ├── fdfs_shared_func.h
│   ├── fdfs_trackerd.c
│   ├── tracker_dump.c
│   ├── tracker_dump.h
│   ├── tracker_func.c
│   ├── tracker_func.h
│   ├── tracker_global.c
│   ├── tracker_global.h
│   ├── tracker_mem.c
│   ├── tracker_mem.h
│   ├── tracker_proto.c
│   ├── tracker_proto.h
│   ├── tracker_relationship.c
│   ├── tracker_relationship.h
│   ├── tracker_service.c
│   ├── tracker_service.h
│   ├── tracker_status.c
│   ├── tracker_status.h
│   └── tracker_types.h
└── typescript_client/
    ├── .eslintrc.js
    ├── .gitignore
    ├── .prettierrc
    ├── LICENSE
    ├── README.md
    ├── examples/
    │   ├── appender-example.ts
    │   ├── basic-usage.ts
    │   └── metadata-example.ts
    ├── jest.config.js
    ├── package.json
    ├── src/
    │   ├── client.ts
    │   ├── connection.ts
    │   ├── errors.ts
    │   ├── index.ts
    │   ├── operations.ts
    │   ├── protocol.ts
    │   └── types.ts
    ├── tests/
    │   ├── client.test.ts
    │   ├── connection.test.ts
    │   ├── integration.test.ts
    │   └── protocol.test.ts
    ├── tsconfig.build.json
    └── tsconfig.json
Download .txt
Showing preview only (319K chars total). Download the full file or copy to clipboard to get everything.
SYMBOL INDEX (3425 symbols across 303 files)

FILE: benchmarks/benchmark_concurrent.c
  type operation_type_t (line 23) | typedef enum {
  type uploaded_file_t (line 29) | typedef struct {
  type user_context_t (line 34) | typedef struct {
  function get_time_us (line 84) | static double get_time_us() {
  function add_to_file_pool (line 109) | static void add_to_file_pool(const char *group_name, const char *remote_...
  function get_random_file (line 126) | static int get_random_file(char *group_name, char *remote_filename) {
  function remove_from_file_pool (line 145) | static void remove_from_file_pool(const char *group_name, const char *re...
  function operation_type_t (line 166) | static operation_type_t select_operation(int upload_ratio, int download_...
  function perform_upload (line 182) | static int perform_upload(user_context_t *ctx, char *file_data) {
  function perform_download (line 202) | static int perform_download(user_context_t *ctx) {
  function perform_delete (line 228) | static int perform_delete(user_context_t *ctx) {
  function signal_handler (line 329) | static void signal_handler(int signum) {
  function print_results (line 336) | static void print_results(double duration) {
  function print_usage (line 389) | static void print_usage(const char *program) {
  function main (line 405) | int main(int argc, char *argv[]) {

FILE: benchmarks/benchmark_download.c
  type file_info_t (line 23) | typedef struct {
  type thread_context_t (line 29) | typedef struct {
  type latency_stats_t (line 45) | typedef struct {
  function get_time_us (line 87) | static double get_time_us() {
  function prepare_test_files (line 112) | static int prepare_test_files() {
  function load_file_list (line 165) | static int load_file_list(const char *filename) {
  function compare_double (line 227) | static int compare_double(const void *a, const void *b) {
  function calculate_latency_stats (line 235) | static void calculate_latency_stats(double *latencies, int count, latenc...
  function print_results (line 351) | static void print_results(double total_time, latency_stats_t *stats) {
  function print_usage (line 396) | static void print_usage(const char *program) {
  function main (line 413) | int main(int argc, char *argv[]) {

FILE: benchmarks/benchmark_large_files.c
  type thread_context_t (line 21) | typedef struct {
  function get_time_us (line 54) | static double get_time_us() {
  function compare_double (line 82) | static int compare_double(const void *a, const void *b) {
  function print_results (line 171) | static void print_results(double total_time, double *all_latencies, int ...
  function print_usage (line 229) | static void print_usage(const char *program) {
  function main (line 244) | int main(int argc, char *argv[]) {

FILE: benchmarks/benchmark_metadata.c
  type file_info_t (line 21) | typedef struct {
  type thread_context_t (line 26) | typedef struct {
  function get_time_us (line 77) | static double get_time_us() {
  function prepare_test_files (line 99) | static int prepare_test_files() {
  function compare_double (line 160) | static int compare_double(const void *a, const void *b) {
  function perform_query (line 168) | static int perform_query(file_info_t *file, double *latency) {
  function perform_update (line 189) | static int perform_update(file_info_t *file, double *latency) {
  function perform_delete (line 208) | static int perform_delete(file_info_t *file, double *latency) {
  function print_latency_stats (line 304) | static void print_latency_stats(const char *op_name, double *latencies, ...
  function print_results (line 332) | static void print_results(double total_time, thread_context_t *contexts) {
  function print_usage (line 406) | static void print_usage(const char *program) {
  function main (line 421) | int main(int argc, char *argv[]) {

FILE: benchmarks/benchmark_small_files.c
  type thread_context_t (line 21) | typedef struct {
  function get_time_us (line 54) | static double get_time_us() {
  function compare_double (line 76) | static int compare_double(const void *a, const void *b) {
  function print_results (line 154) | static void print_results(double total_time, double *all_latencies, int ...
  function print_usage (line 203) | static void print_usage(const char *program) {
  function main (line 218) | int main(int argc, char *argv[]) {

FILE: benchmarks/benchmark_upload.c
  type thread_context_t (line 23) | typedef struct {
  type latency_stats_t (line 38) | typedef struct {
  function get_time_us (line 74) | static double get_time_us() {
  function compare_double (line 99) | static int compare_double(const void *a, const void *b) {
  function calculate_latency_stats (line 107) | static void calculate_latency_stats(double *latencies, int count, latenc...
  function run_warmup (line 232) | static void run_warmup() {
  function print_results (line 262) | static void print_results(double total_time, latency_stats_t *stats) {
  function print_usage (line 307) | static void print_usage(const char *program) {
  function main (line 323) | int main(int argc, char *argv[]) {

FILE: benchmarks/scripts/compare_versions.py
  function load_results (line 14) | def load_results(filepath):
  function calculate_change (line 27) | def calculate_change(baseline, current):
  function format_change (line 34) | def format_change(change):
  function compare_metrics (line 44) | def compare_metrics(baseline_metrics, current_metrics, metric_name):
  function compare_benchmark (line 58) | def compare_benchmark(baseline_data, current_data, bench_name):
  function generate_html_comparison (line 126) | def generate_html_comparison(baseline, current, output_file):
  function main (line 311) | def main():

FILE: benchmarks/scripts/generate_report.py
  function load_results (line 224) | def load_results(input_file):
  function format_bytes (line 237) | def format_bytes(bytes_val):
  function format_number (line 246) | def format_number(num):
  function create_metric_card (line 251) | def create_metric_card(label, value, unit="", card_type="info"):
  function create_progress_bar (line 261) | def create_progress_bar(label, percentage):
  function create_latency_table (line 275) | def create_latency_table(latency_data):
  function generate_upload_section (line 311) | def generate_upload_section(data):
  function generate_download_section (line 381) | def generate_download_section(data):
  function generate_concurrent_section (line 433) | def generate_concurrent_section(data):
  function generate_small_files_section (line 498) | def generate_small_files_section(data):
  function generate_large_files_section (line 550) | def generate_large_files_section(data):
  function generate_metadata_section (line 602) | def generate_metadata_section(data):
  function generate_report (line 655) | def generate_report(results, output_file):
  function main (line 742) | def main():

FILE: cli/fdfs_cli.c
  type CLIConfig (line 38) | typedef struct {
  function print_colored (line 68) | static void print_colored(const char *color, const char *fmt, ...) {
  function print_progress (line 82) | static void print_progress(int64_t cur, int64_t total, const char *label) {
  type tm (line 125) | struct tm
  function print_json (line 131) | static void print_json(const char *op, int res, const char *fid, const c...
  function cmd_upload (line 143) | static int cmd_upload(int argc, char *argv[]) {
  function cmd_download (line 229) | static int cmd_download(int argc, char *argv[]) {
  function cmd_delete (line 294) | static int cmd_delete(int argc, char *argv[]) {
  function cmd_info (line 372) | static int cmd_info(int argc, char *argv[]) {
  function cmd_batch (line 434) | static int cmd_batch(int argc, char *argv[]) {
  function cmd_interactive (line 513) | static int cmd_interactive(void) {
  function usage (line 573) | static void usage(char *argv[]) {
  function main (line 598) | int main(int argc, char *argv[]) {

FILE: client/client_func.c
  function storage_cmp_by_ip_and_port (line 35) | static int storage_cmp_by_ip_and_port(const void *p1, const void *p2)
  function storage_cmp_server_info (line 50) | static int storage_cmp_server_info(const void *p1, const void *p2)
  function insert_into_sorted_servers (line 86) | static void insert_into_sorted_servers(TrackerServerGroup *pTrackerGroup, \
  function copy_tracker_servers (line 106) | static int copy_tracker_servers(TrackerServerGroup *pTrackerGroup,
  function fdfs_check_tracker_group (line 153) | static int fdfs_check_tracker_group(TrackerServerGroup *pTrackerGroup,
  function fdfs_load_tracker_group_ex (line 177) | int fdfs_load_tracker_group_ex(TrackerServerGroup *pTrackerGroup,
  function fdfs_load_tracker_group (line 216) | int fdfs_load_tracker_group(TrackerServerGroup *pTrackerGroup,
  function fdfs_get_params_from_tracker (line 237) | static int fdfs_get_params_from_tracker(bool *use_storage_id)
  function fdfs_client_do_init_ex (line 263) | static int fdfs_client_do_init_ex(TrackerServerGroup *pTrackerGroup, \
  function fdfs_client_init_from_buffer_ex (line 420) | int fdfs_client_init_from_buffer_ex(TrackerServerGroup *pTrackerGroup, \
  function fdfs_client_init_ex (line 450) | int fdfs_client_init_ex(TrackerServerGroup *pTrackerGroup, \
  function fdfs_copy_tracker_group (line 470) | int fdfs_copy_tracker_group(TrackerServerGroup *pDestTrackerGroup, \
  function fdfs_tracker_group_equals (line 502) | bool fdfs_tracker_group_equals(TrackerServerGroup *pGroup1,
  function fdfs_client_destroy_ex (line 531) | void fdfs_client_destroy_ex(TrackerServerGroup *pTrackerGroup)

FILE: client/client_func.h
  type FDFSFileInfo (line 21) | typedef struct {
  function fdfs_combine_file_id (line 146) | static inline int fdfs_combine_file_id(const char *group_name,

FILE: client/client_global.h
  type FDFSConnectFirstBy (line 18) | typedef enum {

FILE: client/fdfs_append_file.c
  function main (line 19) | int main(int argc, char *argv[])

FILE: client/fdfs_appender_test.c
  function writeToFileCallback (line 23) | int writeToFileCallback(void *arg, const int64_t file_size, const char *...
  function uploadFileCallback (line 39) | int uploadFileCallback(void *arg, const int64_t file_size, int sock)
  function main (line 54) | int main(int argc, char *argv[])

FILE: client/fdfs_appender_test1.c
  function writeToFileCallback (line 23) | int writeToFileCallback(void *arg, const int64_t file_size, const char *...
  function uploadFileCallback (line 39) | int uploadFileCallback(void *arg, const int64_t file_size, int sock)
  function main (line 54) | int main(int argc, char *argv[])

FILE: client/fdfs_bulk_import.c
  type BulkImportOptions (line 29) | typedef struct {
  function usage (line 43) | static void usage(const char *program_name)
  function parse_import_mode (line 71) | static int parse_import_mode(const char *mode_str)
  function parse_options (line 82) | static int parse_options(int argc, char *argv[], BulkImportOptions *opti...
  function write_output_mapping (line 179) | static int write_output_mapping(FILE *fp, const BulkImportFileInfo *file...
  function import_single_file (line 197) | static int import_single_file(BulkImportContext *context,
  function import_directory_recursive (line 243) | static int import_directory_recursive(BulkImportContext *context,
  function print_summary (line 289) | static void print_summary(const BulkImportContext *context, const BulkIm...
  function main (line 314) | int main(int argc, char *argv[])

FILE: client/fdfs_crc32.c
  function main (line 19) | int main(int argc, char *argv[])

FILE: client/fdfs_delete_file.c
  function main (line 19) | int main(int argc, char *argv[])

FILE: client/fdfs_download_file.c
  function main (line 19) | int main(int argc, char *argv[])

FILE: client/fdfs_file_info.c
  function usage (line 19) | static void usage(const char *program)
  function main (line 29) | int main(int argc, char *argv[])

FILE: client/fdfs_monitor.c
  function usage (line 30) | static void usage(char *argv[])
  function main (line 39) | int main(int argc, char *argv[])
  function list_storages (line 285) | static int list_storages(FDFSGroupStat *pGroupStat)
  function list_all_groups (line 625) | static int list_all_groups(const char *group_name)

FILE: client/fdfs_regenerate_filename.c
  function main (line 19) | int main(int argc, char *argv[])

FILE: client/fdfs_test.c
  function writeToFileCallback (line 23) | int writeToFileCallback(void *arg, const int64_t file_size, const char *...
  function uploadFileCallback (line 39) | int uploadFileCallback(void *arg, const int64_t file_size, int sock)
  function main (line 54) | int main(int argc, char *argv[])

FILE: client/fdfs_test1.c
  function writeToFileCallback (line 23) | int writeToFileCallback(void *arg, const int64_t file_size, const char *...
  function uploadFileCallback (line 39) | int uploadFileCallback(void *arg, const int64_t file_size, int sock)
  function main (line 53) | int main(int argc, char *argv[])

FILE: client/fdfs_upload_appender.c
  function main (line 18) | int main(int argc, char *argv[])

FILE: client/fdfs_upload_file.c
  function usage (line 19) | static void usage(char *argv[])
  function main (line 25) | int main(int argc, char *argv[])

FILE: client/storage_client.c
  function ConnectionInfo (line 50) | static ConnectionInfo *make_connection_by_tracker(
  function ConnectionInfo (line 88) | static ConnectionInfo *make_connection_by_last_connected(
  function ConnectionInfo (line 134) | static inline ConnectionInfo *storage_make_connection(
  function ConnectionInfo (line 157) | static ConnectionInfo *storage_make_connection_with_retry(
  function storage_get_connection (line 231) | static int storage_get_connection(ConnectionInfo *pTrackerServer, \
  function storage_get_upload_connection (line 291) | static int storage_get_upload_connection(ConnectionInfo *pTrackerServer, \
  function storage_get_metadata1 (line 354) | int storage_get_metadata1(ConnectionInfo *pTrackerServer, \
  function storage_get_metadata (line 365) | int storage_get_metadata(ConnectionInfo *pTrackerServer, \
  function storage_query_file_info_ex1 (line 454) | int storage_query_file_info_ex1(ConnectionInfo *pTrackerServer, \
  function storage_query_file_info_ex (line 463) | int storage_query_file_info_ex(ConnectionInfo *pTrackerServer,
  function storage_delete_file1 (line 589) | int storage_delete_file1(ConnectionInfo *pTrackerServer, \
  function storage_truncate_file1 (line 599) | int storage_truncate_file1(ConnectionInfo *pTrackerServer, \
  function storage_delete_file (line 611) | int storage_delete_file(ConnectionInfo *pTrackerServer, \
  function storage_do_download_file1_ex (line 681) | int storage_do_download_file1_ex(ConnectionInfo *pTrackerServer, \
  function storage_do_download_file_ex (line 694) | int storage_do_download_file_ex(ConnectionInfo *pTrackerServer, \
  function storage_download_file_to_file1 (line 855) | int storage_download_file_to_file1(ConnectionInfo *pTrackerServer, \
  function storage_download_file_to_file (line 867) | int storage_download_file_to_file(ConnectionInfo *pTrackerServer, \
  function storage_upload_by_filename1_ex (line 879) | int storage_upload_by_filename1_ex(ConnectionInfo *pTrackerServer, \
  function storage_do_upload_file1 (line 915) | int storage_do_upload_file1(ConnectionInfo *pTrackerServer, \
  function storage_do_upload_file (line 967) | int storage_do_upload_file(ConnectionInfo *pTrackerServer, \
  function storage_upload_by_callback_ex (line 1200) | int storage_upload_by_callback_ex(ConnectionInfo *pTrackerServer, \
  function storage_upload_by_callback1_ex (line 1214) | int storage_upload_by_callback1_ex(ConnectionInfo *pTrackerServer, \
  function storage_upload_by_filename_ex (line 1252) | int storage_upload_by_filename_ex(ConnectionInfo *pTrackerServer, \
  function storage_set_metadata1 (line 1286) | int storage_set_metadata1(ConnectionInfo *pTrackerServer, \
  function storage_set_metadata (line 1310) | int storage_set_metadata(ConnectionInfo *pTrackerServer, \
  function storage_download_file_ex1 (line 1430) | int storage_download_file_ex1(ConnectionInfo *pTrackerServer, \
  function storage_download_file_ex (line 1443) | int storage_download_file_ex(ConnectionInfo *pTrackerServer, \
  function tracker_query_storage_fetch1 (line 1456) | int tracker_query_storage_fetch1(ConnectionInfo *pTrackerServer, \
  function tracker_query_storage_update1 (line 1466) | int tracker_query_storage_update1(ConnectionInfo *pTrackerServer, \
  function storage_client_create_link (line 1489) | int storage_client_create_link(ConnectionInfo *pTrackerServer, \
  function tracker_query_storage_list1 (line 1645) | int tracker_query_storage_list1(ConnectionInfo *pTrackerServer, \
  function storage_upload_slave_by_filename (line 1655) | int storage_upload_slave_by_filename(ConnectionInfo *pTrackerServer, \
  function storage_upload_slave_by_callback (line 1697) | int storage_upload_slave_by_callback(ConnectionInfo *pTrackerServer, \
  function storage_upload_slave_by_filebuff (line 1720) | int storage_upload_slave_by_filebuff(ConnectionInfo *pTrackerServer, \
  function storage_upload_slave_by_filename1 (line 1742) | int storage_upload_slave_by_filename1(ConnectionInfo *pTrackerServer, \
  function storage_upload_slave_by_filebuff1 (line 1773) | int storage_upload_slave_by_filebuff1(ConnectionInfo *pTrackerServer, \
  function storage_upload_slave_by_callback1 (line 1804) | int storage_upload_slave_by_callback1(ConnectionInfo *pTrackerServer, \
  function storage_do_append_file (line 1843) | int storage_do_append_file(ConnectionInfo *pTrackerServer, \
  function storage_do_modify_file (line 1973) | int storage_do_modify_file(ConnectionInfo *pTrackerServer, \
  function storage_append_by_filename (line 2097) | int storage_append_by_filename(ConnectionInfo *pTrackerServer, \
  function storage_append_by_callback (line 2123) | int storage_append_by_callback(ConnectionInfo *pTrackerServer, \
  function storage_append_by_filebuff (line 2139) | int storage_append_by_filebuff(ConnectionInfo *pTrackerServer, \
  function storage_append_by_filename1 (line 2155) | int storage_append_by_filename1(ConnectionInfo *pTrackerServer, \
  function storage_append_by_filebuff1 (line 2165) | int storage_append_by_filebuff1(ConnectionInfo *pTrackerServer, \
  function storage_append_by_callback1 (line 2176) | int storage_append_by_callback1(ConnectionInfo *pTrackerServer, \
  function storage_modify_by_filename (line 2188) | int storage_modify_by_filename(ConnectionInfo *pTrackerServer, \
  function storage_modify_by_callback (line 2216) | int storage_modify_by_callback(ConnectionInfo *pTrackerServer, \
  function storage_modify_by_filebuff (line 2233) | int storage_modify_by_filebuff(ConnectionInfo *pTrackerServer, \
  function storage_modify_by_filename1 (line 2249) | int storage_modify_by_filename1(ConnectionInfo *pTrackerServer, \
  function storage_modify_by_filebuff1 (line 2260) | int storage_modify_by_filebuff1(ConnectionInfo *pTrackerServer, \
  function storage_modify_by_callback1 (line 2272) | int storage_modify_by_callback1(ConnectionInfo *pTrackerServer, \
  function fdfs_get_file_info_ex1 (line 2285) | int fdfs_get_file_info_ex1(const char *file_id, const bool get_from_server,
  function fdfs_get_file_info_ex (line 2294) | int fdfs_get_file_info_ex(const char *group_name, const char *remote_fil...
  function storage_file_exist (line 2424) | int storage_file_exist(ConnectionInfo *pTrackerServer, \
  function storage_file_exist1 (line 2435) | int storage_file_exist1(ConnectionInfo *pTrackerServer, \
  function storage_truncate_file (line 2444) | int storage_truncate_file(ConnectionInfo *pTrackerServer, \
  function storage_regenerate_appender_filename (line 2530) | int storage_regenerate_appender_filename(ConnectionInfo *pTrackerServer,
  function storage_regenerate_appender_filename1 (line 2617) | int storage_regenerate_appender_filename1(ConnectionInfo *pTrackerServer,

FILE: client/tracker_client.c
  function tracker_get_all_connections_ex (line 29) | int tracker_get_all_connections_ex(TrackerServerGroup *pTrackerGroup)
  function tracker_close_all_connections_ex (line 51) | void tracker_close_all_connections_ex(TrackerServerGroup *pTrackerGroup)
  function ConnectionInfo (line 63) | ConnectionInfo *tracker_get_connection_ex(TrackerServerGroup *pTrackerGr...
  function ConnectionInfo (line 122) | ConnectionInfo *tracker_get_connection_no_pool(TrackerServerGroup *pTrac...
  function ConnectionInfo (line 180) | ConnectionInfo *tracker_get_connection_r_ex(TrackerServerGroup *pTracker...
  function decode_storage_stat (line 245) | static void decode_storage_stat(FDFSStorageStatBuff *pStatBuff,
  function tracker_list_servers (line 363) | int tracker_list_servers(ConnectionInfo *pTrackerServer,
  function tracker_list_one_group (line 508) | int tracker_list_one_group(ConnectionInfo *pTrackerServer, \
  function tracker_list_groups (line 588) | int tracker_list_groups(ConnectionInfo *pTrackerServer,
  function tracker_do_query_storage (line 698) | int tracker_do_query_storage(ConnectionInfo *pTrackerServer,
  function tracker_query_storage_list (line 787) | int tracker_query_storage_list(ConnectionInfo *pTrackerServer,
  function tracker_query_storage_store_without_group (line 906) | int tracker_query_storage_store_without_group(ConnectionInfo *pTrackerSe...
  function tracker_query_storage_store_with_group (line 994) | int tracker_query_storage_store_with_group(ConnectionInfo *pTrackerServe...
  function tracker_query_storage_store_list_with_group (line 1084) | int tracker_query_storage_store_list_with_group(
  function tracker_delete_storage (line 1228) | int tracker_delete_storage(TrackerServerGroup *pTrackerGroup, \
  function tracker_delete_group (line 1350) | int tracker_delete_group(TrackerServerGroup *pTrackerGroup, \
  function tracker_set_trunk_server (line 1409) | int tracker_set_trunk_server(TrackerServerGroup *pTrackerGroup, \
  function tracker_get_storage_status (line 1509) | int tracker_get_storage_status(ConnectionInfo *pTrackerServer,
  function tracker_get_storage_id (line 1593) | int tracker_get_storage_id(ConnectionInfo *pTrackerServer, \
  function tracker_get_storage_max_status (line 1681) | int tracker_get_storage_max_status(TrackerServerGroup *pTrackerGroup, \

FILE: client/tracker_client.h
  type FDFSStorageInfo (line 20) | typedef struct

FILE: common/fdfs_global.c
  type base64_context (line 27) | struct base64_context
  function fdfs_check_data_filename (line 33) | int fdfs_check_data_filename(const char *filename, const int len)
  function fdfs_gen_slave_filename (line 65) | int fdfs_gen_slave_filename(const char *master_filename, \

FILE: common/fdfs_global.h
  type base64_context (line 30) | struct base64_context

FILE: common/fdfs_http_shared.c
  function fdfs_http_get_content_type_by_extname (line 59) | int fdfs_http_get_content_type_by_extname(FDFSHTTPParams *pParams, \
  function fdfs_http_params_load (line 100) | int fdfs_http_params_load(IniContext *pIniContext, \
  function fdfs_http_params_destroy (line 298) | void fdfs_http_params_destroy(FDFSHTTPParams *pParams)
  function fdfs_http_gen_token (line 306) | int fdfs_http_gen_token(const BufferInfo *secret_key, const char *file_id,
  function fdfs_http_check_token (line 331) | int fdfs_http_check_token(const BufferInfo *secret_key, const char *file...

FILE: common/fdfs_http_shared.h
  type FDFSHTTPParams (line 20) | typedef struct

FILE: common/mime_file_parser.c
  function load_mime_types_from_file (line 26) | int load_mime_types_from_file(HashArray *pHash, const char *mime_filename)

FILE: cpp_client/examples/advanced_metadata_example.cpp
  function print_metadata (line 35) | void print_metadata(const fastdfs::Metadata& metadata, const std::string...
  function merge_metadata (line 48) | fastdfs::Metadata merge_metadata(const fastdfs::Metadata& existing,
  function filter_metadata_by_prefix (line 58) | fastdfs::Metadata filter_metadata_by_prefix(const fastdfs::Metadata& met...
  function metadata_matches (line 70) | bool metadata_matches(const fastdfs::Metadata& metadata,
  function get_timestamp (line 82) | std::string get_timestamp() {
  function increment_version (line 91) | std::string increment_version(const std::string& version) {
  function main (line 103) | int main(int argc, char* argv[]) {

FILE: cpp_client/examples/appender_example.cpp
  function main (line 11) | int main(int argc, char* argv[]) {

FILE: cpp_client/examples/basic_usage.cpp
  function main (line 12) | int main(int argc, char* argv[]) {

FILE: cpp_client/examples/batch_operations_example.cpp
  type BatchResult (line 35) | struct BatchResult {
  type ProgressTracker (line 43) | struct ProgressTracker {
    method update (line 50) | void update(bool success) {
    method print_progress (line 60) | void print_progress() {
  function main (line 69) | int main(int argc, char* argv[]) {

FILE: cpp_client/examples/cancellation_example.cpp
  class CancellationToken (line 36) | class CancellationToken {
    method CancellationToken (line 38) | CancellationToken() : cancelled_(false) {}
    method cancel (line 40) | void cancel() {
    method is_cancelled (line 44) | bool is_cancelled() const {
    method reset (line 48) | void reset() {
  function create_test_file (line 57) | void create_test_file(const std::string& filename, int64_t size) {
  function format_duration (line 78) | std::string format_duration(std::chrono::milliseconds ms) {
  function main (line 86) | int main(int argc, char* argv[]) {

FILE: cpp_client/examples/concurrent_operations_example.cpp
  type OperationResult (line 34) | struct OperationResult {
  type Statistics (line 43) | struct Statistics {
    method record (line 50) | void record(bool success, std::chrono::milliseconds duration) {
    method print (line 61) | void print() {
  function main (line 75) | int main(int argc, char* argv[]) {

FILE: cpp_client/examples/configuration_example.cpp
  function parse_config_file (line 35) | std::map<std::string, std::string> parse_config_file(const std::string& ...
  function get_env (line 71) | std::string get_env(const std::string& key, const std::string& default_v...
  function parse_timeout (line 77) | std::chrono::milliseconds parse_timeout(const std::string& timeout_str) {
  function validate_config (line 109) | bool validate_config(const fastdfs::ClientConfig& config, std::string& e...
  function print_config (line 169) | void print_config(const fastdfs::ClientConfig& config, const std::string...
  function main (line 185) | int main(int argc, char* argv[]) {

FILE: cpp_client/examples/connection_pool_example.cpp
  type PoolPerformance (line 32) | struct PoolPerformance {
    method PoolPerformance (line 38) | PoolPerformance() : operations(0), total_time(0), successful(0), faile...
    method average_time (line 40) | double average_time() const {
    method success_rate (line 44) | double success_rate() const {
  function main (line 49) | int main(int argc, char* argv[]) {

FILE: cpp_client/examples/error_handling_example.cpp
  function log_error (line 31) | void log_error(const std::string& operation, const std::exception& e) {
  function retry_with_backoff (line 40) | auto retry_with_backoff(Func&& func, size_t max_retries = 3) -> decltype...
  function main (line 59) | int main(int argc, char* argv[]) {

FILE: cpp_client/examples/file_info_example.cpp
  function format_timestamp (line 38) | std::string format_timestamp(int64_t timestamp) {
  function calculate_file_age (line 47) | std::string calculate_file_age(int64_t create_time) {
  function format_file_size (line 64) | std::string format_file_size(int64_t size) {
  function main (line 80) | int main(int argc, char* argv[]) {

FILE: cpp_client/examples/metadata_example.cpp
  function main (line 11) | int main(int argc, char* argv[]) {

FILE: cpp_client/examples/partial_download_example.cpp
  function verify_data (line 32) | bool verify_data(const std::vector<uint8_t>& data, int64_t expected_offs...
  function format_data_preview (line 45) | std::string format_data_preview(const std::vector<uint8_t>& data, size_t...
  function main (line 59) | int main(int argc, char* argv[]) {

FILE: cpp_client/examples/performance_example.cpp
  type PerformanceMetrics (line 47) | struct PerformanceMetrics {
    method record_operation (line 57) | void record_operation(bool success, std::chrono::milliseconds duration...
    method print (line 71) | void print(const std::string& title) {
  type MemoryUsage (line 110) | struct MemoryUsage {
    method start (line 114) | void start() {
    method update (line 118) | void update() {
    method get_peak_delta (line 125) | size_t get_peak_delta() {
    method get_current_memory (line 130) | size_t get_current_memory() {
  function format_memory (line 148) | std::string format_memory(size_t bytes) {
  function create_test_data (line 164) | std::vector<uint8_t> create_test_data(size_t size) {
  function main (line 172) | int main(int argc, char* argv[]) {

FILE: cpp_client/examples/slave_file_example.cpp
  function main (line 27) | int main(int argc, char* argv[]) {

FILE: cpp_client/examples/streaming_example.cpp
  function format_size (line 39) | std::string format_size(int64_t bytes) {
  function print_progress (line 55) | void print_progress(int64_t current, int64_t total, double percentage) {
  function create_test_file (line 71) | void create_test_file(const std::string& filename, int64_t size) {
  function main (line 95) | int main(int argc, char* argv[]) {

FILE: cpp_client/examples/upload_buffer_example.cpp
  function generate_json_content (line 33) | std::string generate_json_content() {
  function generate_xml_content (line 51) | std::string generate_xml_content() {
  function generate_csv_content (line 74) | std::string generate_csv_content() {
  function generate_binary_content (line 85) | std::vector<uint8_t> generate_binary_content(size_t size) {
  function main (line 93) | int main(int argc, char* argv[]) {

FILE: cpp_client/include/fastdfs/client.hpp
  type fastdfs (line 17) | namespace fastdfs {
    class ClientImpl (line 20) | class ClientImpl
    class Client (line 40) | class Client {
      method Client (line 56) | Client(const Client&) = delete;
      method Client (line 57) | Client& operator=(const Client&) = delete;

FILE: cpp_client/include/fastdfs/errors.hpp
  type fastdfs (line 14) | namespace fastdfs {
    class FastDFSException (line 19) | class FastDFSException : public std::runtime_error {
      method FastDFSException (line 21) | explicit FastDFSException(const std::string& message)
    class FileNotFoundException (line 28) | class FileNotFoundException : public FastDFSException {
      method FileNotFoundException (line 30) | explicit FileNotFoundException(const std::string& message)
    class ConnectionException (line 37) | class ConnectionException : public FastDFSException {
      method ConnectionException (line 39) | explicit ConnectionException(const std::string& message)
    class TimeoutException (line 46) | class TimeoutException : public FastDFSException {
      method TimeoutException (line 48) | explicit TimeoutException(const std::string& message)
    class InvalidArgumentException (line 55) | class InvalidArgumentException : public FastDFSException {
      method InvalidArgumentException (line 57) | explicit InvalidArgumentException(const std::string& message)
    class ProtocolException (line 64) | class ProtocolException : public FastDFSException {
      method ProtocolException (line 66) | explicit ProtocolException(const std::string& message)
    class NoStorageServerException (line 73) | class NoStorageServerException : public FastDFSException {
      method NoStorageServerException (line 75) | explicit NoStorageServerException(const std::string& message)
    class ClientClosedException (line 82) | class ClientClosedException : public FastDFSException {
      method ClientClosedException (line 84) | ClientClosedException()

FILE: cpp_client/include/fastdfs/types.hpp
  type fastdfs (line 17) | namespace fastdfs {
    type TrackerCommand (line 41) | enum class TrackerCommand : uint8_t {
    type StorageCommand (line 61) | enum class StorageCommand : uint8_t {
    type MetadataFlag (line 76) | enum class MetadataFlag : uint8_t {
    type FileInfo (line 82) | struct FileInfo {
    type ClientConfig (line 93) | struct ClientConfig {

FILE: cpp_client/src/client.cpp
  type fastdfs (line 15) | namespace fastdfs {
    class ClientImpl (line 17) | class ClientImpl {
      method ClientImpl (line 19) | ClientImpl(const ClientConfig& config)
      method close (line 34) | void close() {
      method is_closed (line 44) | bool is_closed() const {
      method check_closed (line 49) | void check_closed() const {
      method upload_file (line 55) | std::string upload_file(const std::string& local_filename,
      method upload_buffer (line 61) | std::string upload_buffer(const std::vector<uint8_t>& data,
      method upload_appender_file (line 68) | std::string upload_appender_file(const std::string& local_filename,
      method upload_appender_buffer (line 74) | std::string upload_appender_buffer(const std::vector<uint8_t>& data,
      method upload_slave_file (line 81) | std::string upload_slave_file(const std::string& master_file_id,
      method download_file (line 91) | std::vector<uint8_t> download_file(const std::string& file_id) {
      method download_file_range (line 96) | std::vector<uint8_t> download_file_range(const std::string& file_id,
      method download_to_file (line 103) | void download_to_file(const std::string& file_id,
      method delete_file (line 109) | void delete_file(const std::string& file_id) {
      method append_file (line 114) | void append_file(const std::string& file_id,
      method modify_file (line 120) | void modify_file(const std::string& file_id,
      method truncate_file (line 127) | void truncate_file(const std::string& file_id, int64_t size) {
      method set_metadata (line 132) | void set_metadata(const std::string& file_id,
      method Metadata (line 139) | Metadata get_metadata(const std::string& file_id) {
      method FileInfo (line 144) | FileInfo get_file_info(const std::string& file_id) {
      method file_exists (line 149) | bool file_exists(const std::string& file_id) {
    function Metadata (line 260) | Metadata Client::get_metadata(const std::string& file_id) {
    function FileInfo (line 264) | FileInfo Client::get_file_info(const std::string& file_id) {

FILE: cpp_client/src/internal/connection.cpp
  type fastdfs (line 27) | namespace fastdfs {
    type internal (line 28) | namespace internal {
      function Connection (line 53) | Connection& Connection::operator=(Connection&& other) noexcept {

FILE: cpp_client/src/internal/connection.hpp
  type fastdfs (line 16) | namespace fastdfs {
    type internal (line 17) | namespace internal {
      class Connection (line 22) | class Connection {
        method Connection (line 30) | Connection(const Connection&) = delete;
        method Connection (line 31) | Connection& operator=(const Connection&) = delete;
        method last_used (line 70) | std::chrono::steady_clock::time_point last_used() const { return l...

FILE: cpp_client/src/internal/connection_pool.cpp
  type fastdfs (line 13) | namespace fastdfs {
    type internal (line 14) | namespace internal {
      function ConnectionPool (line 42) | ConnectionPool& ConnectionPool::operator=(ConnectionPool&& other) no...

FILE: cpp_client/src/internal/connection_pool.hpp
  type fastdfs (line 18) | namespace fastdfs {
    type internal (line 19) | namespace internal {
      class Connection (line 21) | class Connection
      class ConnectionPool (line 26) | class ConnectionPool {
        method ConnectionPool (line 36) | ConnectionPool(const ConnectionPool&) = delete;
        method ConnectionPool (line 37) | ConnectionPool& operator=(const ConnectionPool&) = delete;

FILE: cpp_client/src/internal/operations.cpp
  type fastdfs (line 19) | namespace fastdfs {
    type internal (line 20) | namespace internal {
      function pad_string (line 32) | static std::string pad_string(const std::string& str, size_t len) {
      function unpad_string (line 41) | static std::string unpad_string(const std::vector<uint8_t>& data) {
      function get_file_ext_name (line 52) | static std::string get_file_ext_name(const std::string& filename) {
      function read_file_content (line 60) | static std::vector<uint8_t> read_file_content(const std::string& fil...
      function Metadata (line 633) | Metadata Operations::get_metadata(const std::string& file_id) {
      function FileInfo (line 676) | FileInfo Operations::get_file_info(const std::string& file_id) {

FILE: cpp_client/src/internal/operations.hpp
  type fastdfs (line 17) | namespace fastdfs {
    type internal (line 18) | namespace internal {
      class Operations (line 23) | class Operations {
        type StorageServer (line 77) | struct StorageServer {

FILE: cpp_client/src/internal/protocol.cpp
  type fastdfs (line 14) | namespace fastdfs {
    type internal (line 15) | namespace internal {
      function encode_header (line 17) | std::vector<uint8_t> encode_header(int64_t length, uint8_t cmd, uint...
      function ProtocolHeader (line 32) | ProtocolHeader decode_header(const std::vector<uint8_t>& data) {
      function split_file_id (line 51) | void split_file_id(const std::string& file_id,
      function join_file_id (line 75) | std::string join_file_id(const std::string& group_name,
      function encode_metadata (line 80) | std::vector<uint8_t> encode_metadata(const Metadata& metadata) {
      function Metadata (line 109) | Metadata decode_metadata(const std::vector<uint8_t>& data) {

FILE: cpp_client/src/internal/protocol.hpp
  type fastdfs (line 16) | namespace fastdfs {
    type internal (line 17) | namespace internal {
      type ProtocolHeader (line 22) | struct ProtocolHeader {

FILE: csharp_client/ConnectionPool.cs
  class ConnectionPool (line 35) | internal class ConnectionPool : IDisposable
    method ConnectionPool (line 115) | public ConnectionPool(
    method GetConnectionAsync (line 164) | public async Task<PooledConnection> GetConnectionAsync(
    method ReturnConnection (line 222) | public void ReturnConnection(PooledConnection connection)
    method CreateConnectionAsync (line 268) | private async Task<PooledConnection> CreateConnectionAsync(
    method IsConnectionValid (line 316) | private bool IsConnectionValid(PooledConnection connection)
    method CleanupIdleConnections (line 338) | private void CleanupIdleConnections(object state)
    method ThrowIfDisposed (line 396) | private void ThrowIfDisposed()
    method Dispose (line 411) | public void Dispose()
    method Dispose (line 420) | protected virtual void Dispose(bool disposing)
  class PooledConnection (line 457) | internal class PooledConnection : IDisposable
    method Dispose (line 482) | public void Dispose()

FILE: csharp_client/FastDFSClient.cs
  class FastDFSClient (line 59) | public class FastDFSClient : IDisposable
    method FastDFSClient (line 131) | public FastDFSClient(FastDFSClientConfig config)
    method UploadFileAsync (line 268) | public async Task<string> UploadFileAsync(
    method UploadBufferAsync (line 356) | public async Task<string> UploadBufferAsync(
    method DownloadFileAsync (line 488) | public async Task<byte[]> DownloadFileAsync(
    method DownloadFileRangeAsync (line 520) | public async Task<byte[]> DownloadFileRangeAsync(
    method DownloadToFileAsync (line 657) | public async Task DownloadToFileAsync(
    method DeleteFileAsync (line 728) | public async Task DeleteFileAsync(
    method GetFileInfoAsync (line 842) | public async Task<FileInfo> GetFileInfoAsync(
    method SetMetadataAsync (line 957) | public async Task SetMetadataAsync(
    method GetMetadataAsync (line 1095) | public async Task<Dictionary<string, string>> GetMetadataAsync(
    method UploadAppenderFileAsync (line 1220) | public async Task<string> UploadAppenderFileAsync(
    method UploadAppenderBufferAsync (line 1283) | public async Task<string> UploadAppenderBufferAsync(
    method AppendFileAsync (line 1319) | public async Task AppendFileAsync(
    method UploadSlaveFileAsync (line 1374) | public async Task<string> UploadSlaveFileAsync(
    method ThrowIfDisposed (line 1416) | private void ThrowIfDisposed()
    method GetStorageServerForUploadAsync (line 1441) | private async Task<StorageServer> GetStorageServerForUploadAsync(
    method GetStorageServerForDownloadAsync (line 1476) | private async Task<StorageServer> GetStorageServerForDownloadAsync(
    method GetStorageServerForUpdateAsync (line 1489) | private async Task<StorageServer> GetStorageServerForUpdateAsync(
    method ParseFileId (line 1510) | private FileIdParts ParseFileId(string fileId)
    method Dispose (line 1541) | public void Dispose()
    method Dispose (line 1553) | protected virtual void Dispose(bool disposing)
  class FileIdParts (line 1584) | internal class FileIdParts

FILE: csharp_client/FastDFSClientConfig.cs
  class FastDFSClientConfig (line 41) | public class FastDFSClientConfig
    method FastDFSClientConfig (line 359) | public FastDFSClientConfig()
    method FastDFSClientConfig (line 379) | public FastDFSClientConfig(string[] trackerAddresses)
    method Validate (line 399) | public void Validate()
    method Clone (line 452) | public FastDFSClientConfig Clone()

FILE: csharp_client/FastDFSConstants.cs
  class FastDFSConstants (line 32) | public static class FastDFSConstants
    method GetStorageStatusDescription (line 439) | public static string GetStorageStatusDescription(byte status)

FILE: csharp_client/FastDFSErrors.cs
  class FastDFSException (line 29) | public class FastDFSException : Exception
    method FastDFSException (line 42) | public FastDFSException()
    method FastDFSException (line 54) | public FastDFSException(string message)
    method FastDFSException (line 71) | public FastDFSException(string message, Exception innerException)
    method FastDFSException (line 90) | public FastDFSException(string message, byte errorCode, Exception inne...
  class FastDFSProtocolException (line 105) | public class FastDFSProtocolException : FastDFSException
    method FastDFSProtocolException (line 111) | public FastDFSProtocolException()
    method FastDFSProtocolException (line 123) | public FastDFSProtocolException(string message)
    method FastDFSProtocolException (line 139) | public FastDFSProtocolException(string message, Exception innerException)
  class FastDFSNetworkException (line 153) | public class FastDFSNetworkException : FastDFSException
    method FastDFSNetworkException (line 178) | public FastDFSNetworkException(string operation, string address, Excep...
  class FastDFSFileNotFoundException (line 193) | public class FastDFSFileNotFoundException : FastDFSException
    method FastDFSFileNotFoundException (line 207) | public FastDFSFileNotFoundException(string fileId)
    method FastDFSFileNotFoundException (line 224) | public FastDFSFileNotFoundException(string fileId, Exception innerExce...
  class FastDFSNoStorageServerException (line 239) | public class FastDFSNoStorageServerException : FastDFSException
    method FastDFSNoStorageServerException (line 250) | public FastDFSNoStorageServerException()
    method FastDFSNoStorageServerException (line 262) | public FastDFSNoStorageServerException(string groupName)
  class FastDFSConnectionTimeoutException (line 276) | public class FastDFSConnectionTimeoutException : FastDFSNetworkException
    method FastDFSConnectionTimeoutException (line 293) | public FastDFSConnectionTimeoutException(string address, TimeSpan time...
  class FastDFSNetworkTimeoutException (line 307) | public class FastDFSNetworkTimeoutException : FastDFSNetworkException
    method FastDFSNetworkTimeoutException (line 327) | public FastDFSNetworkTimeoutException(string operation, string address...

FILE: csharp_client/FastDFSTypes.cs
  type MetadataFlag (line 28) | public enum MetadataFlag : byte
  class FileInfo (line 52) | public class FileInfo
    method ToString (line 85) | public override string ToString()
  class StorageServer (line 98) | public class StorageServer
    method ToString (line 134) | public override string ToString()
  class GroupInfo (line 147) | public class GroupInfo
    method ToString (line 229) | public override string ToString()
  class StorageInfo (line 243) | public class StorageInfo
    method ToString (line 356) | public override string ToString()
  class ProtocolHeader (line 369) | public class ProtocolHeader
    method ToString (line 396) | public override string ToString()
  class UploadResponse (line 409) | public class UploadResponse
    method ToString (line 438) | public override string ToString()

FILE: csharp_client/ProtocolBuilder.cs
  class ProtocolBuilder (line 31) | internal static class ProtocolBuilder
    method BuildQueryStorageStoreRequest (line 46) | public static byte[] BuildQueryStorageStoreRequest(string groupName)
    method BuildQueryStorageFetchRequest (line 81) | public static byte[] BuildQueryStorageFetchRequest(string groupName, s...
    method BuildQueryStorageUpdateRequest (line 114) | public static byte[] BuildQueryStorageUpdateRequest(string groupName, ...
    method BuildUploadRequest (line 157) | public static byte[] BuildUploadRequest(
    method BuildDownloadRequest (line 231) | public static byte[] BuildDownloadRequest(
    method BuildDeleteRequest (line 284) | public static byte[] BuildDeleteRequest(string groupName, string remot...
    method BuildQueryFileInfoRequest (line 317) | public static byte[] BuildQueryFileInfoRequest(string groupName, strin...
    method BuildSetMetadataRequest (line 353) | public static byte[] BuildSetMetadataRequest(
    method BuildGetMetadataRequest (line 397) | public static byte[] BuildGetMetadataRequest(string groupName, string ...
    method BuildMessage (line 431) | private static byte[] BuildMessage(byte cmd, byte[] body)
    method EncodeMetadata (line 469) | private static byte[] EncodeMetadata(Dictionary<string, string> metadata)

FILE: csharp_client/ProtocolParser.cs
  class ProtocolParser (line 31) | internal static class ProtocolParser
    method ParseHeader (line 49) | public static ProtocolHeader ParseHeader(byte[] data)
    method ParseStorageServerResponse (line 94) | public static StorageServer ParseStorageServerResponse(byte[] data)
    method ParseUploadResponse (line 158) | public static string ParseUploadResponse(byte[] data)
    method ParseFileInfoResponse (line 199) | public static FileInfo ParseFileInfoResponse(byte[] data)
    method ParseMetadata (line 270) | public static Dictionary<string, string> ParseMetadata(byte[] data)

FILE: csharp_client/examples/AdvancedMetadataExample.cs
  class AdvancedMetadataExample (line 50) | class AdvancedMetadataExample
    method Main (line 65) | static async Task Main(string[] args)
    method ValidateMetadata (line 1197) | static ValidationResult ValidateMetadata(Dictionary<string, string> me...
    method ValidateFieldType (line 1251) | static bool ValidateFieldType(string value, MetadataFieldType expected...
    method ValidateFieldConstraint (line 1271) | static (bool IsValid, string ErrorMessage) ValidateFieldConstraint(str...
    method ProcessWorkflowStage (line 1305) | static string ProcessWorkflowStage(string currentStage, Dictionary<str...
    method RouteByPriority (line 1326) | static string RouteByPriority(string priority)
    method CalculateMetadataSize (line 1344) | static int CalculateMetadataSize(Dictionary<string, string> metadata)
  class MetadataSchema (line 1366) | class MetadataSchema
  type MetadataFieldType (line 1387) | enum MetadataFieldType
  class MetadataConstraint (line 1416) | class MetadataConstraint
  class ValidationResult (line 1440) | class ValidationResult

FILE: csharp_client/examples/AppenderFileExample.cs
  class AppenderFileExample (line 44) | class AppenderFileExample
    method Main (line 59) | static async Task Main(string[] args)

FILE: csharp_client/examples/BasicExample.cs
  class BasicExample (line 30) | class BasicExample
    method Main (line 41) | static async Task Main(string[] args)

FILE: csharp_client/examples/BatchOperationsExample.cs
  class BatchOperationsExample (line 52) | class BatchOperationsExample
    method Main (line 67) | static async Task Main(string[] args)
  class BatchUploadResult (line 1349) | class BatchUploadResult
  class BatchDownloadResult (line 1392) | class BatchDownloadResult

FILE: csharp_client/examples/CancellationExample.cs
  class CancellationExample (line 49) | class CancellationExample
    method Main (line 64) | static async Task Main(string[] args)

FILE: csharp_client/examples/ConcurrentOperationsExample.cs
  class ConcurrentOperationsExample (line 51) | class ConcurrentOperationsExample
    method Main (line 66) | static async Task Main(string[] args)

FILE: csharp_client/examples/ConfigurationExample.cs
  class ConfigurationExample (line 49) | class ConfigurationExample
    method Main (line 64) | static async Task Main(string[] args)
    method CreateDevelopmentConfig (line 850) | static FastDFSClientConfig CreateDevelopmentConfig()
    method CreateStagingConfig (line 881) | static FastDFSClientConfig CreateStagingConfig()
    method CreateProductionConfig (line 916) | static FastDFSClientConfig CreateProductionConfig()
    method CreateTestConfig (line 952) | static FastDFSClientConfig CreateTestConfig()
    method CreateConfigFromEnvironment (line 984) | static FastDFSClientConfig CreateConfigFromEnvironment()
    method CreateConfigFromFile (line 1029) | static FastDFSClientConfig CreateConfigFromFile()
    method GetCurrentLoadLevel (line 1103) | static double GetCurrentLoadLevel()
    method DisplayConfiguration (line 1122) | static void DisplayConfiguration(string name, FastDFSClientConfig config)

FILE: csharp_client/examples/ConnectionPoolExample.cs
  class ConnectionPoolExample (line 50) | class ConnectionPoolExample
    method Main (line 65) | static async Task Main(string[] args)

FILE: csharp_client/examples/ErrorHandlingExample.cs
  class ErrorHandlingExample (line 49) | class ErrorHandlingExample
    method Main (line 64) | static async Task Main(string[] args)
    method SimpleRetryWithFixedDelay (line 664) | static async Task SimpleRetryWithFixedDelay(FastDFSClient client, stri...
    method ExponentialBackoffRetry (line 719) | static async Task ExponentialBackoffRetry(FastDFSClient client, string...
    method RetryWithMaxAttempts (line 777) | static async Task RetryWithMaxAttempts(FastDFSClient client, string fi...
    method RetryWithCancellation (line 862) | static async Task RetryWithCancellation(FastDFSClient client, string f...
    method FallbackToAlternativeContent (line 926) | static async Task FallbackToAlternativeContent(FastDFSClient client, s...
    method GracefulDegradation (line 971) | static async Task GracefulDegradation(FastDFSClient client)
    method RetryWithDifferentParameters (line 1036) | static async Task RetryWithDifferentParameters(FastDFSClient client, s...

FILE: csharp_client/examples/FileInfoExample.cs
  class FileInfoExample (line 52) | class FileInfoExample
    method Main (line 67) | static async Task Main(string[] args)
    method CalculateCRC32 (line 1117) | static uint CalculateCRC32(byte[] data)
  class ValidationResult (line 1163) | class ValidationResult
  class AuditRecord (line 1188) | class AuditRecord
  class ComplianceCheck (line 1243) | class ComplianceCheck

FILE: csharp_client/examples/IntegrationExample.cs
  class IntegrationExample (line 53) | class IntegrationExample
    method Main (line 68) | static async Task Main(string[] args)
  class FastDFSOptions (line 1022) | public class FastDFSOptions
  type IFastDFSService (line 1061) | public interface IFastDFSService
    method UploadFileAsync (line 1066) | Task<string> UploadFileAsync(string localFilePath, Dictionary<string, ...
    method DownloadFileAsync (line 1071) | Task<byte[]> DownloadFileAsync(string fileId);
    method DeleteFileAsync (line 1076) | Task DeleteFileAsync(string fileId);
  class FastDFSService (line 1085) | public class FastDFSService : IFastDFSService
    method FastDFSService (line 1095) | public FastDFSService(FastDFSClient client, ILogger<FastDFSService> lo...
    method UploadFileAsync (line 1104) | public async Task<string> UploadFileAsync(string localFilePath, Dictio...
    method DownloadFileAsync (line 1124) | public async Task<byte[]> DownloadFileAsync(string fileId)
    method DeleteFileAsync (line 1144) | public async Task DeleteFileAsync(string fileId)

FILE: csharp_client/examples/MetadataExample.cs
  class MetadataExample (line 29) | class MetadataExample
    method Main (line 34) | static async Task Main(string[] args)

FILE: csharp_client/examples/PartialDownloadExample.cs
  class PartialDownloadExample (line 49) | class PartialDownloadExample
    method Main (line 64) | static async Task Main(string[] args)

FILE: csharp_client/examples/PerformanceExample.cs
  class PerformanceExample (line 50) | class PerformanceExample
    method Main (line 65) | static async Task Main(string[] args)
  class BenchmarkResult (line 1100) | class BenchmarkResult

FILE: csharp_client/examples/SlaveFileExample.cs
  class SlaveFileExample (line 48) | class SlaveFileExample
    method Main (line 63) | static async Task Main(string[] args)

FILE: csharp_client/examples/StreamingExample.cs
  class StreamingExample (line 49) | class StreamingExample
    method Main (line 73) | static async Task Main(string[] args)
    method CreateLargeTestFileAsync (line 988) | static async Task CreateLargeTestFileAsync(string filePath, long fileS...

FILE: csharp_client/examples/UploadBufferExample.cs
  class UploadBufferExample (line 53) | class UploadBufferExample
    method Main (line 72) | static async Task Main(string[] args)

FILE: examples/c_examples/01_basic_upload.c
  function print_usage (line 46) | void print_usage(const char *program_name)
  function validate_file (line 60) | int validate_file(const char *filepath)
  function main (line 82) | int main(int argc, char *argv[])

FILE: examples/c_examples/02_basic_download.c
  function download_callback (line 49) | int download_callback(void *arg, const int64_t file_size,
  function print_usage (line 83) | void print_usage(const char *program_name)
  function parse_file_id (line 101) | int parse_file_id(const char *file_id, char *group_name, char *filename)
  function write_to_file (line 135) | int write_to_file(const char *filename, const char *buff, const int64_t ...
  function main (line 157) | int main(int argc, char *argv[])

FILE: examples/c_examples/03_metadata_operations.c
  function print_usage (line 61) | void print_usage(const char *program_name)
  function parse_file_id (line 95) | int parse_file_id(const char *file_id, char *group_name, char *filename)
  function parse_metadata (line 124) | int parse_metadata(int argc, char *argv[], int start_index,
  function display_metadata (line 189) | void display_metadata(const FDFSMetaData *meta_list, int meta_count)
  function main (line 207) | int main(int argc, char *argv[])

FILE: examples/c_examples/04_appender_file.c
  function print_usage (line 61) | void print_usage(const char *program_name)
  function validate_file (line 80) | int validate_file(const char *filepath)
  function read_file_content (line 101) | int read_file_content(const char *filepath, char **buffer, int64_t *file...
  function main (line 135) | int main(int argc, char *argv[])

FILE: examples/c_examples/05_slave_file.c
  function print_usage (line 64) | void print_usage(const char *program_name)
  function validate_file (line 87) | int validate_file(const char *filepath)
  function validate_prefix (line 109) | int validate_prefix(const char *prefix)
  function main (line 129) | int main(int argc, char *argv[])

FILE: examples/c_examples/06_batch_upload.c
  type UploadResult (line 74) | typedef struct {
  type BatchStats (line 84) | typedef struct {
  function print_usage (line 95) | void print_usage(const char *program_name)
  function is_directory (line 112) | int is_directory(const char *path)
  function is_regular_file (line 124) | int is_regular_file(const char *path)
  function get_file_size (line 136) | int64_t get_file_size(const char *filepath)
  function format_size (line 148) | void format_size(int64_t size, char *buffer, size_t buffer_size)
  function get_current_time (line 164) | double get_current_time()
  function upload_single_file (line 174) | int upload_single_file(ConnectionInfo *pTrackerServer,
  function print_upload_result (line 235) | void print_upload_result(int index, int total, const UploadResult *result)
  function print_batch_summary (line 253) | void print_batch_summary(const BatchStats *stats, const UploadResult *re...
  function main (line 290) | int main(int argc, char *argv[])

FILE: examples/c_examples/07_connection_pool.c
  function get_current_time_ms (line 55) | int64_t get_current_time_ms(void)
  function print_usage (line 65) | void print_usage(const char *program_name)
  function perform_operation (line 85) | int perform_operation(ConnectionInfo *pTrackerServer, int op_num, bool *...
  function demo_with_connection_pool (line 109) | int demo_with_connection_pool(const char *conf_filename, int num_operati...
  function demo_without_connection_pool (line 192) | int demo_without_connection_pool(const char *conf_filename, int num_oper...
  function demo_all_connections (line 245) | int demo_all_connections(void)
  function demo_no_pool_connection (line 292) | int demo_no_pool_connection(void)
  function main (line 334) | int main(int argc, char *argv[])

FILE: examples/c_examples/08_error_handling.c
  type ErrorCategory (line 66) | typedef enum {
  type RecoveryAction (line 78) | typedef enum {
  function print_usage (line 88) | void print_usage(const char *program_name)
  function ErrorCategory (line 112) | ErrorCategory categorize_error(int error_code)
  function is_transient_error (line 168) | int is_transient_error(int error_code)
  function RecoveryAction (line 181) | RecoveryAction suggest_recovery_action(int error_code)
  function print_error_details (line 221) | void print_error_details(const char *operation, int error_code, const ch...
  function retry_operation (line 268) | int retry_operation(operation_func_t operation_func, void *context,
  function test_connection_errors (line 307) | int test_connection_errors(const char *conf_filename)
  function test_upload_errors (line 360) | int test_upload_errors(const char *conf_filename)
  function test_download_errors (line 429) | int test_download_errors(const char *conf_filename)
  function test_metadata_errors (line 512) | int test_metadata_errors(const char *conf_filename)
  function test_timeout_errors (line 558) | int test_timeout_errors(const char *conf_filename)
  function demonstrate_cleanup_patterns (line 585) | void demonstrate_cleanup_patterns(void)
  function main (line 628) | int main(int argc, char *argv[])

FILE: examples/php_examples/01_basic_upload.php
  function initializeFastDFS (line 26) | function initializeFastDFS() {
  function uploadFile (line 52) | function uploadFile($tracker, $localFilePath, $fileExtension = '') {
  function uploadFromBuffer (line 96) | function uploadFromBuffer($tracker, $fileContent, $fileExtension) {
  function main (line 123) | function main() {

FILE: examples/php_examples/02_basic_download.php
  function initializeFastDFS (line 27) | function initializeFastDFS() {
  function downloadToFile (line 52) | function downloadToFile($tracker, $fileId, $localPath) {
  function downloadToBuffer (line 90) | function downloadToBuffer($tracker, $fileId) {
  function downloadPartial (line 122) | function downloadPartial($tracker, $fileId, $offset, $length) {
  function getFileInfo (line 154) | function getFileInfo($tracker, $fileId) {
  function fileExists (line 193) | function fileExists($tracker, $fileId) {
  function main (line 215) | function main() {

FILE: examples/php_examples/03_metadata_operations.php
  function initializeFastDFS (line 37) | function initializeFastDFS() {
  function uploadWithMetadata (line 62) | function uploadWithMetadata($tracker, $localFilePath, $metadata = []) {
  function getMetadata (line 114) | function getMetadata($tracker, $fileId) {
  function setMetadata (line 154) | function setMetadata($tracker, $fileId, $metadata, $flag = METADATA_MERG...
  function deleteMetadata (line 200) | function deleteMetadata($tracker, $fileId) {
  function demonstrateMergeVsOverwrite (line 233) | function demonstrateMergeVsOverwrite($tracker, $fileId) {
  function createTestFile (line 273) | function createTestFile() {
  function main (line 286) | function main() {

FILE: examples/php_examples/04_appender_file.php
  function initializeFastDFS (line 34) | function initializeFastDFS() {
  function uploadAppenderFile (line 59) | function uploadAppenderFile($tracker, $localFilePath, $metadata = []) {
  function uploadAppenderFromBuffer (line 109) | function uploadAppenderFromBuffer($tracker, $content, $fileExtension, $m...
  function appendFromFile (line 148) | function appendFromFile($tracker, $fileId, $localFilePath) {
  function appendFromBuffer (line 190) | function appendFromBuffer($tracker, $fileId, $content) {
  function modifyFile (line 226) | function modifyFile($tracker, $fileId, $offset, $content) {
  function truncateFile (line 263) | function truncateFile($tracker, $fileId, $truncateSize) {
  function downloadAndDisplay (line 297) | function downloadAndDisplay($tracker, $fileId) {
  function demonstrateLogFile (line 327) | function demonstrateLogFile($tracker) {
  function demonstrateModification (line 371) | function demonstrateModification($tracker) {
  function demonstrateTruncate (line 424) | function demonstrateTruncate($tracker) {
  function main (line 465) | function main() {

FILE: examples/php_examples/05_slave_file.php
  function initializeFastDFS (line 35) | function initializeFastDFS() {
  function uploadMasterFile (line 62) | function uploadMasterFile($tracker, $localFilePath, $metadata = []) {
  function uploadSlaveFile (line 115) | function uploadSlaveFile($tracker, $masterFileId, $localFilePath, $prefi...
  function uploadSlaveFromBuffer (line 172) | function uploadSlaveFromBuffer($tracker, $masterFileId, $content, $prefi...
  function downloadSlaveFile (line 215) | function downloadSlaveFile($tracker, $slaveFileId, $localPath) {
  function downloadSlaveToBuffer (line 256) | function downloadSlaveToBuffer($tracker, $slaveFileId) {
  function deleteSlaveFile (line 292) | function deleteSlaveFile($tracker, $slaveFileId) {
  function createTestImage (line 326) | function createTestImage($filename, $width, $height, $text) {
  function demonstrateImageThumbnails (line 354) | function demonstrateImageThumbnails($tracker) {
  function demonstrateDocumentConversion (line 435) | function demonstrateDocumentConversion($tracker) {
  function main (line 531) | function main() {

FILE: examples/php_examples/06_advanced_download.php
  function initializeFastDFS (line 41) | function initializeFastDFS() {
  function getStorageServerInfo (line 68) | function getStorageServerInfo($tracker, $fileId) {
  function downloadWithRetry (line 125) | function downloadWithRetry($tracker, $fileId, $localPath, $maxRetries = ...
  function downloadInChunks (line 185) | function downloadInChunks($tracker, $fileId, $localPath, $chunkSize = CH...
  function downloadMultipleFiles (line 294) | function downloadMultipleFiles($tracker, $fileIds, $downloadDir) {
  function downloadWithProgress (line 366) | function downloadWithProgress($tracker, $fileId, $localPath) {
  function downloadRange (line 407) | function downloadRange($tracker, $fileId, $offset, $length, $localPath) {
  function formatBytes (line 453) | function formatBytes($bytes, $precision = 2) {
  function createTestFiles (line 469) | function createTestFiles($tracker) {
  function main (line 512) | function main() {

FILE: examples/php_examples/07_connection_pool_error_handling.php
  class FastDFSException (line 56) | class FastDFSException extends Exception {
    method __construct (line 59) | public function __construct($message, $code = 0, Exception $previous =...
    method getContext (line 64) | public function getContext() {
  class FastDFSConnectionException (line 72) | class FastDFSConnectionException extends FastDFSException {}
  class FastDFSUploadException (line 77) | class FastDFSUploadException extends FastDFSException {}
  class FastDFSDownloadException (line 82) | class FastDFSDownloadException extends FastDFSException {}
  class FastDFSFileNotFoundException (line 87) | class FastDFSFileNotFoundException extends FastDFSException {}
  class FastDFSTimeoutException (line 92) | class FastDFSTimeoutException extends FastDFSException {}
  class FastDFSCircuitBreakerException (line 97) | class FastDFSCircuitBreakerException extends FastDFSException {}
  class FastDFSConnectionPool (line 105) | class FastDFSConnectionPool {
    method __construct (line 122) | public function __construct(array $trackerServers, $minSize = 2, $maxS...
    method warmUp (line 140) | private function warmUp() {
    method createConnection (line 164) | private function createConnection() {
    method getNextServer (line 206) | private function getNextServer() {
    method acquire (line 218) | public function acquire() {
    method release (line 258) | public function release($connection) {
    method isConnectionValid (line 284) | private function isConnectionValid($connection) {
    method closeConnection (line 304) | private function closeConnection($connection) {
    method getStats (line 315) | public function getStats() {
    method shutdown (line 327) | public function shutdown() {
    method __destruct (line 349) | public function __destruct() {
  class CircuitBreaker (line 360) | class CircuitBreaker {
    method __construct (line 373) | public function __construct($threshold = 5, $timeout = 30) {
    method allowRequest (line 384) | public function allowRequest() {
    method recordSuccess (line 412) | public function recordSuccess() {
    method recordFailure (line 423) | public function recordFailure() {
    method getState (line 441) | public function getState() {
    method reset (line 448) | public function reset() {
  class FastDFSLogger (line 458) | class FastDFSLogger {
    method __construct (line 466) | public function __construct($logFile = null) {
    method logError (line 476) | public function logError(Exception $exception, array $context = []) {
    method logInfo (line 504) | public function logInfo($message) {
  class FastDFSClient (line 514) | class FastDFSClient {
    method __construct (line 526) | public function __construct(FastDFSConnectionPool $pool, CircuitBreake...
    method uploadFile (line 541) | public function uploadFile($filePath, array $metadata = [], $maxRetrie...
    method downloadFile (line 632) | public function downloadFile($fileId, $localPath, $maxRetries = MAX_RE...
    method calculateBackoff (line 706) | private function calculateBackoff($attempt) {
    method getPoolStats (line 716) | public function getPoolStats() {
  function demonstrateConnectionPool (line 724) | function demonstrateConnectionPool() {
  function demonstrateErrorHandling (line 778) | function demonstrateErrorHandling() {
  function main (line 828) | function main() {

FILE: examples/php_examples/08_error_handling.php
  class ErrorResult (line 47) | class ErrorResult {
    method success (line 60) | public static function success($data) {
    method failure (line 78) | public static function failure($error, $errorCode = 'UNKNOWN', array $...
    method isSuccess (line 93) | public function isSuccess() {
    method getOrThrow (line 103) | public function getOrThrow() {
  class ErrorCodes (line 114) | class ErrorCodes {
  class DetailedLogger (line 134) | class DetailedLogger {
    method __construct (line 150) | public function __construct($logFile, $minLevel = self::LEVEL_INFO) {
    method log (line 162) | private function log($level, $message, array $context = []) {
    method debug (line 194) | public function debug($message, array $context = []) {
    method info (line 198) | public function info($message, array $context = []) {
    method warning (line 202) | public function warning($message, array $context = []) {
    method error (line 207) | public function error($message, array $context = []) {
    method critical (line 212) | public function critical($message, array $context = []) {
  class FileValidator (line 221) | class FileValidator {
    method __construct (line 224) | public function __construct(DetailedLogger $logger) {
    method validate (line 234) | public function validate($filePath) {
    method formatBytes (line 336) | private function formatBytes($bytes) {
  class FastDFSOperations (line 348) | class FastDFSOperations {
    method __construct (line 359) | public function __construct(DetailedLogger $logger) {
    method connect (line 369) | public function connect() {
    method uploadFile (line 427) | public function uploadFile($filePath, array $metadata = []) {
    method downloadFile (line 531) | public function downloadFile($fileId, $localPath) {
    method deleteFile (line 659) | public function deleteFile($fileId) {
    method rollback (line 721) | public function rollback() {
    method disconnect (line 755) | public function disconnect() {
  function demonstrateValidationErrors (line 768) | function demonstrateValidationErrors() {
  function demonstrateTransactionRollback (line 814) | function demonstrateTransactionRollback() {
  function demonstrateGracefulDegradation (line 878) | function demonstrateGracefulDegradation() {
  function demonstrateCompleteWorkflow (line 919) | function demonstrateCompleteWorkflow() {
  function main (line 975) | function main() {

FILE: go_client/appender.go
  method uploadSlaveFileWithRetry (line 11) | func (c *Client) uploadSlaveFileWithRetry(ctx context.Context, masterFil...
  method uploadSlaveFileInternal (line 36) | func (c *Client) uploadSlaveFileInternal(ctx context.Context, masterFile...
  method appendFileWithRetry (line 126) | func (c *Client) appendFileWithRetry(ctx context.Context, fileID string,...
  method appendFileInternal (line 151) | func (c *Client) appendFileInternal(ctx context.Context, fileID string, ...
  method modifyFileWithRetry (line 206) | func (c *Client) modifyFileWithRetry(ctx context.Context, fileID string,...
  method modifyFileInternal (line 231) | func (c *Client) modifyFileInternal(ctx context.Context, fileID string, ...
  method truncateFileWithRetry (line 288) | func (c *Client) truncateFileWithRetry(ctx context.Context, fileID strin...
  method truncateFileInternal (line 313) | func (c *Client) truncateFileInternal(ctx context.Context, fileID string...

FILE: go_client/client.go
  type Client (line 18) | type Client struct
    method UploadFile (line 105) | func (c *Client) UploadFile(ctx context.Context, localFilename string,...
    method UploadBuffer (line 122) | func (c *Client) UploadBuffer(ctx context.Context, data []byte, fileEx...
    method UploadAppenderFile (line 131) | func (c *Client) UploadAppenderFile(ctx context.Context, localFilename...
    method UploadAppenderBuffer (line 140) | func (c *Client) UploadAppenderBuffer(ctx context.Context, data []byte...
    method UploadSlaveFile (line 159) | func (c *Client) UploadSlaveFile(ctx context.Context, masterFileID, pr...
    method DownloadFile (line 169) | func (c *Client) DownloadFile(ctx context.Context, fileID string) ([]b...
    method DownloadFileRange (line 184) | func (c *Client) DownloadFileRange(ctx context.Context, fileID string,...
    method DownloadToFile (line 193) | func (c *Client) DownloadToFile(ctx context.Context, fileID, localFile...
    method DeleteFile (line 202) | func (c *Client) DeleteFile(ctx context.Context, fileID string) error {
    method AppendFile (line 211) | func (c *Client) AppendFile(ctx context.Context, fileID string, data [...
    method ModifyFile (line 220) | func (c *Client) ModifyFile(ctx context.Context, fileID string, offset...
    method TruncateFile (line 229) | func (c *Client) TruncateFile(ctx context.Context, fileID string, size...
    method SetMetadata (line 244) | func (c *Client) SetMetadata(ctx context.Context, fileID string, metad...
    method GetMetadata (line 253) | func (c *Client) GetMetadata(ctx context.Context, fileID string) (map[...
    method GetFileInfo (line 262) | func (c *Client) GetFileInfo(ctx context.Context, fileID string) (*Fil...
    method FileExists (line 271) | func (c *Client) FileExists(ctx context.Context, fileID string) (bool,...
    method Close (line 287) | func (c *Client) Close() error {
    method checkClosed (line 316) | func (c *Client) checkClosed() error {
  type ClientConfig (line 27) | type ClientConfig struct
  function NewClient (line 51) | func NewClient(config *ClientConfig) (*Client, error) {
  function validateConfig (line 327) | func validateConfig(config *ClientConfig) error {

FILE: go_client/client_test.go
  function TestNewClient (line 12) | func TestNewClient(t *testing.T) {
  function TestClientDefaults (line 63) | func TestClientDefaults(t *testing.T) {
  function TestSplitFileID (line 79) | func TestSplitFileID(t *testing.T) {
  function TestJoinFileID (line 130) | func TestJoinFileID(t *testing.T) {
  function TestGetFileExtName (line 153) | func TestGetFileExtName(t *testing.T) {
  function TestEncodeDecodeMetadata (line 189) | func TestEncodeDecodeMetadata(t *testing.T) {
  function TestEncodeDecodeHeader (line 230) | func TestEncodeDecodeHeader(t *testing.T) {
  function TestMapStatusToError (line 271) | func TestMapStatusToError(t *testing.T) {
  function TestClientClose (line 316) | func TestClientClose(t *testing.T) {

FILE: go_client/connection.go
  type Connection (line 14) | type Connection struct
    method Send (line 57) | func (c *Connection) Send(data []byte, timeout time.Duration) error {
    method Receive (line 97) | func (c *Connection) Receive(size int, timeout time.Duration) ([]byte,...
    method ReceiveFull (line 130) | func (c *Connection) ReceiveFull(size int, timeout time.Duration) ([]b...
    method Close (line 162) | func (c *Connection) Close() error {
    method IsAlive (line 179) | func (c *Connection) IsAlive() bool {
    method LastUsed (line 207) | func (c *Connection) LastUsed() time.Time {
    method Addr (line 216) | func (c *Connection) Addr() string {
  function NewConnection (line 31) | func NewConnection(addr string, timeout time.Duration) (*Connection, err...
  type ConnectionPool (line 226) | type ConnectionPool struct
    method Get (line 291) | func (p *ConnectionPool) Get(ctx context.Context, addr string) (*Conne...
    method Put (line 361) | func (p *ConnectionPool) Put(conn *Connection) error {
    method cleanPool (line 409) | func (p *ConnectionPool) cleanPool(sp *serverPool) {
    method AddAddr (line 432) | func (p *ConnectionPool) AddAddr(addr string) {
    method Close (line 460) | func (p *ConnectionPool) Close() error {
  type serverPool (line 238) | type serverPool struct
  function NewConnectionPool (line 258) | func NewConnectionPool(addrs []string, maxConns int, connectTimeout, idl...

FILE: go_client/errors.go
  type ProtocolError (line 60) | type ProtocolError struct
    method Error (line 66) | func (e *ProtocolError) Error() string {
  type NetworkError (line 73) | type NetworkError struct
    method Error (line 80) | func (e *NetworkError) Error() string {
    method Unwrap (line 85) | func (e *NetworkError) Unwrap() error {
  type StorageError (line 91) | type StorageError struct
    method Error (line 97) | func (e *StorageError) Error() string {
    method Unwrap (line 102) | func (e *StorageError) Unwrap() error {
  type TrackerError (line 108) | type TrackerError struct
    method Error (line 114) | func (e *TrackerError) Error() string {
    method Unwrap (line 119) | func (e *TrackerError) Unwrap() error {
  function mapStatusToError (line 138) | func mapStatusToError(status byte) error {

FILE: go_client/examples/appender/main.go
  function main (line 12) | func main() {

FILE: go_client/examples/basic/main.go
  function main (line 12) | func main() {

FILE: go_client/examples/batch/main.go
  type BatchResult (line 17) | type BatchResult struct
  type BatchStats (line 26) | type BatchStats struct
  function createTestData (line 36) | func createTestData(size int) []byte {
  function main (line 44) | func main() {

FILE: go_client/examples/concurrent/main.go
  type OperationResult (line 17) | type OperationResult struct
  function createTestData (line 27) | func createTestData(size int) []byte {
  function main (line 35) | func main() {

FILE: go_client/examples/connection_pool/main.go
  type PoolStats (line 17) | type PoolStats struct
  function createTestData (line 27) | func createTestData(size int) []byte {
  function main (line 35) | func main() {

FILE: go_client/examples/error_handling/main.go
  function logError (line 16) | func logError(operation string, err error) {
  function retryWithBackoff (line 23) | func retryWithBackoff(ctx context.Context, maxRetries int, operation fun...
  function retryWithFixedDelay (line 49) | func retryWithFixedDelay(ctx context.Context, maxRetries int, delay time...
  function main (line 71) | func main() {

FILE: go_client/examples/metadata/main.go
  function main (line 12) | func main() {

FILE: go_client/examples/performance/main.go
  type PerformanceMetrics (line 19) | type PerformanceMetrics struct
    method RecordOperation (line 32) | func (pm *PerformanceMetrics) RecordOperation(success bool, duration t...
    method Print (line 54) | func (pm *PerformanceMetrics) Print(title string) {
    method Reset (line 104) | func (pm *PerformanceMetrics) Reset() {
  type MemoryStats (line 119) | type MemoryStats struct
    method Start (line 125) | func (ms *MemoryStats) Start() {
    method Update (line 133) | func (ms *MemoryStats) Update() {
    method GetPeakDelta (line 142) | func (ms *MemoryStats) GetPeakDelta() uint64 {
  function FormatMemory (line 150) | func FormatMemory(bytes uint64) string {
  function CreateTestData (line 164) | func CreateTestData(size int) []byte {
  function main (line 172) | func main() {

FILE: go_client/metadata.go
  method setMetadataWithRetry (line 11) | func (c *Client) setMetadataWithRetry(ctx context.Context, fileID string...
  method setMetadataInternal (line 36) | func (c *Client) setMetadataInternal(ctx context.Context, fileID string,...
  method getMetadataWithRetry (line 97) | func (c *Client) getMetadataWithRetry(ctx context.Context, fileID string...
  method getMetadataInternal (line 122) | func (c *Client) getMetadataInternal(ctx context.Context, fileID string)...
  method getFileInfoWithRetry (line 187) | func (c *Client) getFileInfoWithRetry(ctx context.Context, fileID string...
  method getFileInfoInternal (line 212) | func (c *Client) getFileInfoInternal(ctx context.Context, fileID string)...

FILE: go_client/operations.go
  method uploadFileWithRetry (line 11) | func (c *Client) uploadFileWithRetry(ctx context.Context, localFilename ...
  method uploadFileInternal (line 38) | func (c *Client) uploadFileInternal(ctx context.Context, localFilename s...
  method uploadBufferWithRetry (line 52) | func (c *Client) uploadBufferWithRetry(ctx context.Context, data []byte,...
  method uploadBufferInternal (line 77) | func (c *Client) uploadBufferInternal(ctx context.Context, data []byte, ...
  method getStorageServer (line 172) | func (c *Client) getStorageServer(ctx context.Context, groupName string)...
  method downloadFileWithRetry (line 252) | func (c *Client) downloadFileWithRetry(ctx context.Context, fileID strin...
  method downloadFileInternal (line 277) | func (c *Client) downloadFileInternal(ctx context.Context, fileID string...
  method getDownloadStorageServer (line 342) | func (c *Client) getDownloadStorageServer(ctx context.Context, groupName...
  method downloadToFileWithRetry (line 403) | func (c *Client) downloadToFileWithRetry(ctx context.Context, fileID, lo...
  method deleteFileWithRetry (line 413) | func (c *Client) deleteFileWithRetry(ctx context.Context, fileID string)...
  method deleteFileInternal (line 438) | func (c *Client) deleteFileInternal(ctx context.Context, fileID string) ...

FILE: go_client/protocol.go
  function encodeHeader (line 25) | func encodeHeader(length int64, cmd byte, status byte) []byte {
  function decodeHeader (line 42) | func decodeHeader(data []byte) (*TrackerHeader, error) {
  function splitFileID (line 67) | func splitFileID(fileID string) (string, string, error) {
  function joinFileID (line 99) | func joinFileID(groupName, remoteFilename string) string {
  function encodeMetadata (line 116) | func encodeMetadata(metadata map[string]string) []byte {
  function decodeMetadata (line 150) | func decodeMetadata(data []byte) (map[string]string, error) {
  function getFileExtName (line 190) | func getFileExtName(filename string) string {
  function readFileContent (line 210) | func readFileContent(filename string) ([]byte, error) {
  function writeFileContent (line 243) | func writeFileContent(filename string, data []byte) error {
  function padString (line 272) | func padString(s string, length int) []byte {
  function unpadString (line 286) | func unpadString(data []byte) string {
  function encodeInt64 (line 297) | func encodeInt64(n int64) []byte {
  function decodeInt64 (line 310) | func decodeInt64(data []byte) int64 {
  function encodeInt32 (line 323) | func encodeInt32(n int32) []byte {
  function decodeInt32 (line 335) | func decodeInt32(data []byte) int32 {

FILE: go_client/types.go
  constant TrackerDefaultPort (line 15) | TrackerDefaultPort = 22122
  constant StorageDefaultPort (line 16) | StorageDefaultPort = 23000
  constant TrackerProtoCmdServiceQueryStoreWithoutGroupOne (line 19) | TrackerProtoCmdServiceQueryStoreWithoutGroupOne = 101
  constant TrackerProtoCmdServiceQueryFetchOne (line 20) | TrackerProtoCmdServiceQueryFetchOne             = 102
  constant TrackerProtoCmdServiceQueryUpdate (line 21) | TrackerProtoCmdServiceQueryUpdate               = 103
  constant TrackerProtoCmdServiceQueryStoreWithGroupOne (line 22) | TrackerProtoCmdServiceQueryStoreWithGroupOne    = 104
  constant TrackerProtoCmdServiceQueryFetchAll (line 23) | TrackerProtoCmdServiceQueryFetchAll             = 105
  constant TrackerProtoCmdServiceQueryStoreWithoutGroupAll (line 24) | TrackerProtoCmdServiceQueryStoreWithoutGroupAll = 106
  constant TrackerProtoCmdServiceQueryStoreWithGroupAll (line 25) | TrackerProtoCmdServiceQueryStoreWithGroupAll    = 107
  constant TrackerProtoCmdServerListOneGroup (line 26) | TrackerProtoCmdServerListOneGroup               = 90
  constant TrackerProtoCmdServerListAllGroups (line 27) | TrackerProtoCmdServerListAllGroups              = 91
  constant TrackerProtoCmdServerListStorage (line 28) | TrackerProtoCmdServerListStorage                = 92
  constant TrackerProtoCmdServerDeleteStorage (line 29) | TrackerProtoCmdServerDeleteStorage              = 93
  constant TrackerProtoCmdStorageReportIPChanged (line 30) | TrackerProtoCmdStorageReportIPChanged           = 94
  constant TrackerProtoCmdStorageReportStatus (line 31) | TrackerProtoCmdStorageReportStatus              = 95
  constant TrackerProtoCmdStorageReportDiskUsage (line 32) | TrackerProtoCmdStorageReportDiskUsage           = 96
  constant TrackerProtoCmdStorageSyncTimestamp (line 33) | TrackerProtoCmdStorageSyncTimestamp             = 97
  constant TrackerProtoCmdStorageSyncReport (line 34) | TrackerProtoCmdStorageSyncReport                = 98
  constant StorageProtoCmdUploadFile (line 37) | StorageProtoCmdUploadFile         = 11
  constant StorageProtoCmdDeleteFile (line 38) | StorageProtoCmdDeleteFile         = 12
  constant StorageProtoCmdSetMetadata (line 39) | StorageProtoCmdSetMetadata        = 13
  constant StorageProtoCmdDownloadFile (line 40) | StorageProtoCmdDownloadFile       = 14
  constant StorageProtoCmdGetMetadata (line 41) | StorageProtoCmdGetMetadata        = 15
  constant StorageProtoCmdUploadSlaveFile (line 42) | StorageProtoCmdUploadSlaveFile    = 21
  constant StorageProtoCmdQueryFileInfo (line 43) | StorageProtoCmdQueryFileInfo      = 22
  constant StorageProtoCmdUploadAppenderFile (line 44) | StorageProtoCmdUploadAppenderFile = 23
  constant StorageProtoCmdAppendFile (line 45) | StorageProtoCmdAppendFile         = 24
  constant StorageProtoCmdModifyFile (line 46) | StorageProtoCmdModifyFile         = 34
  constant StorageProtoCmdTruncateFile (line 47) | StorageProtoCmdTruncateFile       = 36
  constant TrackerProtoResp (line 50) | TrackerProtoResp     = 100
  constant FdfsProtoResp (line 51) | FdfsProtoResp        = TrackerProtoResp
  constant FdfsStorageProtoResp (line 52) | FdfsStorageProtoResp = TrackerProtoResp
  constant FdfsGroupNameMaxLen (line 55) | FdfsGroupNameMaxLen   = 16
  constant FdfsFileExtNameMaxLen (line 56) | FdfsFileExtNameMaxLen = 6
  constant FdfsMaxMetaNameLen (line 57) | FdfsMaxMetaNameLen    = 64
  constant FdfsMaxMetaValueLen (line 58) | FdfsMaxMetaValueLen   = 256
  constant FdfsFilePrefixMaxLen (line 59) | FdfsFilePrefixMaxLen  = 16
  constant FdfsStorageIDMaxSize (line 60) | FdfsStorageIDMaxSize  = 16
  constant FdfsVersionSize (line 61) | FdfsVersionSize       = 8
  constant IPAddressSize (line 62) | IPAddressSize         = 16
  constant FdfsRecordSeparator (line 65) | FdfsRecordSeparator = '\x01'
  constant FdfsFieldSeparator (line 66) | FdfsFieldSeparator  = '\x02'
  constant FdfsProtoHeaderLen (line 69) | FdfsProtoHeaderLen = 10
  constant FdfsStorageStatusInit (line 72) | FdfsStorageStatusInit      = 0
  constant FdfsStorageStatusWaitSync (line 73) | FdfsStorageStatusWaitSync  = 1
  constant FdfsStorageStatusSyncing (line 74) | FdfsStorageStatusSyncing   = 2
  constant FdfsStorageStatusIPChanged (line 75) | FdfsStorageStatusIPChanged = 3
  constant FdfsStorageStatusDeleted (line 76) | FdfsStorageStatusDeleted   = 4
  constant FdfsStorageStatusOffline (line 77) | FdfsStorageStatusOffline   = 5
  constant FdfsStorageStatusOnline (line 78) | FdfsStorageStatusOnline    = 6
  constant FdfsStorageStatusActive (line 79) | FdfsStorageStatusActive    = 7
  constant FdfsStorageStatusRecovery (line 80) | FdfsStorageStatusRecovery  = 9
  constant FdfsStorageStatusNone (line 81) | FdfsStorageStatusNone      = 99
  type MetadataFlag (line 86) | type MetadataFlag
  constant MetadataOverwrite (line 91) | MetadataOverwrite MetadataFlag = 'O'
  constant MetadataMerge (line 95) | MetadataMerge MetadataFlag = 'M'
  type FileInfo (line 101) | type FileInfo struct
  type StorageServer (line 117) | type StorageServer struct
  type GroupInfo (line 125) | type GroupInfo struct
  type StorageInfo (line 142) | type StorageInfo struct
  type TrackerHeader (line 165) | type TrackerHeader struct
  type UploadResponse (line 173) | type UploadResponse struct
  type ConnectionInfo (line 180) | type ConnectionInfo struct

FILE: javascript_client/examples/01_basic_upload.js
  function main (line 22) | async function main() {

FILE: javascript_client/examples/02_metadata_operations.js
  function main (line 20) | async function main() {

FILE: javascript_client/examples/03_appender_file.js
  function main (line 22) | async function main() {

FILE: javascript_client/examples/04_slave_file.js
  function createThumbnail (line 26) | function createThumbnail(imageData) {
  function createPreview (line 38) | function createPreview(imageData) {
  function main (line 46) | async function main() {

FILE: javascript_client/src/client.js
  class Client (line 59) | class Client {
    method constructor (line 78) | constructor(config) {
    method _validateConfig (line 130) | _validateConfig(config) {
    method _checkClosed (line 152) | _checkClosed() {
    method uploadFile (line 183) | async uploadFile(localFilename, metadata = null) {
    method uploadBuffer (line 224) | async uploadBuffer(data, fileExtName, metadata = null) {
    method uploadAppenderFile (line 256) | async uploadAppenderFile(localFilename, metadata = null) {
    method uploadAppenderBuffer (line 282) | async uploadAppenderBuffer(data, fileExtName, metadata = null) {
    method uploadSlaveFile (line 319) | async uploadSlaveFile(masterFileId, prefixName, fileExtName, data, met...
    method downloadFile (line 353) | async downloadFile(fileId) {
    method downloadFileRange (line 380) | async downloadFileRange(fileId, offset, length) {
    method downloadToFile (line 409) | async downloadToFile(fileId, localFilename) {
    method deleteFile (line 434) | async deleteFile(fileId) {
    method appendFile (line 466) | async appendFile(fileId, data) {
    method modifyFile (line 499) | async modifyFile(fileId, offset, data) {
    method truncateFile (line 534) | async truncateFile(fileId, size) {
    method setMetadata (line 573) | async setMetadata(fileId, metadata, flag = 'OVERWRITE') {
    method getMetadata (line 602) | async getMetadata(fileId) {
    method getFileInfo (line 629) | async getFileInfo(fileId) {
    method fileExists (line 660) | async fileExists(fileId) {
    method close (line 697) | async close() {

FILE: javascript_client/src/connection.js
  class Connection (line 25) | class Connection {
    method constructor (line 32) | constructor(socket, addr) {
    method send (line 50) | async send(data, timeout = 30000) {
    method receive (line 85) | async receive(size, timeout = 30000) {
    method receiveFull (line 131) | async receiveFull(size, timeout = 30000) {
    method close (line 185) | close() {
    method isAlive (line 200) | isAlive() {
    method getLastUsed (line 215) | getLastUsed() {
    method getAddr (line 224) | getAddr() {
  class ConnectionPool (line 242) | class ConnectionPool {
    method constructor (line 251) | constructor(addrs, maxConns = 10, connectTimeout = 5000, idleTimeout =...
    method get (line 278) | async get(addr) {
    method _createConnection (line 324) | async _createConnection(addr) {
    method put (line 367) | put(conn) {
    method _cleanPool (line 422) | _cleanPool(addr) {
    method addAddr (line 450) | addAddr(addr) {
    method close (line 469) | close() {

FILE: javascript_client/src/errors.js
  class FastDFSError (line 21) | class FastDFSError extends Error {
    method constructor (line 22) | constructor(message) {
  class ClientClosedError (line 35) | class ClientClosedError extends FastDFSError {
    method constructor (line 36) | constructor() {
  class FileNotFoundError (line 48) | class FileNotFoundError extends FastDFSError {
    method constructor (line 49) | constructor(fileId) {
  class NoStorageServerError (line 62) | class NoStorageServerError extends FastDFSError {
    method constructor (line 63) | constructor() {
  class ConnectionTimeoutError (line 74) | class ConnectionTimeoutError extends FastDFSError {
    method constructor (line 75) | constructor(addr) {
  class NetworkTimeoutError (line 87) | class NetworkTimeoutError extends FastDFSError {
    method constructor (line 88) | constructor(operation) {
  class InvalidFileIDError (line 100) | class InvalidFileIDError extends FastDFSError {
    method constructor (line 101) | constructor(fileId) {
  class InvalidResponseError (line 114) | class InvalidResponseError extends FastDFSError {
    method constructor (line 115) | constructor(details) {
  class StorageServerOfflineError (line 127) | class StorageServerOfflineError extends FastDFSError {
    method constructor (line 128) | constructor(addr) {
  class TrackerServerOfflineError (line 140) | class TrackerServerOfflineError extends FastDFSError {
    method constructor (line 141) | constructor(addr) {
  class InsufficientSpaceError (line 153) | class InsufficientSpaceError extends FastDFSError {
    method constructor (line 154) | constructor() {
  class FileAlreadyExistsError (line 165) | class FileAlreadyExistsError extends FastDFSError {
    method constructor (line 166) | constructor(fileId) {
  class InvalidMetadataError (line 178) | class InvalidMetadataError extends FastDFSError {
    method constructor (line 179) | constructor(details) {
  class OperationNotSupportedError (line 192) | class OperationNotSupportedError extends FastDFSError {
    method constructor (line 193) | constructor(operation) {
  class InvalidArgumentError (line 205) | class InvalidArgumentError extends FastDFSError {
    method constructor (line 206) | constructor(details) {
  class ProtocolError (line 219) | class ProtocolError extends FastDFSError {
    method constructor (line 220) | constructor(code, message) {
  class NetworkError (line 233) | class NetworkError extends FastDFSError {
    method constructor (line 234) | constructor(operation, addr, originalError) {
  function mapStatusToError (line 259) | function mapStatusToError(status) {

FILE: javascript_client/src/operations.js
  class Operations (line 45) | class Operations {
    method constructor (line 54) | constructor(trackerPool, storagePool, networkTimeout, retryCount) {
    method _withRetry (line 68) | async _withRetry(operation) {
    method _queryStorageForUpload (line 105) | async _queryStorageForUpload(groupName = null) {
    method _queryStorageForUpdate (line 162) | async _queryStorageForUpdate(groupName, remoteFilename) {
    method uploadBuffer (line 214) | async uploadBuffer(fileData, fileExtName, metadata, isAppender) {
    method uploadSlaveFile (line 270) | async uploadSlaveFile(masterFileId, prefixName, fileExtName, fileData,...
    method downloadFile (line 360) | async downloadFile(fileId, offset, downloadBytes) {
    method deleteFile (line 402) | async deleteFile(fileId) {
    method appendFile (line 448) | async appendFile(fileId, data) {
    method modifyFile (line 509) | async modifyFile(fileId, offset, data) {
    method truncateFile (line 576) | async truncateFile(fileId, truncatedFileSize) {
    method setMetadata (line 633) | async setMetadata(fileId, metadata, flag) {
    method getMetadata (line 703) | async getMetadata(fileId) {
    method getFileInfo (line 751) | async getFileInfo(fileId) {

FILE: javascript_client/src/protocol.js
  function encodeHeader (line 40) | function encodeHeader(bodyLength, cmd, status = 0) {
  function decodeHeader (line 64) | function decodeHeader(headerBuf) {
  function padString (line 90) | function padString(str, maxLen) {
  function readString (line 107) | function readString(buf, offset = 0, maxLen) {
  function parseFileId (line 130) | function parseFileId(fileId) {
  function encodeMetadata (line 160) | function encodeMetadata(metadata) {
  function decodeMetadata (line 194) | function decodeMetadata(metaBuf) {
  function encodeUploadRequest (line 239) | function encodeUploadRequest(storePathIndex, fileSize, fileExtName, file...
  function decodeUploadResponse (line 274) | function decodeUploadResponse(responseBuf) {
  function encodeDownloadRequest (line 294) | function encodeDownloadRequest(offset, downloadBytes, groupName, remoteF...
  function decodeFileInfo (line 333) | function decodeFileInfo(responseBuf) {

FILE: javascript_client/src/types.js
  constant TRACKER_DEFAULT_PORT (line 23) | const TRACKER_DEFAULT_PORT = 22122;
  constant STORAGE_DEFAULT_PORT (line 29) | const STORAGE_DEFAULT_PORT = 23000;
  constant FDFS_PROTO_HEADER_LEN (line 35) | const FDFS_PROTO_HEADER_LEN = 10;
  constant FDFS_GROUP_NAME_MAX_LEN (line 45) | const FDFS_GROUP_NAME_MAX_LEN = 16;
  constant FDFS_FILE_EXT_NAME_MAX_LEN (line 51) | const FDFS_FILE_EXT_NAME_MAX_LEN = 6;
  constant FDFS_MAX_META_NAME_LEN (line 57) | const FDFS_MAX_META_NAME_LEN = 64;
  constant FDFS_MAX_META_VALUE_LEN (line 63) | const FDFS_MAX_META_VALUE_LEN = 256;
  constant FDFS_FILE_PREFIX_MAX_LEN (line 69) | const FDFS_FILE_PREFIX_MAX_LEN = 16;
  constant FDFS_STORAGE_ID_MAX_SIZE (line 75) | const FDFS_STORAGE_ID_MAX_SIZE = 16;
  constant FDFS_VERSION_SIZE (line 81) | const FDFS_VERSION_SIZE = 8;
  constant IP_ADDRESS_SIZE (line 87) | const IP_ADDRESS_SIZE = 16;
  constant FDFS_RECORD_SEPARATOR (line 97) | const FDFS_RECORD_SEPARATOR = 0x01;
  constant FDFS_FIELD_SEPARATOR (line 103) | const FDFS_FIELD_SEPARATOR = 0x02;

FILE: monitoring/health_check/health_checker.c
  type HealthStatus (line 34) | typedef enum {
  type ClusterHealth (line 41) | typedef struct {
  type AlertState (line 51) | typedef struct {
  function should_suppress_alert (line 64) | static int should_suppress_alert(const char *message) {
  function send_alert (line 81) | static void send_alert(const char *level, const char *message) {
  function signal_handler (line 107) | static void signal_handler(int sig) {
  function HealthStatus (line 114) | static HealthStatus check_storage_health(FDFSStorageBrief *pStorage,
  function perform_health_check (line 172) | static int perform_health_check(ClusterHealth *cluster_health) {
  function print_health_status (line 274) | static void print_health_status(ClusterHealth *cluster_health) {
  function main (line 308) | int main(int argc, char *argv[]) {

FILE: monitoring/prometheus_exporter/fdfs_exporter.c
  function format_metric_name (line 40) | static void format_metric_name(char *buffer, size_t size,
  function append_metric (line 48) | static int append_metric(char *response, size_t *offset, size_t max_size,
  function export_group_metrics (line 85) | static int export_group_metrics(char *response, size_t *offset, size_t m...
  function export_storage_metrics (line 130) | static int export_storage_metrics(char *response, size_t *offset, size_t...
  function collect_metrics (line 270) | static int collect_metrics(char *response, size_t max_size) {
  function handle_request (line 328) | static void handle_request(int client_socket) {
  function signal_handler (line 391) | static void signal_handler(int sig) {
  function main (line 402) | int main(int argc, char *argv[]) {

FILE: php_client/fastdfs_callback_test.php
  function my_upload_file_callback (line 78) | function my_upload_file_callback($sock, $args)
  function my_download_file_callback (line 86) | function my_download_file_callback($args, $file_size, $data)

FILE: php_client/fastdfs_client.c
  type FDFSConfigInfo (line 19) | typedef struct
  type FDFSPhpContext (line 24) | typedef struct
  type php_fdfs_t (line 30) | typedef struct
  type php_fdfs_callback_t (line 42) | typedef struct
  type php_fdfs_upload_callback_t (line 48) | typedef struct
  function php_fdfs_tracker_get_connection_impl (line 831) | static void php_fdfs_tracker_get_connection_impl(INTERNAL_FUNCTION_PARAM...
  function php_fdfs_tracker_make_all_connections_impl (line 865) | static void php_fdfs_tracker_make_all_connections_impl( \
  function php_fdfs_tracker_close_all_connections_impl (line 892) | static void php_fdfs_tracker_close_all_connections_impl( \
  function php_fdfs_connect_server_impl (line 912) | static void php_fdfs_connect_server_impl(INTERNAL_FUNCTION_PARAMETERS, \
  function php_fdfs_disconnect_server_impl (line 959) | static void php_fdfs_disconnect_server_impl(INTERNAL_FUNCTION_PARAMETERS, \
  function php_fdfs_get_callback_from_hash (line 1018) | static int php_fdfs_get_callback_from_hash(HashTable *callback_hash, \
  function php_fdfs_get_upload_callback_from_hash (line 1052) | static int php_fdfs_get_upload_callback_from_hash(HashTable *callback_ha...
  function php_fdfs_get_server_from_hash (line 1090) | static int php_fdfs_get_server_from_hash(HashTable *tracker_hash, \
  function php_fastdfs_active_test_impl (line 1157) | static void php_fastdfs_active_test_impl(INTERNAL_FUNCTION_PARAMETERS, \
  function php_fdfs_tracker_list_groups_impl (line 1202) | static void php_fdfs_tracker_list_groups_impl(INTERNAL_FUNCTION_PARAMETE...
  function php_fdfs_tracker_query_storage_store_impl (line 1630) | static void php_fdfs_tracker_query_storage_store_impl( \
  function php_fdfs_tracker_query_storage_store_list_impl (line 1736) | static void php_fdfs_tracker_query_storage_store_list_impl( \
  function php_fdfs_tracker_do_query_storage_impl (line 1859) | static void php_fdfs_tracker_do_query_storage_impl( \
  function php_fdfs_tracker_delete_storage_impl (line 1996) | static void php_fdfs_tracker_delete_storage_impl( \
  function php_fdfs_storage_delete_file_impl (line 2047) | static void php_fdfs_storage_delete_file_impl( \
  function php_fdfs_storage_truncate_file_impl (line 2206) | static void php_fdfs_storage_truncate_file_impl( \
  function php_fdfs_storage_download_file_to_callback_impl (line 2368) | static void php_fdfs_storage_download_file_to_callback_impl( \
  function php_fdfs_storage_download_file_to_buff_impl (line 2549) | static void php_fdfs_storage_download_file_to_buff_impl( \
  function php_fdfs_storage_download_file_to_file_impl (line 2717) | static void php_fdfs_storage_download_file_to_file_impl( \
  function php_fdfs_storage_get_metadata_impl (line 2888) | static void php_fdfs_storage_get_metadata_impl( \
  function php_fdfs_storage_file_exist_impl (line 3063) | static void php_fdfs_storage_file_exist_impl( \
  function php_fdfs_tracker_query_storage_list_impl (line 3220) | static void php_fdfs_tracker_query_storage_list_impl( \
  function php_fdfs_upload_callback (line 3370) | static int php_fdfs_upload_callback(void *arg, const int64_t file_size, ...
  function php_fdfs_download_callback (line 3425) | static int php_fdfs_download_callback(void *arg, const int64_t file_size, \
  function php_fdfs_storage_upload_file_impl (line 3505) | static void php_fdfs_storage_upload_file_impl(INTERNAL_FUNCTION_PARAMETE...
  function php_fdfs_storage_upload_slave_file_impl (line 3786) | static void php_fdfs_storage_upload_slave_file_impl( \
  function php_fdfs_storage_append_file_impl (line 4100) | static void php_fdfs_storage_append_file_impl( \
  function php_fdfs_storage_modify_file_impl (line 4328) | static void php_fdfs_storage_modify_file_impl( \
  function php_fdfs_storage_regenerate_appender_filename_impl (line 4560) | static void php_fdfs_storage_regenerate_appender_filename_impl(
  function php_fdfs_storage_set_metadata_impl (line 4744) | static void php_fdfs_storage_set_metadata_impl(INTERNAL_FUNCTION_PARAMET...
  function php_fdfs_http_gen_token_impl (line 4954) | static void php_fdfs_http_gen_token_impl(INTERNAL_FUNCTION_PARAMETERS, \
  function php_fdfs_send_data_impl (line 4994) | static void php_fdfs_send_data_impl(INTERNAL_FUNCTION_PARAMETERS, \
  function php_fdfs_get_file_info_impl (line 5030) | static void php_fdfs_get_file_info_impl(INTERNAL_FUNCTION_PARAMETERS, \
  function php_fdfs_gen_slave_filename_impl (line 5138) | static void php_fdfs_gen_slave_filename_impl(INTERNAL_FUNCTION_PARAMETER...
  function ZEND_FUNCTION (line 5225) | ZEND_FUNCTION(fastdfs_tracker_get_connection)
  function ZEND_FUNCTION (line 5235) | ZEND_FUNCTION(fastdfs_tracker_make_all_connections)
  function ZEND_FUNCTION (line 5245) | ZEND_FUNCTION(fastdfs_tracker_close_all_connections)
  function ZEND_FUNCTION (line 5255) | ZEND_FUNCTION(fastdfs_connect_server)
  function ZEND_FUNCTION (line 5265) | ZEND_FUNCTION(fastdfs_disconnect_server)
  function ZEND_FUNCTION (line 5275) | ZEND_FUNCTION(fastdfs_active_test)
  function ZEND_FUNCTION (line 5285) | ZEND_FUNCTION(fastdfs_get_last_error_no)
  function ZEND_FUNCTION (line 5294) | ZEND_FUNCTION(fastdfs_get_last_error_info)
  function ZEND_FUNCTION (line 5306) | ZEND_FUNCTION(fastdfs_client_version)
  function ZEND_FUNCTION (line 5322) | ZEND_FUNCTION(fastdfs_tracker_list_groups)
  function ZEND_FUNCTION (line 5333) | ZEND_FUNCTION(fastdfs_tracker_query_storage_store)
  function ZEND_FUNCTION (line 5344) | ZEND_FUNCTION(fastdfs_tracker_query_storage_store_list)
  function ZEND_FUNCTION (line 5355) | ZEND_FUNCTION(fastdfs_tracker_query_storage_update)
  function ZEND_FUNCTION (line 5367) | ZEND_FUNCTION(fastdfs_tracker_query_storage_fetch)
  function ZEND_FUNCTION (line 5379) | ZEND_FUNCTION(fastdfs_tracker_query_storage_list)
  function ZEND_FUNCTION (line 5391) | ZEND_FUNCTION(fastdfs_tracker_query_storage_update1)
  function ZEND_FUNCTION (line 5403) | ZEND_FUNCTION(fastdfs_tracker_query_storage_fetch1)
  function ZEND_FUNCTION (line 5415) | ZEND_FUNCTION(fastdfs_tracker_query_storage_list1)
  function ZEND_FUNCTION (line 5426) | ZEND_FUNCTION(fastdfs_tracker_delete_storage)
  function ZEND_FUNCTION (line 5439) | ZEND_FUNCTION(fastdfs_storage_upload_by_filename)
  function ZEND_FUNCTION (line 5452) | ZEND_FUNCTION(fastdfs_storage_upload_by_filename1)
  function ZEND_FUNCTION (line 5465) | ZEND_FUNCTION(fastdfs_storage_upload_by_filebuff)
  function ZEND_FUNCTION (line 5478) | ZEND_FUNCTION(fastdfs_storage_upload_by_filebuff1)
  function ZEND_FUNCTION (line 5491) | ZEND_FUNCTION(fastdfs_storage_upload_by_callback)
  function ZEND_FUNCTION (line 5504) | ZEND_FUNCTION(fastdfs_storage_upload_by_callback1)
  function ZEND_FUNCTION (line 5517) | ZEND_FUNCTION(fastdfs_storage_append_by_filename)
  function ZEND_FUNCTION (line 5529) | ZEND_FUNCTION(fastdfs_storage_append_by_filename1)
  function ZEND_FUNCTION (line 5541) | ZEND_FUNCTION(fastdfs_storage_append_by_filebuff)
  function ZEND_FUNCTION (line 5553) | ZEND_FUNCTION(fastdfs_storage_append_by_filebuff1)
  function ZEND_FUNCTION (line 5565) | ZEND_FUNCTION(fastdfs_storage_append_by_callback)
  function ZEND_FUNCTION (line 5577) | ZEND_FUNCTION(fastdfs_storage_append_by_callback1)
  function ZEND_FUNCTION (line 5589) | ZEND_FUNCTION(fastdfs_storage_modify_by_filename)
  function ZEND_FUNCTION (line 5601) | ZEND_FUNCTION(fastdfs_storage_modify_by_filename1)
  function ZEND_FUNCTION (line 5613) | ZEND_FUNCTION(fastdfs_storage_modify_by_filebuff)
  function ZEND_FUNCTION (line 5625) | ZEND_FUNCTION(fastdfs_storage_modify_by_filebuff1)
  function ZEND_FUNCTION (line 5637) | ZEND_FUNCTION(fastdfs_storage_modify_by_callback)
  function ZEND_FUNCTION (line 5649) | ZEND_FUNCTION(fastdfs_storage_modify_by_callback1)
  function ZEND_FUNCTION (line 5660) | ZEND_FUNCTION(fastdfs_storage_regenerate_appender_filename)
  function ZEND_FUNCTION (line 5671) | ZEND_FUNCTION(fastdfs_storage_regenerate_appender_filename1)
  function ZEND_FUNCTION (line 5683) | ZEND_FUNCTION(fastdfs_storage_upload_appender_by_filename)
  function ZEND_FUNCTION (line 5696) | ZEND_FUNCTION(fastdfs_storage_upload_appender_by_filename1)
  function ZEND_FUNCTION (line 5709) | ZEND_FUNCTION(fastdfs_storage_upload_appender_by_filebuff)
  function ZEND_FUNCTION (line 5722) | ZEND_FUNCTION(fastdfs_storage_upload_appender_by_filebuff1)
  function ZEND_FUNCTION (line 5735) | ZEND_FUNCTION(fastdfs_storage_upload_appender_by_callback)
  function ZEND_FUNCTION (line 5748) | ZEND_FUNCTION(fastdfs_storage_upload_appender_by_callback1)
  function ZEND_FUNCTION (line 5762) | ZEND_FUNCTION(fastdfs_storage_upload_slave_by_filename)
  function ZEND_FUNCTION (line 5775) | ZEND_FUNCTION(fastdfs_storage_upload_slave_by_filename1)
  function ZEND_FUNCTION (line 5789) | ZEND_FUNCTION(fastdfs_storage_upload_slave_by_filebuff)
  function ZEND_FUNCTION (line 5802) | ZEND_FUNCTION(fastdfs_storage_upload_slave_by_filebuff1)
  function ZEND_FUNCTION (line 5816) | ZEND_FUNCTION(fastdfs_storage_upload_slave_by_callback)
  function ZEND_FUNCTION (line 5830) | ZEND_FUNCTION(fastdfs_storage_upload_slave_by_callback1)
  function ZEND_FUNCTION (line 5842) | ZEND_FUNCTION(fastdfs_storage_delete_file)
  function ZEND_FUNCTION (line 5853) | ZEND_FUNCTION(fastdfs_storage_delete_file1)
  function ZEND_FUNCTION (line 5865) | ZEND_FUNCTION(fastdfs_storage_truncate_file)
  function ZEND_FUNCTION (line 5877) | ZEND_FUNCTION(fastdfs_storage_truncate_file1)
  function ZEND_FUNCTION (line 5889) | ZEND_FUNCTION(fastdfs_storage_download_file_to_buff)
  function ZEND_FUNCTION (line 5901) | ZEND_FUNCTION(fastdfs_storage_download_file_to_buff1)
  function ZEND_FUNCTION (line 5913) | ZEND_FUNCTION(fastdfs_storage_download_file_to_callback)
  function ZEND_FUNCTION (line 5925) | ZEND_FUNCTION(fastdfs_storage_download_file_to_callback1)
  function ZEND_FUNCTION (line 5937) | ZEND_FUNCTION(fastdfs_storage_download_file_to_file)
  function ZEND_FUNCTION (line 5949) | ZEND_FUNCTION(fastdfs_storage_download_file_to_file1)
  function ZEND_FUNCTION (line 5961) | ZEND_FUNCTION(fastdfs_storage_set_metadata)
  function ZEND_FUNCTION (line 5972) | ZEND_FUNCTION(fastdfs_storage_set_metadata1)
  function ZEND_FUNCTION (line 5983) | ZEND_FUNCTION(fastdfs_storage_get_metadata)
  function ZEND_FUNCTION (line 5994) | ZEND_FUNCTION(fastdfs_storage_get_metadata1)
  function ZEND_FUNCTION (line 6005) | ZEND_FUNCTION(fastdfs_storage_file_exist)
  function ZEND_FUNCTION (line 6016) | ZEND_FUNCTION(fastdfs_storage_file_exist1)
  function ZEND_FUNCTION (line 6026) | ZEND_FUNCTION(fastdfs_http_gen_token)
  function ZEND_FUNCTION (line 6037) | ZEND_FUNCTION(fastdfs_get_file_info)
  function ZEND_FUNCTION (line 6047) | ZEND_FUNCTION(fastdfs_get_file_info1)
  function ZEND_FUNCTION (line 6057) | ZEND_FUNCTION(fastdfs_send_data)
  function ZEND_FUNCTION (line 6068) | ZEND_FUNCTION(fastdfs_gen_slave_filename)
  function php_fdfs_close (line 6074) | static void php_fdfs_close(php_fdfs_t *i_obj TSRMLS_DC)
  function php_fdfs_destroy (line 6087) | static void php_fdfs_destroy(php_fdfs_t *i_obj TSRMLS_DC)
  function php_fdfs_free_storage (line 7374) | static void php_fdfs_free_storage(void *object TSRMLS_DC)
  function php_fdfs_free_storage (line 7382) | static void php_fdfs_free_storage(zend_object *object)
  function zend_object_value (line 7392) | zend_object_value php_fdfs_new(zend_class_entry *ce TSRMLS_DC)
  function zend_object (line 7410) | zend_object* php_fdfs_new(zend_class_entry *ce)
  function PHP_FASTDFS_API (line 7424) | PHP_FASTDFS_API zend_class_entry *php_fdfs_get_ce(void)
  function PHP_FASTDFS_API (line 7429) | PHP_FASTDFS_API zend_class_entry *php_fdfs_get_exception(void)
  function PHP_FASTDFS_API (line 7434) | PHP_FASTDFS_API zend_class_entry *php_fdfs_get_exception_base(int root T...
  function load_config_files (line 7470) | static int load_config_files()
  function PHP_MINIT_FUNCTION (line 7741) | PHP_MINIT_FUNCTION(fastdfs_client)
  function PHP_MSHUTDOWN_FUNCTION (line 7816) | PHP_MSHUTDOWN_FUNCTION(fastdfs_client)
  function PHP_RINIT_FUNCTION (line 7846) | PHP_RINIT_FUNCTION(fastdfs_client)
  function PHP_RSHUTDOWN_FUNCTION (line 7851) | PHP_RSHUTDOWN_FUNCTION(fastdfs_client)
  function PHP_MINFO_FUNCTION (line 7857) | PHP_MINFO_FUNCTION(fastdfs_client)

FILE: python_client/examples/appender_example.py
  function main (line 12) | def main():

FILE: python_client/examples/basic_usage.py
  function main (line 13) | def main():

FILE: python_client/examples/meta_example.py
  function main (line 15) | def main():

FILE: python_client/fdfs/client.py
  class ClientConfig (line 18) | class ClientConfig:
  class Client (line 38) | class Client:
    method __init__ (line 54) | def __init__(self, config: ClientConfig):
    method _validate_config (line 93) | def _validate_config(self, config: ClientConfig) -> None:
    method _check_closed (line 105) | def _check_closed(self) -> None:
    method upload_file (line 111) | def upload_file(self, local_filename: str, metadata: Optional[Dict[str...
    method upload_buffer (line 130) | def upload_buffer(self, data: bytes, file_ext_name: str,
    method upload_appender_file (line 150) | def upload_appender_file(self, local_filename: str,
    method upload_appender_buffer (line 172) | def upload_appender_buffer(self, data: bytes, file_ext_name: str,
    method download_file (line 192) | def download_file(self, file_id: str) -> bytes:
    method download_file_range (line 211) | def download_file_range(self, file_id: str, offset: int, length: int) ...
    method download_to_file (line 232) | def download_to_file(self, file_id: str, local_filename: str) -> None:
    method delete_file (line 250) | def delete_file(self, file_id: str) -> None:
    method set_metadata (line 266) | def set_metadata(self, file_id: str, metadata: Dict[str, str],
    method get_metadata (line 285) | def get_metadata(self, file_id: str) -> Dict[str, str]:
    method get_file_info (line 304) | def get_file_info(self, file_id: str) -> FileInfo:
    method file_exists (line 323) | def file_exists(self, file_id: str) -> bool:
    method close (line 345) | def close(self) -> None:
    method __enter__ (line 364) | def __enter__(self):
    method __exit__ (line 368) | def __exit__(self, exc_type, exc_val, exc_tb):

FILE: python_client/fdfs/connection.py
  class Connection (line 17) | class Connection:
    method __init__ (line 25) | def __init__(self, sock: socket.socket, addr: str):
    method send (line 38) | def send(self, data: bytes, timeout: float = 30.0) -> None:
    method receive (line 70) | def receive(self, size: int, timeout: float = 30.0) -> bytes:
    method receive_full (line 104) | def receive_full(self, size: int, timeout: float = 30.0) -> bytes:
    method close (line 141) | def close(self) -> None:
    method is_alive (line 154) | def is_alive(self) -> bool:
    method get_last_used (line 174) | def get_last_used(self) -> float:
    method get_addr (line 184) | def get_addr(self) -> str:
  class ConnectionPool (line 194) | class ConnectionPool:
    method __init__ (line 205) | def __init__(self, addrs: List[str], max_conns: int = 10,
    method get (line 228) | def get(self, addr: Optional[str] = None) -> Connection:
    method _create_connection (line 271) | def _create_connection(self, addr: str) -> Connection:
    method put (line 299) | def put(self, conn: Optional[Connection]) -> None:
    method _clean_pool (line 344) | def _clean_pool(self, addr: str) -> None:
    method add_addr (line 366) | def add_addr(self, addr: str) -> None:
    method close (line 386) | def close(self) -> None:

FILE: python_client/fdfs/errors.py
  class FastDFSError (line 9) | class FastDFSError(Exception):
  class ClientClosedError (line 14) | class ClientClosedError(FastDFSError):
    method __init__ (line 16) | def __init__(self):
  class FileNotFoundError (line 20) | class FileNotFoundError(FastDFSError):
    method __init__ (line 22) | def __init__(self, file_id: str = ""):
  class NoStorageServerError (line 27) | class NoStorageServerError(FastDFSError):
    method __init__ (line 29) | def __init__(self):
  class ConnectionTimeoutError (line 33) | class ConnectionTimeoutError(FastDFSError):
    method __init__ (line 35) | def __init__(self, addr: str = ""):
  class NetworkTimeoutError (line 40) | class NetworkTimeoutError(FastDFSError):
    method __init__ (line 42) | def __init__(self, operation: str = ""):
  class InvalidFileIDError (line 47) | class InvalidFileIDError(FastDFSError):
    method __init__ (line 49) | def __init__(self, file_id: str = ""):
  class InvalidResponseError (line 54) | class InvalidResponseError(FastDFSError):
    method __init__ (line 56) | def __init__(self, details: str = ""):
  class StorageServerOfflineError (line 61) | class StorageServerOfflineError(FastDFSError):
    method __init__ (line 63) | def __init__(self, addr: str = ""):
  class TrackerServerOfflineError (line 68) | class TrackerServerOfflineError(FastDFSError):
    method __init__ (line 70) | def __init__(self, addr: str = ""):
  class InsufficientSpaceError (line 75) | class InsufficientSpaceError(FastDFSError):
    method __init__ (line 77) | def __init__(self):
  class FileAlreadyExistsError (line 81) | class FileAlreadyExistsError(FastDFSError):
    method __init__ (line 83) | def __init__(self, file_id: str = ""):
  class InvalidMetadataError (line 88) | class InvalidMetadataError(FastDFSError):
    method __init__ (line 90) | def __init__(self, details: str = ""):
  class OperationNotSupportedError (line 95) | class OperationNotSupportedError(FastDFSError):
    method __init__ (line 97) | def __init__(self, operation: str = ""):
  class InvalidArgumentError (line 102) | class InvalidArgumentError(FastDFSError):
    method __init__ (line 104) | def __init__(self, details: str = ""):
  class ProtocolError (line 109) | class ProtocolError(FastDFSError):
    method __init__ (line 117) | def __init__(self, code: int, message: str = ""):
  class NetworkError (line 123) | class NetworkError(FastDFSError):
    method __init__ (line 132) | def __init__(self, operation: str, addr: str, original_error: Exception):
  function map_status_to_error (line 139) | def map_status_to_error(status: int) -> Optional[FastDFSError]:

FILE: python_client/fdfs/operations.py
  class Operations (line 46) | class Operations:
    method __init__ (line 53) | def __init__(self, tracker_pool: ConnectionPool, storage_pool: Connect...
    method upload_file (line 69) | def upload_file(self, local_filename: str, metadata: Optional[Dict[str...
    method upload_buffer (line 86) | def upload_buffer(self, data: bytes, file_ext_name: str,
    method _upload_buffer_internal (line 109) | def _upload_buffer_internal(self, data: bytes, file_ext_name: str,
    method _get_storage_server (line 172) | def _get_storage_server(self, group_name: str) -> StorageServer:
    method download_file (line 235) | def download_file(self, file_id: str, offset: int = 0, length: int = 0...
    method _download_file_internal (line 255) | def _download_file_internal(self, file_id: str, offset: int, length: i...
    method _get_download_storage_server (line 297) | def _get_download_storage_server(self, group_name: str, remote_filenam...
    method download_to_file (line 347) | def download_to_file(self, file_id: str, local_filename: str) -> None:
    method delete_file (line 358) | def delete_file(self, file_id: str) -> None:
    method _delete_file_internal (line 374) | def _delete_file_internal(self, file_id: str) -> None:
    method set_metadata (line 409) | def set_metadata(self, file_id: str, metadata: Dict[str, str], flag: M...
    method get_metadata (line 460) | def get_metadata(self, file_id: str) -> Dict[str, str]:
    method get_file_info (line 511) | def get_file_info(self, file_id: str) -> FileInfo:

FILE: python_client/fdfs/protocol.py
  function encode_header (line 26) | def encode_header(length: int, cmd: int, status: int = 0) -> bytes:
  function decode_header (line 49) | def decode_header(data: bytes) -> TrackerHeader:
  function split_file_id (line 74) | def split_file_id(file_id: str) -> Tuple[str, str]:
  function join_file_id (line 108) | def join_file_id(group_name: str, remote_filename: str) -> str:
  function encode_metadata (line 124) | def encode_metadata(metadata: Optional[Dict[str, str]]) -> bytes:
  function decode_metadata (line 159) | def decode_metadata(data: bytes) -> Dict[str, str]:
  function get_file_ext_name (line 195) | def get_file_ext_name(filename: str) -> str:
  function read_file_content (line 224) | def read_file_content(filename: str) -> bytes:
  function write_file_content (line 242) | def write_file_content(filename: str, data: bytes) -> None:
  function pad_string (line 262) | def pad_string(s: str, length: int) -> bytes:
  function unpad_string (line 283) | def unpad_string(data: bytes) -> str:
  function encode_int64 (line 299) | def encode_int64(n: int) -> bytes:
  function decode_int64 (line 314) | def decode_int64(data: bytes) -> int:
  function encode_int32 (line 331) | def encode_int32(n: int) -> bytes:
  function decode_int32 (line 344) | def decode_int32(data: bytes) -> int:

FILE: python_client/fdfs/types.py
  class TrackerCommand (line 36) | class TrackerCommand(IntEnum):
  class StorageCommand (line 56) | class StorageCommand(IntEnum):
  class StorageStatus (line 71) | class StorageStatus(IntEnum):
  class MetadataFlag (line 85) | class MetadataFlag(IntEnum):
  class FileInfo (line 92) | class FileInfo:
  class StorageServer (line 109) | class StorageServer:
  class TrackerHeader (line 124) | class TrackerHeader:
  class UploadResponse (line 139) | class UploadResponse:

FILE: python_client/tests/test_client.py
  class TestClientConfig (line 15) | class TestClientConfig(unittest.TestCase):
    method test_config_defaults (line 18) | def test_config_defaults(self):
    method test_config_custom_values (line 28) | def test_config_custom_values(self):
  class TestClient (line 46) | class TestClient(unittest.TestCase):
    method test_client_creation_valid_config (line 49) | def test_client_creation_valid_config(self):
    method test_client_creation_invalid_config (line 59) | def test_client_creation_invalid_config(self):
    method test_client_close (line 71) | def test_client_close(self):
    method test_client_close_idempotent (line 83) | def test_client_close_idempotent(self):
    method test_client_context_manager (line 91) | def test_client_context_manager(self):
    method test_upload_buffer (line 101) | def test_upload_buffer(self, mock_upload):
    method test_download_file (line 116) | def test_download_file(self, mock_download):
    method test_delete_file (line 131) | def test_delete_file(self, mock_delete):
    method test_file_exists (line 143) | def test_file_exists(self, mock_get_info):

FILE: python_client/tests/test_connection.py
  class TestConnection (line 13) | class TestConnection(unittest.TestCase):
    method test_connection_creation (line 16) | def test_connection_creation(self):
    method test_connection_last_used (line 50) | def test_connection_last_used(self):
  class TestConnectionPool (line 64) | class TestConnectionPool(unittest.TestCase):
    method test_pool_creation (line 67) | def test_pool_creation(self):
    method test_pool_add_addr (line 77) | def test_pool_add_addr(self):
    method test_pool_close (line 90) | def test_pool_close(self):
    method test_pool_close_idempotent (line 99) | def test_pool_close_idempotent(self):

FILE: python_client/tests/test_integration.py
  class TestIntegration (line 20) | class TestIntegration(unittest.TestCase):
    method setUpClass (line 24) | def setUpClass(cls):
    method tearDownClass (line 31) | def tearDownClass(cls):
    method test_upload_download_delete_cycle (line 35) | def test_upload_download_delete_cycle(self):
    method test_upload_file_from_disk (line 55) | def test_upload_file_from_disk(self):
    method test_download_to_file (line 77) | def test_download_to_file(self):
    method test_metadata_operations (line 99) | def test_metadata_operations(self):
    method test_file_info (line 131) | def test_file_info(self):
    method test_file_exists (line 148) | def test_file_exists(self):
    method test_download_range (line 161) | def test_download_range(self):

FILE: python_client/tests/test_protocol.py
  class TestProtocol (line 22) | class TestProtocol(unittest.TestCase):
    method test_encode_decode_header (line 25) | def test_encode_decode_header(self):
    method test_decode_header_short_data (line 39) | def test_decode_header_short_data(self):
    method test_split_file_id_valid (line 44) | def test_split_file_id_valid(self):
    method test_split_file_id_invalid (line 52) | def test_split_file_id_invalid(self):
    method test_join_file_id (line 66) | def test_join_file_id(self):
    method test_encode_decode_metadata (line 74) | def test_encode_decode_metadata(self):
    method test_encode_metadata_empty (line 91) | def test_encode_metadata_empty(self):
    method test_decode_metadata_empty (line 99) | def test_decode_metadata_empty(self):
    method test_get_file_ext_name (line 104) | def test_get_file_ext_name(self):
    method test_pad_unpad_string (line 118) | def test_pad_unpad_string(self):
    method test_pad_string_truncate (line 129) | def test_pad_string_truncate(self):
    method test_encode_decode_int64 (line 137) | def test_encode_decode_int64(self):
    method test_decode_int64_short_data (line 148) | def test_decode_int64_short_data(self):

FILE: ruby_client/examples/basic_usage.rb
  function main (line 18) | def main

FILE: ruby_client/examples/metadata_example.rb
  function main (line 18) | def main

FILE: ruby_client/examples/upload_buffer.rb
  function main (line 18) | def main

FILE: ruby_client/lib/fastdfs.rb
  type FastDFS (line 67) | module FastDFS

FILE: ruby_client/lib/fastdfs/client.rb
  type FastDFS (line 54) | module FastDFS
    class Client (line 78) | class Client
      method initialize (line 109) | def initialize(config)
      method upload_file (line 190) | def upload_file(local_filename, metadata = nil)
      method upload_buffer (line 228) | def upload_buffer(data, file_ext_name, metadata = nil)
      method upload_appender_file (line 264) | def upload_appender_file(local_filename, metadata = nil)
      method upload_appender_buffer (line 289) | def upload_appender_buffer(data, file_ext_name, metadata = nil)
      method upload_slave_file (line 335) | def upload_slave_file(master_file_id, prefix_name, file_ext_name, da...
      method download_file (line 369) | def download_file(file_id)
      method download_file_range (line 408) | def download_file_range(file_id, offset, length)
      method download_to_file (line 441) | def download_to_file(file_id, local_filename)
      method delete_file (line 469) | def delete_file(file_id)
      method append_file (line 507) | def append_file(file_id, data)
      method modify_file (line 545) | def modify_file(file_id, offset, data)
      method truncate_file (line 582) | def truncate_file(file_id, size)
      method set_metadata (line 626) | def set_metadata(file_id, metadata, flag = :overwrite)
      method get_metadata (line 664) | def get_metadata(file_id)
      method get_file_info (line 697) | def get_file_info(file_id)
      method file_exists? (line 732) | def file_exists?(file_id)
      method close (line 770) | def close
      method closed? (line 825) | def closed?
      method _validate_config (line 843) | def _validate_config(config)
      method _check_closed (line 933) | def _check_closed

FILE: ruby_client/lib/fastdfs/client_config.rb
  type FastDFS (line 12) | module FastDFS
    class ClientConfig (line 33) | class ClientConfig
      method initialize (line 120) | def initialize(options = {})
      method to_s (line 196) | def to_s
      method to_h (line 214) | def to_h
      method == (line 233) | def ==(other)
      method hash (line 251) | def hash
      method eql? (line 263) | def eql?(other)

FILE: ruby_client/lib/fastdfs/connection_pool.rb
  type FastDFS (line 19) | module FastDFS
    class Connection (line 28) | class Connection
      method initialize (line 36) | def initialize(sock, addr)
      method send (line 70) | def send(data, timeout = 30.0)
      method receive (line 132) | def receive(size, timeout = 30.0)
      method receive_full (line 185) | def receive_full(size, timeout = 30.0)
      method close (line 250) | def close
      method alive? (line 284) | def alive?
    class ConnectionPool (line 338) | class ConnectionPool
      method initialize (line 349) | def initialize(addrs:, max_conns: 10, connect_timeout: 5.0, idle_tim...
      method get (line 405) | def get(addr = nil)
      method put (line 529) | def put(conn)
      method close (line 611) | def close
      method closed? (line 652) | def closed?

FILE: ruby_client/lib/fastdfs/errors.rb
  type FastDFS (line 15) | module FastDFS
    class Error (line 27) | class Error < StandardError
    class ClientClosedError (line 42) | class ClientClosedError < Error
      method initialize (line 46) | def initialize(message = "client is closed")
    class FileNotFoundError (line 63) | class FileNotFoundError < Error
      method initialize (line 67) | def initialize(message = "file not found")
    class NoStorageServerError (line 84) | class NoStorageServerError < Error
      method initialize (line 88) | def initialize(message = "no storage server available")
    class ConnectionTimeoutError (line 104) | class ConnectionTimeoutError < Error
      method initialize (line 108) | def initialize(message = "connection timeout")
    class NetworkTimeoutError (line 124) | class NetworkTimeoutError < Error
      method initialize (line 128) | def initialize(message = "network timeout")
    class InvalidFileIDError (line 145) | class InvalidFileIDError < Error
      method initialize (line 149) | def initialize(message = "invalid file ID")
    class InvalidResponseError (line 166) | class InvalidResponseError < Error
      method initialize (line 170) | def initialize(message = "invalid response from server")
    class StorageServerOfflineError (line 186) | class StorageServerOfflineError < Error
      method initialize (line 190) | def initialize(message = "storage server is offline")
    class TrackerServerOfflineError (line 206) | class TrackerServerOfflineError < Error
      method initialize (line 210) | def initialize(message = "tracker server is offline")
    class InsufficientSpaceError (line 226) | class InsufficientSpaceError < Error
      method initialize (line 230) | def initialize(message = "insufficient storage space")
    class FileAlreadyExistsError (line 247) | class FileAlreadyExistsError < Error
      method initialize (line 251) | def initialize(message = "file already exists")
    class InvalidMetadataError (line 268) | class InvalidMetadataError < Error
      method initialize (line 272) | def initialize(message = "invalid metadata")
    class OperationNotSupportedError (line 290) | class OperationNotSupportedError < Error
      method initialize (line 294) | def initialize(message = "operation not supported")
    class InvalidArgumentError (line 311) | class InvalidArgumentError < Error
      method initialize (line 315) | def initialize(message = "invalid argument")
    class ProtocolError (line 335) | class ProtocolError < Error
      method initialize (line 345) | def initialize(code, message)
    class NetworkError (line 366) | class NetworkError < Error
      method initialize (line 387) | def initialize(op, addr, original_error)
    class StorageError (line 406) | class StorageError < Error
      method initialize (line 421) | def initialize(server, original_error)
    class TrackerError (line 439) | class TrackerError < Error
      method initialize (line 454) | def initialize(server, original_error)
    function map_status_to_error (line 480) | def self.map_status_to_error(status)

FILE: ruby_client/lib/fastdfs/operations.rb
  type FastDFS (line 21) | module FastDFS
    class Operations (line 30) | class Operations
      method initialize (line 40) | def initialize(tracker_pool:, storage_pool:, network_timeout:, retry...
      method upload_file (line 73) | def upload_file(local_filename, metadata, is_appender: false)
      method upload_buffer (line 125) | def upload_buffer(data, file_ext_name, metadata, is_appender: false)
      method download_file (line 194) | def download_file(file_id, offset: 0, length: 0)
      method download_to_file (line 256) | def download_to_file(file_id, local_filename)
      method delete_file (line 295) | def delete_file(file_id)
      method upload_slave_file (line 341) | def upload_slave_file(master_file_id, prefix_name, file_ext_name, da...
      method append_file (line 348) | def append_file(file_id, data)
      method modify_file (line 355) | def modify_file(file_id, offset, data)
      method truncate_file (line 362) | def truncate_file(file_id, size)
      method set_metadata (line 369) | def set_metadata(file_id, metadata, flag)
      method get_metadata (line 376) | def get_metadata(file_id)
      method get_file_info (line 383) | def get_file_info(file_id)
      method _upload_buffer_internal (line 392) | def _upload_buffer_internal(data, file_ext_name, metadata, is_appender)
      method _download_file_internal (line 399) | def _download_file_internal(file_id, offset, length)
      method _delete_file_internal (line 406) | def _delete_file_internal(file_id)

FILE: ruby_client/lib/fastdfs/protocol.rb
  type FastDFS (line 18) | module FastDFS
    type Protocol (line 26) | module Protocol
      function encode_header (line 39) | def encode_header(body_len, cmd, status = 0)
      function decode_header (line 78) | def decode_header(header)
      function encode_int64 (line 118) | def encode_int64(value)
      function decode_int64 (line 146) | def decode_int64(data)
      function pad_string (line 181) | def pad_string(str, len)
      function unpad_string (line 217) | def unpad_string(str)
      function split_file_id (line 241) | def split_file_id(file_id)
      function join_file_id (line 291) | def join_file_id(group_name, remote_filename)
      function encode_metadata (line 319) | def encode_metadata(metadata)
      function decode_metadata (line 389) | def decode_metadata(data)

FILE: ruby_client/lib/fastdfs/types.rb
  type FastDFS (line 16) | module FastDFS
    type TrackerCommand (line 54) | module TrackerCommand
    type StorageCommand (line 108) | module StorageCommand
    type StorageStatus (line 146) | module StorageStatus
    type MetadataFlag (line 181) | module MetadataFlag
    class FileInfo (line 201) | class FileInfo
      method initialize (line 232) | def initialize(file_size, create_time, crc32, source_ip_addr)
      method to_s (line 253) | def to_s
      method == (line 262) | def ==(other)
      method hash (line 274) | def hash
      method eql? (line 283) | def eql?(other)
    class StorageServer (line 297) | class StorageServer
      method initialize (line 321) | def initialize(ip_addr, port, store_path_index = 0)
      method address (line 338) | def address
      method to_s (line 345) | def to_s
      method == (line 354) | def ==(other)
      method hash (line 365) | def hash
      method eql? (line 374) | def eql?(other)
    class TrackerHeader (line 385) | class TrackerHeader
      method initialize (line 406) | def initialize(length, cmd, status = 0)
      method to_s (line 423) | def to_s
      method == (line 432) | def ==(other)
      method hash (line 443) | def hash
      method eql? (line 452) | def eql?(other)
    class UploadResponse (line 461) | class UploadResponse
      method initialize (line 476) | def initialize(group_name, remote_filename)
      method file_id (line 489) | def file_id
      method to_s (line 496) | def to_s
      method == (line 505) | def ==(other)
      method hash (line 515) | def hash
      method eql? (line 524) | def eql?(other)

FILE: rust_client/benches/benchmark.rs
  function bench_upload_small_file (line 19) | fn bench_upload_small_file(c: &mut Criterion) {
  function bench_upload_medium_file (line 53) | fn bench_upload_medium_file(c: &mut Criterion) {
  function bench_download_file (line 95) | fn bench_download_file(c: &mut Criterion) {
  function bench_metadata_operations (line 127) | fn bench_metadata_operations(c: &mut Criterion) {
  function bench_concurrent_uploads (line 179) | fn bench_concurrent_uploads(c: &mut Criterion) {

FILE: rust_client/examples/advanced_metadata_example.rs
  type MetadataSchema (line 42) | struct MetadataSchema {
    method new (line 55) | fn new() -> Self {
    method validate (line 93) | fn validate(&self, metadata: &HashMap<String, String>) -> Vec<String> {
  type MetadataFilter (line 126) | struct MetadataFilter {
    method new (line 141) | fn new() -> Self {
    method with_exact_match (line 152) | fn with_exact_match(mut self, key: &str, value: &str) -> Self {
    method with_required_key (line 159) | fn with_required_key(mut self, key: &str) -> Self {
    method with_excluded_key (line 166) | fn with_excluded_key(mut self, key: &str) -> Self {
    method with_partial_match (line 173) | fn with_partial_match(mut self, key: &str, value: &str) -> Self {
    method matches (line 180) | fn matches(&self, metadata: &HashMap<String, String>) -> bool {
  type WorkflowAction (line 228) | enum WorkflowAction {
  type WorkflowRule (line 243) | struct WorkflowRule {
  type WorkflowEngine (line 254) | struct WorkflowEngine {
    method new (line 263) | fn new() -> Self {
    method add_rule (line 271) | fn add_rule(mut self, rule: WorkflowRule) -> Self {
    method process (line 278) | fn process(&self, metadata: &HashMap<String, String>) -> Option<&Workf...
  function main (line 298) | async fn main() -> Result<(), Box<dyn std::error::Error>> {

FILE: rust_client/examples/appender_example.rs
  function main (line 19) | async fn main() -> Result<(), Box<dyn std::error::Error>> {

FILE: rust_client/examples/basic_usage.rs
  function main (line 18) | async fn main() -> Result<(), Box<dyn std::error::Error>> {

FILE: rust_client/examples/batch_operations_example.rs
  function main (line 31) | async fn main() -> Result<(), Box<dyn std::error::Error>> {

FILE: rust_client/examples/cancellation_example.rs
  function check_cancellation (line 50) | fn check_cancellation(token: &CancellationToken) -> Result<(), Box<dyn s...
  function simulate_long_upload (line 59) | async fn simulate_long_upload(
  function simulate_long_download (line 99) | async fn simulate_long_download(
  function main (line 131) | async fn main() -> Result<(), Box<dyn std::error::Error>> {

FILE: rust_client/examples/concurrent_operations_example.rs
  function main (line 30) | async fn main() -> Result<(), Box<dyn std::error::Error>> {

FILE: rust_client/examples/configuration_example.rs
  type Environment (line 45) | enum Environment {
  function get_environment (line 56) | fn get_environment() -> Environment {
  function create_development_config (line 85) | fn create_development_config() -> ClientConfig {
  function create_staging_config (line 113) | fn create_staging_config() -> ClientConfig {
  function create_production_config (line 144) | fn create_production_config() -> ClientConfig {
  function create_high_performance_config (line 182) | fn create_high_performance_config() -> ClientConfig {
  function create_high_availability_config (line 212) | fn create_high_availability_config() -> ClientConfig {
  function create_low_latency_config (line 243) | fn create_low_latency_config() -> ClientConfig {
  function create_resource_constrained_config (line 273) | fn create_resource_constrained_config() -> ClientConfig {
  function main (line 302) | async fn main() -> Result<(), Box<dyn std::error::Error>> {

FILE: rust_client/examples/connection_pool_example.rs
  function main (line 30) | async fn main() -> Result<(), Box<dyn std::error::Error>> {

FILE: rust_client/examples/error_handling_example.rs
  function main (line 30) | async fn main() -> Result<(), Box<dyn std::error::Error>> {

FILE: rust_client/examples/file_info_example.rs
  function main (line 38) | async fn main() -> Result<(), Box<dyn std::error::Error>> {

FILE: rust_client/examples/integration_example.rs
  type AppConfig (line 35) | pub struct AppConfig {
    method from_env (line 53) | pub fn from_env() -> Result<Self, Box<dyn std::error::Error>> {
    method to_client_config (line 92) | pub fn to_client_config(&self) -> ClientConfig {
  type AppState (line 107) | pub struct AppState {
    method new (line 117) | pub fn new(config: AppConfig) -> Result<Self, Box<dyn std::error::Erro...
  type FileService (line 130) | pub struct FileService {
    method new (line 136) | pub fn new(client: Arc<Client>) -> Self {
    method upload_file (line 141) | pub async fn upload_file(
    method download_file (line 153) | pub async fn download_file(&self, file_id: &str) -> Result<Vec<u8>, Se...
    method get_file_info (line 162) | pub async fn get_file_info(&self, file_id: &str) -> Result<fastdfs::Fi...
    method delete_file (line 170) | pub async fn delete_file(&self, file_id: &str) -> Result<(), ServiceEr...
  type ServiceError (line 185) | pub enum ServiceError {
    method from (line 197) | fn from(err: FastDFSError) -> Self {
    method fmt (line 212) | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  function init_logging (line 230) | pub fn init_logging(config: &AppConfig) {
  function log_info (line 242) | fn log_info(event: &str, message: &str) {
  function log_error (line 247) | fn log_error(event: &str, error: &dyn std::error::Error) {
  function log_warn (line 252) | fn log_warn(event: &str, message: &str) {
  function main (line 263) | async fn main() -> Result<(), Box<dyn std::error::Error>> {
  method clone (line 503) | fn clone(&self) -> Self {

FILE: rust_client/examples/metadata_example.rs
  function main (line 22) | async fn main() -> Result<(), Box<dyn std::error::Error>> {

FILE: rust_client/examples/partial_download_example.rs
  function main (line 30) | async fn main() -> Result<(), Box<dyn std::error::Error>> {

FILE: rust_client/examples/performance_example.rs
  type OperationMetrics (line 38) | pub struct OperationMetrics {
  type PerformanceStats (line 53) | pub struct PerformanceStats {
    method from_metrics (line 78) | pub fn from_metrics(metrics: &[OperationMetrics]) -> Self {
    method print (line 137) | pub fn print(&self) {
  function benchmark_connection_pool_sizes (line 161) | async fn benchmark_connection_pool_sizes(
  function benchmark_batch_operations (line 246) | async fn benchmark_batch_operations(
  function benchmark_concurrent_batch (line 307) | async fn benchmark_concurrent_batch(
  function benchmark_memory_patterns (line 388) | async fn benchmark_memory_patterns(
  function benchmark_optimization_techniques (line 451) | async fn benchmark_optimization_techniques(
  function demonstrate_criterion_usage (line 566) | fn demonstrate_criterion_usage() {
  function main (line 615) | async fn main() -> Result<(), Box<dyn std::error::Error>> {

FILE: rust_client/examples/slave_file_example.rs
  function main (line 28) | async fn main() -> Result<(), Box<dyn std::error::Error>> {

FILE: rust_client/examples/streaming_example.rs
  type Progress (line 57) | struct Progress {
    method new (line 70) | fn new(total: u64) -> Self {
    method update (line 80) | fn update(&mut self, bytes: u64) {
    method percentage (line 86) | fn percentage(&self) -> f64 {
    method bytes_per_second (line 95) | fn bytes_per_second(&self) -> f64 {
    method format_bytes (line 105) | fn format_bytes(bytes: u64) -> String {
    method print (line 119) | fn print(&self) {
  function upload_file_chunked (line 149) | async fn upload_file_chunked(
  function download_file_chunked (line 208) | async fn download_file_chunked(
  function create_chunk_stream (line 279) | fn create_chunk_stream(
  function process_stream_with_progress (line 294) | async fn process_stream_with_progress<S>(
  type MemoryReader (line 336) | struct MemoryReader {
  method poll_read (line 344) | fn poll_read(
  type MemoryWriter (line 365) | struct MemoryWriter {
  method poll_write (line 372) | fn poll_write(
  method poll_flush (line 382) | fn poll_flush(
  method poll_shutdown (line 390) | fn poll_shutdown(
  function copy_with_progress (line 401) | async fn copy_with_progress<R, W>(
  function stream_with_backpressure (line 456) | async fn stream_with_backpressure<S>(
  function main (line 518) | async fn main() -> Result<(), Box<dyn std::error::Error>> {

FILE: rust_client/examples/upload_buffer_example.rs
  function generate_json_content (line 49) | fn generate_json_content() -> String {
  function generate_xml_content (line 68) | fn generate_xml_content() -> String {
  function generate_csv_content (line 92) | fn generate_csv_content() -> String {
  function generate_binary_content (line 110) | fn generate_binary_content(size: usize) -> Vec<u8> {
  function generate_text_content (line 118) | fn generate_text_content() -> String {
  function main (line 146) | async fn main() -> Result<(), Box<dyn std::error::Error>> {

FILE: rust_client/src/client.rs
  type Client (line 37) | pub struct Client {
    method new (line 47) | pub fn new(config: ClientConfig) -> Result<Self> {
    method validate_config (line 81) | fn validate_config(config: &ClientConfig) -> Result<()> {
    method check_closed (line 101) | async fn check_closed(&self) -> Result<()> {
    method upload_file (line 110) | pub async fn upload_file(&self, local_filename: &str, metadata: Option...
    method upload_buffer (line 116) | pub async fn upload_buffer(
    method upload_appender_file (line 127) | pub async fn upload_appender_file(
    method upload_appender_buffer (line 137) | pub async fn upload_appender_buffer(
    method download_file (line 148) | pub async fn download_file(&self, file_id: &str) -> Result<Bytes> {
    method download_file_range (line 154) | pub async fn download_file_range(&self, file_id: &str, offset: u64, le...
    method download_to_file (line 160) | pub async fn download_to_file(&self, file_id: &str, local_filename: &s...
    method delete_file (line 166) | pub async fn delete_file(&self, file_id: &str) -> Result<()> {
    method set_metadata (line 172) | pub async fn set_metadata(
    method get_metadata (line 183) | pub async fn get_metadata(&self, file_id: &str) -> Result<Metadata> {
    method get_file_info (line 189) | pub async fn get_file_info(&self, file_id: &str) -> Result<FileInfo> {
    method file_exists (line 195) | pub async fn file_exists(&self, file_id: &str) -> bool {
    method close (line 203) | pub async fn close(&self) {

FILE: rust_client/src/connection.rs
  type Connection (line 21) | pub struct Connection {
    method new (line 29) | pub fn new(stream: TcpStream, addr: String) -> Self {
    method send (line 40) | pub async fn send(&mut self, data: &[u8], timeout_ms: u64) -> Result<(...
    method receive_full (line 65) | pub async fn receive_full(&mut self, size: usize, timeout_ms: u64) -> ...
    method last_used (line 89) | pub fn last_used(&self) -> Instant {
    method addr (line 94) | pub fn addr(&self) -> &str {
  type ConnectionPool (line 106) | pub struct ConnectionPool {
    method new (line 119) | pub fn new(
    method get (line 144) | pub async fn get(&self, addr: Option<&str>) -> Result<Connection> {
    method create_connection (line 192) | async fn create_connection(&self, addr: &str) -> Result<Connection> {
    method put (line 217) | pub async fn put(&self, conn: Connection) {
    method clean_pool (line 250) | fn clean_pool(&self, pool: &mut Vec<Connection>) {
    method add_addr (line 259) | pub async fn add_addr(&self, addr: String) {
    method close (line 276) | pub async fn close(&self) {

FILE: rust_client/src/errors.rs
  type Result (line 9) | pub type Result<T> = std::result::Result<T, FastDFSError>;
  type FastDFSError (line 13) | pub enum FastDFSError {
  function map_status_to_error (line 103) | pub fn map_status_to_error(status: u8) -> Option<FastDFSError> {

FILE: rust_client/src/operations.rs
  type Operations (line 18) | pub struct Operations {
    method new (line 27) | pub fn new(
    method upload_file (line 42) | pub async fn upload_file(
    method upload_buffer (line 55) | pub async fn upload_buffer(
    method upload_buffer_internal (line 82) | async fn upload_buffer_internal(
    method get_storage_server (line 162) | async fn get_storage_server(&self, group_name: &str) -> Result<Storage...
    method download_file (line 225) | pub async fn download_file(&self, file_id: &str, offset: u64, length: ...
    method download_file_internal (line 243) | async fn download_file_internal(&self, file_id: &str, offset: u64, len...
    method get_download_storage_server (line 293) | async fn get_download_storage_server(
    method download_to_file (line 350) | pub async fn download_to_file(&self, file_id: &str, local_filename: &s...
    method delete_file (line 357) | pub async fn delete_file(&self, file_id: &str) -> Result<()> {
    method delete_file_internal (line 375) | async fn delete_file_internal(&self, file_id: &str) -> Result<()> {
    method set_metadata (line 415) | pub async fn set_metadata(
    method get_metadata (line 467) | pub async fn get_metadata(&self, file_id: &str) -> Result<Metadata> {
    method get_file_info (line 517) | pub async fn get_file_info(&self, file_id: &str) -> Result<FileInfo> {

FILE: rust_client/src/protocol.rs
  function encode_header (line 19) | pub fn encode_header(length: u64, cmd: u8, status: u8) -> Bytes {
  function decode_header (line 30) | pub fn decode_header(data: &[u8]) -> Result<TrackerHeader> {
  function split_file_id (line 50) | pub fn split_file_id(file_id: &str) -> Result<(String, String)> {
  function join_file_id (line 77) | pub fn join_file_id(group_name: &str, remote_filename: &str) -> String {
  function encode_metadata (line 90) | pub fn encode_metadata(metadata: &Metadata) -> Bytes {
  function decode_metadata (line 120) | pub fn decode_metadata(data: &[u8]) -> Result<Metadata> {
  function get_file_ext_name (line 156) | pub fn get_file_ext_name(filename: &str) -> String {
  function read_file_content (line 172) | pub fn read_file_content(filename: &str) -> Result<Bytes> {
  function write_file_content (line 180) | pub fn write_file_content(filename: &str, data: &[u8]) -> Result<()> {
  function pad_string (line 193) | pub fn pad_string(s: &str, length: usize) -> Bytes {
  function unpad_string (line 206) | pub fn unpad_string(data: &[u8]) -> String {
  function encode_int64 (line 214) | pub fn encode_int64(n: u64) -> Bytes {
  function decode_int64 (line 223) | pub fn decode_int64(data: &[u8]) -> u64 {
  function encode_int32 (line 232) | pub fn encode_int32(n: u32) -> Bytes {
  function decode_int32 (line 239) | pub fn decode_int32(data: &[u8]) -> u32 {
  function test_encode_decode_header (line 252) | fn test_encode_decode_header() {
  function test_split_file_id (line 267) | fn test_split_file_id() {
  function test_join_file_id (line 276) | fn test_join_file_id() {
  function test_encode_decode_metadata (line 285) | fn test_encode_decode_metadata() {
  function test_get_file_ext_name (line 299) | fn test_get_file_ext_name() {
  function test_pad_unpad_string (line 306) | fn test_pad_unpad_string() {

FILE: rust_client/src/types.rs
  constant TRACKER_DEFAULT_PORT (line 9) | pub const TRACKER_DEFAULT_PORT: u16 = 22122;
  constant STORAGE_DEFAULT_PORT (line 10) | pub const STORAGE_DEFAULT_PORT: u16 = 23000;
  constant FDFS_PROTO_HEADER_LEN (line 13) | pub const FDFS_PROTO_HEADER_LEN: usize = 10;
  constant FDFS_GROUP_NAME_MAX_LEN (line 16) | pub const FDFS_GROUP_NAME_MAX_LEN: usize = 16;
  constant FDFS_FILE_EXT_NAME_MAX_LEN (line 17) | pub const FDFS_FILE_EXT_NAME_MAX_LEN: usize = 6;
  constant FDFS_MAX_META_NAME_LEN (line 18) | pub const FDFS_MAX_META_NAME_LEN: usize = 64;
  constant FDFS_MAX_META_VALUE_LEN (line 19) | pub const FDFS_MAX_META_VALUE_LEN: usize = 256;
  constant FDFS_FILE_PREFIX_MAX_LEN (line 20) | pub const FDFS_FILE_PREFIX_MAX_LEN: usize = 16;
  constant FDFS_STORAGE_ID_MAX_SIZE (line 21) | pub const FDFS_STORAGE_ID_MAX_SIZE: usize = 16;
  constant FDFS_VERSION_SIZE (line 22) | pub const FDFS_VERSION_SIZE: usize = 8;
  constant IP_ADDRESS_SIZE (line 23) | pub const IP_ADDRESS_SIZE: usize = 16;
  constant FDFS_RECORD_SEPARATOR (line 26) | pub const FDFS_RECORD_SEPARATOR: u8 = 0x01;
  constant FDFS_FIELD_SEPARATOR (line 27) | pub const FDFS_FIELD_SEPARATOR: u8 = 0x02;
  type TrackerCommand (line 32) | pub enum TrackerCommand {
  function from (line 52) | fn from(cmd: TrackerCommand) -> u8 {
  type StorageCommand (line 60) | pub enum StorageCommand {
  function from (line 75) | fn from(cmd: StorageCommand) -> u8 {
  type StorageStatus (line 83) | pub enum StorageStatus {
  type MetadataFlag (line 99) | pub enum MetadataFlag {
  function from (line 107) | fn from(flag: MetadataFlag) -> u8 {
  type FileInfo (line 114) | pub struct FileInfo {
  type StorageServer (line 127) | pub struct StorageServer {
  type TrackerHeader (line 138) | pub struct TrackerHeader {
  type UploadResponse (line 149) | pub struct UploadResponse {
  type ClientConfig (line 158) | pub struct ClientConfig {
    method new (line 188) | pub fn new(tracker_addrs: Vec<String>) -> Self {
    method with_max_conns (line 196) | pub fn with_max_conns(mut self, max_conns: usize) -> Self {
    method with_connect_timeout (line 202) | pub fn with_connect_timeout(mut self, timeout: u64) -> Self {
    method with_network_timeout (line 208) | pub fn with_network_timeout(mut self, timeout: u64) -> Self {
    method with_idle_timeout (line 214) | pub fn with_idle_timeout(mut self, timeout: u64) -> Self {
    method with_retry_count (line 220) | pub fn with_retry_count(mut self, count: usize) -> Self {
  method default (line 174) | fn default() -> Self {
  type Metadata (line 227) | pub type Metadata = std::collections::HashMap<String, String>;

FILE: rust_client/tests/client_tests.rs
  function test_client_creation_valid_config (line 21) | fn test_client_creation_valid_config() {
  function test_client_creation_empty_trackers (line 40) | fn test_client_creation_empty_trackers() {
  function test_client_creation_invalid_address (line 59) | fn test_client_creation_invalid_address() {
  function test_config_builder (line 78) | fn test_config_builder() {
  function test_config_defaults (line 109) | fn test_config_defaults() {
  function test_client_close (line 147) | async fn test_client_close() {
  function test_client_close_idempotent (line 168) | async fn test_client_close_idempotent() {
  function test_invalid_file_id (line 195) | async fn test_invalid_file_id() {

FILE: rust_client/tests/integration_tests.rs
  function get_tracker_addr (line 16) | fn get_tracker_addr() -> String {
  function should_run_integration_tests (line 24) | fn should_run_integration_tests() -> bool {
  function test_upload_download_delete_cycle (line 37) | async fn test_upload_download_delete_cycle() {
  function test_upload_file_from_disk (line 99) | async fn test_upload_file_from_disk() {
  function test_download_to_file (line 149) | async fn test_download_to_file() {
  function test_metadata_operations (line 196) | async fn test_metadata_operations() {
  function test_get_file_info (line 284) | async fn test_get_file_info() {
  function test_file_exists (line 333) | async fn test_file_exists() {
  function test_download_range (line 381) | async fn test_download_range() {

FILE: rust_client/tests/protocol_tests.rs
  function test_encode_decode_header (line 23) | fn test_encode_decode_header() {
  function test_decode_header_short_data (line 59) | fn test_decode_header_short_data() {
  function test_encode_header_max_values (line 76) | fn test_encode_header_max_values() {
  function test_encode_header_zero_values (line 102) | fn test_encode_header_zero_values() {
  function test_split_file_id_valid (line 138) | fn test_split_file_id_valid() {
  function test_split_file_id_invalid (line 158) | fn test_split_file_id_invalid() {
  function test_join_file_id (line 184) | fn test_join_file_id() {
  function test_file_id_round_trip (line 204) | fn test_file_id_round_trip() {
  function test_encode_decode_metadata (line 233) | fn test_encode_decode_metadata() {
  function test_encode_metadata_empty (line 273) | fn test_encode_metadata_empty() {
  function test_decode_metadata_empty (line 292) | fn test_decode_metadata_empty() {
  function test_metadata_with_special_chars (line 311) | fn test_metadata_with_special_chars() {
  function test_metadata_truncation (line 333) | fn test_metadata_truncation() {
  function test_get_file_ext_name (line 367) | fn test_get_file_ext_name() {
  function test_get_file_ext_name_truncation (line 396) | fn test_get_file_ext_name_truncation() {
  function test_get_file_ext_name_with_path (line 417) | fn test_get_file_ext_name_with_path() {
  function test_pad_unpad_string (line 442) | fn test_pad_unpad_string() {
  function test_pad_string_truncate (line 472) | fn test_pad_string_truncate() {
  function test_pad_empty_string (line 493) | fn test_pad_empty_string() {
  function test_unpad_string_no_padding (line 514) | fn test_unpad_string_no_padding() {
  function test_encode_decode_int64 (line 539) | fn test_encode_decode_int64() {
  function test_decode_int64_short_data (line 579) | fn test_decode_int64_short_data() {
  function test_encode_decode_int32 (line 595) | fn test_encode_decode_int32() {
  function test_decode_int32_short_data (line 629) | fn test_decode_int32_short_data() {

FILE: storage/fdfs_storaged.c
  function main (line 78) | int main(int argc, char *argv[])
  function sigQuitHandler (line 319) | static void sigQuitHandler(int sig)
  function sigAlarmHandler (line 335) | static void sigAlarmHandler(int sig)
  function sigHupHandler (line 387) | static void sigHupHandler(int sig)
  function sigUsrHandler (line 403) | static void sigUsrHandler(int sig)
  function sigDumpHandler (line 410) | static void sigDumpHandler(int sig)
  function setup_schedule_tasks (line 430) | static int setup_schedule_tasks()
  function setupSignalHandlers (line 479) | static int setupSignalHandlers()

FILE: storage/fdht_client/fdht_client.c
  function fdht_proxy_extra_deal (line 29) | static void fdht_proxy_extra_deal(GroupArray *pGroupArray, bool *bKeepAl...
  function fdht_client_init (line 60) | int fdht_client_init(const char *filename)
  function fdht_load_conf (line 160) | int fdht_load_conf(const char *filename, GroupArray *pGroupArray, \
  function fdht_client_destroy (line 188) | void fdht_client_destroy()
  function FDHTServerInfo (line 199) | static FDHTServerInfo *get_connection(ServerArray *pServerArray, \
  function fdht_get_ex1 (line 357) | int fdht_get_ex1(GroupArray *pGroupArray, const bool bKeepAlive, \
  function fdht_batch_set_ex (line 513) | int fdht_batch_set_ex(GroupArray *pGroupArray, const bool bKeepAlive, \
  function fdht_batch_delete_ex (line 702) | int fdht_batch_delete_ex(GroupArray *pGroupArray, const bool bKeepAlive, \
  function fdht_batch_get_ex1 (line 853) | int fdht_batch_get_ex1(GroupArray *pGroupArray, const bool bKeepAlive, \
  function fdht_set_ex (line 1083) | int fdht_set_ex(GroupArray *pGroupArray, const bool bKeepAlive, \
  function fdht_inc_ex (line 1152) | int fdht_inc_ex(GroupArray *pGroupArray, const bool bKeepAlive, \
  function fdht_delete_ex (line 1267) | int fdht_delete_ex(GroupArray *pGroupArray, const bool bKeepAlive, \
  function fdht_connect_all_servers (line 1319) | int fdht_connect_all_servers(GroupArray *pGroupArray, const bool bKeepAl...
  function fdht_disconnect_all_servers (line 1366) | void fdht_disconnect_all_servers(GroupArray *pGroupArray)
  function fdht_stat_ex (line 1390) | int fdht_stat_ex(GroupArray *pGroupArray, const bool bKeepAlive, \
  function fdht_get_sub_keys_ex (line 1486) | int fdht_get_sub_keys_ex(GroupArray *pGroupArray, const bool bKeepAlive, \

FILE: storage/fdht_client/fdht_func.c
  function fdht_split_ids (line 30) | int fdht_split_ids(const char *szIds, int **ppIds, int *id_count)
  function fdht_cmp_by_ip_and_port_p (line 293) | static int fdht_cmp_by_ip_and_port_p(const void *p1, const void *p2)
  function fdht_cmp_by_ip_and_port_pp (line 308) | static int fdht_cmp_by_ip_and_port_pp(const void *p1, const void *p2)
  function fdht_insert_sorted_servers (line 323) | static void fdht_insert_sorted_servers(GroupArray *pGroupArray, \
  function fdht_load_groups_ex (line 342) | int fdht_load_groups_ex(IniContext *pIniContext, \
  function fdht_copy_group_array (line 648) | int fdht_copy_group_array(GroupArray *pDestGroupArray, \
  function fdht_free_group_array (line 736) | void fdht_free_group_array(GroupArray *pGroupArray)

FILE: storage/fdht_client/fdht_proto.c
  function fdht_recv_header (line 27) | int fdht_recv_header(FDHTServerInfo *pServer, fdht_pkg_size_t *in_bytes)
  function fdht_recv_response (line 66) | int fdht_recv_response(FDHTServerInfo *pServer, \
  function fdht_quit (line 136) | int fdht_quit(FDHTServerInfo *pServer)
  function fdht_disconnect_server (line 158) | void fdht_disconnect_server(FDHTServerInfo *pServer)
  function fdht_connect_server_nb (line 167) | int fdht_connect_server_nb(FDHTServerInfo *pServer, const int connect_ti...
  function fdht_connect_server (line 218) | int fdht_connect_server(FDHTServerInfo *pServer)
  function fdht_client_set (line 282) | int fdht_client_set(FDHTServerInfo *pServer, const char keep_alive, \
  function fdht_client_delete (line 381) | int fdht_client_delete(FDHTServerInfo *pServer, const char keep_alive, \
  function fdht_client_heart_beat (line 448) | int fdht_client_heart_beat(FDHTServerInfo *pServer)

FILE: storage/fdht_client/fdht_proto_types.h
  type fdht_pkg_size_t (line 38) | typedef int fdht_pkg_size_t;
  type FDHTProtoHeader (line 72) | typedef struct

FILE: storage/fdht_client/fdht_types.h
  type FDHTKeyInfo (line 53) | typedef struct
  type FDHTObjectInfo (line 63) | typedef struct
  type FDHTSubKey (line 71) | typedef struct
  type FDHTKeyValuePair (line 77) | typedef struct
  type FDHTServerInfo (line 86) | typedef struct
  type FDHTGroupServer (line 93) | typedef struct
  type FDHTServerStat (line 102) | typedef struct {
  type ServerArray (line 113) | typedef struct
  type GroupArray (line 119) | typedef struct

FILE: storage/file_id_hashtable.c
  type FileIdInfo (line 22) | typedef struct file_id_info {
  type FileIdHashtable (line 32) | typedef struct {
  type FileIdSharedLockArray (line 40) | typedef struct {
  type FileIdHTableContext (line 45) | typedef struct {
  function file_id_hashtable_init (line 63) | int file_id_hashtable_init()
  function file_id_hashtable_destroy (line 122) | void file_id_hashtable_destroy()
  function file_id_hashtable_add (line 159) | int file_id_hashtable_add(const string_t *file_id)
  function file_id_hashtable_del (line 241) | static int file_id_hashtable_del(FileIdInfo *finfo)
  function clear_expired_file_id_func (line 285) | static int clear_expired_file_id_func(void *args)

FILE: storage/storage_bulk_import.c
  function storage_bulk_import_init (line 43) | int storage_bulk_import_init()
  function storage_bulk_import_destroy (line 54) | void storage_bulk_import_destroy()
  function storage_validate_file_path (line 64) | int storage_validate_file_path(const char *file_path,
  function calculate_crc32_for_file (line 106) | static uint32_t calculate_crc32_for_file(const char *file_path, int64_t ...
  function storage_calculate_file_metadata (line 146) | int storage_calculate_file_metadata(const char *file_path,
  function storage_generate_file_id (line 200) | int storage_generate_file_id(BulkImportFileInfo *file_info,
  function storage_get_full_file_path (line 241) | int storage_get_full_file_path(int store_path_index, const char *file_id,
  function storage_check_available_space (line 273) | bool storage_check_available_space(int store_path_index, int64_t require...
  function copy_file_content (line 293) | static int copy_file_content(const char *src_path, const char *dest_path...
  function storage_transfer_file_to_storage (line 363) | int storage_transfer_file_to_storage(BulkImportFileInfo *file_info, int ...
  function storage_update_index_for_bulk_file (line 446) | int storage_update_index_for_bulk_file(BulkImportFileInfo *file_info)
  function storage_register_bulk_file (line 459) | int storage_register_bulk_file(BulkImportContext *context, BulkImportFil...

FILE: storage/storage_bulk_import.h
  type BulkImportFileInfo (line 52) | typedef struct {
  type BulkImportContext (line 68) | typedef struct {

FILE: storage/storage_dio.c
  type storage_dio_context (line 35) | struct storage_dio_context
  function storage_dio_init (line 41) | int storage_dio_init()
  function storage_dio_terminate (line 149) | void storage_dio_terminate()
  function storage_dio_queue_push (line 161) | int storage_dio_queue_push(struct fast_task_info *pTask)
  function storage_dio_get_thread_index (line 180) | int storage_dio_get_thread_index(struct fast_task_info *pTask, \
  function dio_delete_normal_file (line 212) | int dio_delete_normal_file(struct fast_task_info *pTask)
  function dio_delete_trunk_file (line 232) | int dio_delete_trunk_file(struct fast_task_info *pTask)
  function dio_discard_file (line 249) | int dio_discard_file(struct fast_task_info *pTask)
  function dio_open_file (line 268) | int dio_open_file(StorageFileContext *pFileContext)
  function dio_read_file (line 313) | int dio_read_file(struct fast_task_info *pTask)
  function dio_write_file (line 406) | int dio_write_file(struct fast_task_info *pTask)
  function dio_truncate_file (line 538) | int dio_truncate_file(struct fast_task_info *pTask)
  function dio_read_finish_clean_up (line 607) | void dio_read_finish_clean_up(struct fast_task_info *pTask)
  function dio_write_finish_clean_up (line 619) | void dio_write_finish_clean_up(struct fast_task_info *pTask)
  function dio_append_finish_clean_up (line 646) | void dio_append_finish_clean_up(struct fast_task_info *pTask)
  function dio_modify_finish_clean_up (line 686) | void dio_modify_finish_clean_up(struct fast_task_info *pTask)
  function dio_trunk_write_finish_clean_up (line 709) | void dio_trunk_write_finish_clean_up(struct fast_task_info *pTask)
  function dio_thread_deal_task (line 734) | static void dio_thread_deal_task(struct fast_task_info *head)
  type storage_dio_context (line 756) | struct storage_dio_context
  type fast_task_info (line 757) | struct fast_task_info
  type storage_dio_context (line 759) | struct storage_dio_context
  function dio_check_trunk_file_when_upload (line 787) | int dio_check_trunk_file_when_upload(struct fast_task_info *pTask)
  function dio_check_trunk_file_when_sync (line 818) | int dio_check_trunk_file_when_sync(struct fast_task_info *pTask)
  function dio_check_trunk_file_ex (line 826) | int dio_check_trunk_file_ex(int fd, const char *filename, const int64_t ...
  function dio_write_chunk_header (line 876) | int dio_write_chunk_header(struct fast_task_info *pTask)

FILE: storage/storage_dio.h
  type storage_dio_context (line 22) | struct storage_dio_context
  type storage_dio_thread_data (line 30) | struct storage_dio_thread_data
  type fast_task_info (line 50) | struct fast_task_info
  type fast_task_info (line 52) | struct fast_task_info
  type fast_task_info (line 54) | struct fast_task_info
  type fast_task_info (line 55) | struct fast_task_info
  type fast_task_info (line 56) | struct fast_task_info
  type fast_task_info (line 57) | struct fast_task_info
  type fast_task_info (line 58) | struct fast_task_info
  type fast_task_info (line 59) | struct fast_task_info
  type fast_task_info (line 61) | struct fast_task_info
  type fast_task_info (line 62) | struct fast_task_info
  type fast_task_info (line 63) | struct fast_task_info
  type fast_task_info (line 64) | struct fast_task_info
  type fast_task_info (line 65) | struct fast_task_info
  type fast_task_info (line 70) | struct fast_task_info
  type fast_task_info (line 71) | struct fast_task_info
  type fast_task_info (line 72) | struct fast_task_info

FILE: storage/storage_disk_recovery.c
  type FDFSTrunkFileIdInfo (line 40) | typedef struct {
  type RecoveryThreadData (line 46) | typedef struct recovery_thread_data {
  function storage_do_fetch_binlog (line 150) | static int storage_do_fetch_binlog(ConnectionInfo *pSrcStorage, \
  function recovery_get_src_storage_server (line 226) | static int recovery_get_src_storage_server(ConnectionInfo *pSrcStorage)
  function storage_disk_recovery_delete_thread_files (line 432) | static int storage_disk_recovery_delete_thread_files(const string_t *bas...
  function storage_disk_recovery_finish (line 479) | static int storage_disk_recovery_finish(const string_t *base_path)
  function do_write_to_flag_file (line 501) | static int do_write_to_flag_file(const char *flag_filename,
  function do_write_to_mark_file (line 532) | static int do_write_to_mark_file(const char *mark_filename,
  function recovery_write_to_mark_file (line 548) | static inline int recovery_write_to_mark_file(StorageBinLogReader *pReader)
  function recovery_init_global_binlog_file (line 554) | static int recovery_init_global_binlog_file(const string_t *base_path)
  function recovery_init_flag_file (line 567) | static int recovery_init_flag_file(const string_t *base_path,
  function recovery_load_params_from_flag_file (line 577) | static int recovery_load_params_from_flag_file(const char *full_flag_fil...
  function recovery_reader_init (line 625) | static int recovery_reader_init(const RecoveryThreadData *pThreadData,
  function recovery_reader_check_init (line 685) | static int recovery_reader_check_init(const RecoveryThreadData *pThreadD...
  function recovery_download_file_to_local (line 696) | static int recovery_download_file_to_local(StorageBinLogRecord *pRecord,
  function storage_do_recovery (line 778) | static int storage_do_recovery(RecoveryThreadData *pThreadData,
  function storage_disk_recovery_old_version_migrate (line 1062) | static int storage_disk_recovery_old_version_migrate(const string_t *bas...
  function do_dispatch_binlog_for_threads (line 1127) | static int do_dispatch_binlog_for_threads(const string_t *base_path)
  function storage_disk_recovery_dispatch_binlog_for_threads (line 1282) | static int storage_disk_recovery_dispatch_binlog_for_threads(
  function storage_disk_recovery_do_restore (line 1355) | static int storage_disk_recovery_do_restore(const string_t *base_path)
  function storage_disk_recovery_check_restore (line 1505) | int storage_disk_recovery_check_restore(const string_t *base_path)
  function storage_compare_trunk_id_info (line 1535) | static int storage_compare_trunk_id_info(void *p1, void *p2)
  function tree_write_file_walk_callback (line 1549) | static int tree_write_file_walk_callback(void *data, void *args)
  function disk_recovery_write_to_binlog (line 1569) | static int disk_recovery_write_to_binlog(FILE *fp,
  function storage_do_split_trunk_binlog (line 1609) | static int storage_do_split_trunk_binlog(const int store_path_index,
  function storage_disk_recovery_split_trunk_binlog (line 1770) | static int storage_disk_recovery_split_trunk_binlog(const int store_path...
  function storage_disk_recovery_prepare (line 1797) | int storage_disk_recovery_prepare(const int store_path_index)

FILE: storage/storage_dump.c
  function fdfs_dump_global_vars (line 27) | static int fdfs_dump_global_vars(char *buff, const int buffSize)
  function fdfs_dump_tracker_servers (line 241) | static int fdfs_dump_tracker_servers(char *buff, const int buffSize)
  function fdfs_dump_storage_servers (line 273) | static int fdfs_dump_storage_servers(char *buff, const int buffSize)
  function fdfs_dump_storage_stat (line 310) | static int fdfs_dump_storage_stat(char *buff, const int buffSize)
  function fdfs_dump_storage_global_vars_to_file (line 386) | int fdfs_dump_storage_global_vars_to_file(const char *filename)

FILE: storage/storage_func.c
  type FDFSStorePathMarkInfo (line 277) | typedef struct
  function storage_do_get_group_name (line 289) | static int storage_do_get_group_name(ConnectionInfo *pTrackerServer)
  function storage_get_group_name_from_tracker (line 337) | static int storage_get_group_name_from_tracker()
  function get_my_server_id_by_local_ip (line 370) | static int get_my_server_id_by_local_ip()
  function tracker_get_my_server_id (line 393) | static int tracker_get_my_server_id(const char *conf_filename,
  function load_from_stat_file (line 498) | static int load_from_stat_file()
  function storage_write_to_stat_file (line 627) | int storage_write_to_stat_file()
  function storage_write_to_sync_ini_file (line 952) | int storage_write_to_sync_ini_file()
  function storage_check_and_make_global_data_path (line 1100) | int storage_check_and_make_global_data_path()
  function storage_load_store_path_marks (line 1126) | static int storage_load_store_path_marks(IniContext *pIniContext)
  function storage_generate_store_path_mark (line 1158) | static int storage_generate_store_path_mark(const int store_path_index)
  function storage_check_store_path_mark (line 1220) | static int storage_check_store_path_mark(const int store_path_index,
  function storage_check_and_make_data_dirs (line 1391) | static int storage_check_and_make_data_dirs()
  function storage_make_data_dirs (line 1576) | static int storage_make_data_dirs(const string_t *base_path, bool *pathC...
  function storage_load_paths (line 1728) | static int storage_load_paths(IniContext *pItemContext,
  function storage_set_access_log_header (line 1743) | void storage_set_access_log_header(struct log_context *pContext)
  function storage_check_tracker_ipaddr (line 1752) | static int storage_check_tracker_ipaddr(const char *filename)
  function init_my_result_per_tracker (line 1781) | static int init_my_result_per_tracker()
  function access_log_config_to_string (line 1814) | static void access_log_config_to_string(char *output, const int size)
  function storage_func_init (line 1828) | int storage_func_init(const char *filename)
  function storage_func_destroy (line 2465) | int storage_func_destroy()
  function storage_server_is_myself (line 2502) | bool storage_server_is_myself(const FDFSStorageBrief *pStorageBrief)
  function storage_id_is_myself (line 2514) | bool storage_id_is_myself(const char *storage_id)
  function storage_get_my_ip_from_tracker (line 2526) | static int storage_get_my_ip_from_tracker(ConnectionInfo *conn,
  function storage_set_tracker_client_ips (line 2567) | int storage_set_tracker_client_ips(ConnectionInfo *conn,
  function storage_logic_to_local_full_filename (line 2636) | int storage_logic_to_local_full_filename(const char *logic_filename,

FILE: storage/storage_global.c
  type storage_dio_thread_data (line 101) | struct storage_dio_thread_data
  function storage_cmp_by_server_id (line 105) | int storage_cmp_by_server_id(const void *p1, const void *p2)
  function storage_insert_ip_addr_to_multi_ips (line 112) | int storage_insert_ip_addr_to_multi_ips(FDFSMultiIP *multi_ip,

FILE: storage/storage_global.h
  type StorageAccessLogContext (line 41) | typedef struct storage_access_log_context {
  type storage_dio_thread_data (line 139) | struct storage_dio_thread_data

FILE: storage/storage_ip_changed_dealer.c
  function storage_do_changelog_req (line 31) | static int storage_do_changelog_req(ConnectionInfo *pTrackerServer)
  function storage_report_ip_changed (line 62) | static int storage_report_ip_changed(ConnectionInfo *pTrackerServer)
  function storage_get_my_tracker_client_ip (line 122) | int storage_get_my_tracker_client_ip()
  function storage_report_storage_ip_addr (line 197) | static int storage_report_storage_ip_addr()
  function storage_changelog_req (line 284) | int storage_changelog_req()
  function storage_check_ip_changed (line 356) | int storage_check_ip_changed()

FILE: storage/storage_param_getter.c
  function storage_convert_src_server_id (line 34) | static int storage_convert_src_server_id()
  function storage_get_params_from_tracker (line 69) | int storage_get_params_from_tracker()

FILE: storage/storage_service.c
  type StorageFileInfoForCRC32 (line 97) | typedef struct
  type fast_mblock_man (line 107) | struct fast_mblock_man
  type fast_task_info (line 117) | struct fast_task_info
  type fast_task_info (line 119) | struct fast_task_info
  type fast_task_info (line 124) | struct fast_task_info
  type fast_task_info (line 130) | struct fast_task_info
  type fast_task_info (line 135) | struct fast_task_info
  type SourceFileInfo (line 175) | typedef struct
  type TrunkCreateLinkArg (line 182) | typedef struct
  type fast_task_info (line 188) | struct fast_task_info
  type fast_task_info (line 195) | struct fast_task_info
  function FDFSStorageServer (line 198) | static FDFSStorageServer *get_storage_server(const char *storage_server_id)
  function storage_log_access_log (line 289) | static void storage_log_access_log(struct fast_task_info *pTask, \
  function storage_delete_file_auto (line 377) | static int storage_delete_file_auto(StorageFileContext *pFileContext)
  function storage_is_slave_file (line 397) | static bool storage_is_slave_file(const char *remote_filename, \
  function storage_delete_file_log_error (line 428) | static void storage_delete_file_log_error(struct fast_task_info *pTask, \
  function storage_sync_delete_file_log_error (line 441) | static void storage_sync_delete_file_log_error(struct fast_task_info *pT...
  function storage_sync_delete_file_done_callback (line 466) | static void storage_sync_delete_file_done_callback( \
  function storage_sync_truncate_file_done_callback (line 505) | static void storage_sync_truncate_file_done_callback( \
  function storage_sync_copy_file_rename_filename (line 546) | static int storage_sync_copy_file_rename_filename(
  function storage_sync_copy_file_done_callback (line 575) | static void storage_sync_copy_file_done_callback(struct fast_task_info *...
  function storage_sync_modify_file_done_callback (line 652) | static void storage_sync_modify_file_done_callback( \
  function storage_get_metadata_done_callback (line 729) | static void storage_get_metadata_done_callback(struct fast_task_info *pT...
  function storage_download_file_done_callback (line 761) | static void storage_download_file_done_callback( \
  function storage_do_delete_meta_file (line 800) | static int storage_do_delete_meta_file(struct fast_task_info *pTask)
  function storage_delete_fdfs_file_done_callback (line 1103) | static void storage_delete_fdfs_file_done_callback( \
  function storage_upload_file_done_callback (line 1185) | static void storage_upload_file_done_callback(struct fast_task_info *pTa...
  function storage_server_get_logic_filename (line 1278) | static int storage_server_get_logic_filename(const int store_path_index,
  function storage_trunk_create_link_file_done_callback (line 1306) | static void storage_trunk_create_link_file_done_callback( \
  function storage_append_file_done_callback (line 1401) | static void storage_append_file_done_callback(struct fast_task_info *pTa...
  function storage_modify_file_done_callback (line 1478) | static void storage_modify_file_done_callback(struct fast_task_info *pTa...
  function storage_do_truncate_file_done_callback (line 1555) | static void storage_do_truncate_file_done_callback(struct fast_task_info...
  function storage_set_metadata_done_callback (line 1626) | static void storage_set_metadata_done_callback( \
  function storage_set_body_length (line 1682) | int storage_set_body_length(struct fast_task_info *pTask)
  function sock_accept_done_callback (line 1715) | static int sock_accept_done_callback(struct fast_task_info *task,
  function sock_send_done_callback (line 1734) | static int sock_send_done_callback(struct fast_task_info *pTask,
  function storage_clear_task (line 1788) | static void storage_clear_task(struct fast_task_info *pTask)
  function storage_service_init (line 1801) | int storage_service_init()
  function storage_service_destroy (line 1831) | void storage_service_destroy()
  function storage_get_storage_path_index (line 1835) | int storage_get_storage_path_index(int *store_path_index)
  function storage_get_store_path (line 1898) | void storage_get_store_path(const char *filename, const int filename_len, \
  function storage_gen_filename (line 1953) | static int storage_gen_filename(StorageClientInfo *pClientInfo,
  function storage_sort_metadata_buff (line 2023) | static int storage_sort_metadata_buff(char *meta_buff, const int meta_size)
  function storage_format_ext_name (line 2045) | static void storage_format_ext_name(const char *file_ext_name,
  function storage_get_filename_ex (line 2078) | static int storage_get_filename_ex(StorageClientInfo *pClientInfo,
  function storage_client_create_link_wrapper (line 2141) | static int storage_client_create_link_wrapper(struct fast_task_info *pTa...
  function storage_service_upload_file_done (line 2254) | static int storage_service_upload_file_done(struct fast_task_info *pTask)
  function storage_nio_notify (line 2653) | static int storage_nio_notify(struct fast_task_info *pTask, const int st...
  function calc_crc32_continue_callback (line 2677) | static int calc_crc32_continue_callback(struct fast_task_info *pTask,
  function storage_trunk_do_create_link (line 2684) | static int storage_trunk_do_create_link(struct fast_task_info *pTask,
  function storage_trunk_create_link (line 2722) | static int storage_trunk_create_link(struct fast_task_info *pTask, \
  function storage_service_do_create_link (line 2772) | static int storage_service_do_create_link(struct fast_task_info *pTask, \
  function storage_set_link_file_meta (line 2838) | static int storage_set_link_file_meta(struct fast_task_info *pTask, \
  function storage_do_set_metadata (line 2917) | static int storage_do_set_metadata(struct fast_task_info *pTask)
  function storage_server_set_metadata (line 3136) | static int storage_server_set_metadata(struct fast_task_info *pTask)
  function storage_server_report_server_id (line 3309) | static int storage_server_report_server_id(struct fast_task_info *pTask)
  function storage_server_trunk_sync_binlog (line 3351) | static int storage_server_trunk_sync_binlog(struct fast_task_info *pTask)
  function query_file_info_response (line 3394) | static int query_file_info_response(struct fast_task_info *pTask,
  function calc_crc32_done_callback_for_query_finfo (line 3438) | static void calc_crc32_done_callback_for_query_finfo(
  function push_calc_crc32_to_dio_queue (line 3477) | static int push_calc_crc32_to_dio_queue(struct fast_task_info *pTask,
  function query_file_info_deal_response (line 3510) | static int query_file_info_deal_response(struct fast_task_info *pTask,
  function storage_server_query_file_info (line 3565) | static int storage_server_query_file_info(struct fast_task_info *pTask)
  function storage_server_trunk_alloc_space (line 3798) | static int storage_server_trunk_alloc_space(struct fast_task_info *pTask)
  function storage_server_trunk_get_binlog_size (line 3881) | static int storage_server_trunk_get_binlog_size(struct fast_task_info *p...
  function storage_server_trunk_truncate_binlog_file (line 3932) | static int storage_server_trunk_truncate_binlog_file(struct fast_task_in...
  function storage_server_trunk_delete_binlog_marks (line 3973) | static int storage_server_trunk_delete_binlog_marks(struct fast_task_inf...
  function storage_server_trunk_confirm_or_free (line 4031) | static int storage_server_trunk_confirm_or_free(struct fast_task_info *p...
  function storage_server_fetch_one_path_binlog_dealer (line 4100) | static int storage_server_fetch_one_path_binlog_dealer(
  function fetch_one_path_binlog_finish_clean_up (line 4366) | static void fetch_one_path_binlog_finish_clean_up(struct fast_task_info ...
  function storage_server_do_fetch_one_path_binlog (line 4398) | static int storage_server_do_fetch_one_path_binlog(
  function storage_server_fetch_one_path_binlog (line 4461) | static int storage_server_fetch_one_path_binlog(struct fast_task_info *p...
  function storage_upload_file (line 4517) | static int storage_upload_file(struct fast_task_info *pTask, bool bAppen...
  function storage_deal_active_test (line 4721) | static int storage_deal_active_test(struct fast_task_info *pTask)
  function storage_server_check_appender_file (line 4743) | static int storage_server_check_appender_file(struct fast_task_info *pTask,
  function calc_crc32_done_callback_for_regenerate (line 4828) | static void calc_crc32_done_callback_for_regenerate(
  function storage_server_regenerate_appender_filename (line 4968) | static int storage_server_regenerate_appender_filename(struct fast_task_...
  function storage_append_file (line 5030) | static int storage_append_file(struct fast_task_info *pTask)
  function storage_modify_file (line 5136) | static int storage_modify_file(struct fast_task_info *pTask)
  function storage_do_truncate_file (line 5263) | static int storage_do_truncate_file(struct fast_task_info *pTask)
  function storage_upload_slave_file (line 5443) | static int storage_upload_slave_file(struct fast_task_info *pTask)
  function storage_sync_copy_file (line 5679) | static int storage_sync_copy_file(struct fast_task_info *pTask, \
  function set_fname2log_for_modify (line 5997) | static inline void set_fname2log_for_modify(
  function storage_sync_append_file (line 6041) | static int storage_sync_append_file(struct fast_task_info *pTask)
  function storage_sync_modify_file (line 6260) | static int storage_sync_modify_file(struct fast_task_info *pTask)
  function storage_sync_truncate_file (line 6452) | static int storage_sync_truncate_file(struct fast_task_info *pTask)
  function storage_do_sync_link_file (line 6629) | static int storage_do_sync_link_file(struct fast_task_info *pTask)
  function storage_sync_link_file (line 6883) | static int storage_sync_link_file(struct fast_task_info *pTask)
  function storage_sync_rename_file (line 6981) | static int storage_sync_rename_file(struct fast_task_info *pTask)
  function storage_server_get_metadata (line 7117) | static int storage_server_get_metadata(struct fast_task_info *pTask)
  function storage_server_download_file (line 7248) | static int storage_server_download_file(struct fast_task_info *pTask)
  function storage_do_delete_file (line 7430) | static int storage_do_delete_file(struct fast_task_info *pTask, \
  function storage_read_from_file (line 7457) | static int storage_read_from_file(struct fast_task_info *pTask, \
  function storage_write_to_file (line 7507) | static int storage_write_to_file(struct fast_task_info *pTask, \
  function storage_sync_delete_file (line 7564) | static int storage_sync_delete_file(struct fast_task_info *pTask)
  function storage_server_delete_file (line 7693) | static int storage_server_delete_file(struct fast_task_info *pTask)
  function storage_create_link_core (line 7918) | static int storage_create_link_core(struct fast_task_info *pTask, \
  function storage_do_create_link (line 8139) | static int storage_do_create_link(struct fast_task_info *pTask)
  function storage_create_link (line 8335) | static int storage_create_link(struct fast_task_info *pTask)
  function fdfs_stat_file_sync_func (line 8405) | int fdfs_stat_file_sync_func(void *args)
  function storage_deal_task (line 8439) | static int storage_deal_task(struct fast_task_info *pTask, const int stage)

FILE: storage/storage_sync.c
  type storage_dispatch_context (line 117) | struct storage_dispatch_context
  type StorageSyncTaskInfo (line 118) | typedef struct {
  type StorageSyncTaskArray (line 131) | typedef struct {
  type StorageDispatchContext (line 137) | typedef struct storage_dispatch_context {
  type fc_list_head (line 160) | struct fc_list_head
  function storage_sync_copy_file (line 185) | static int storage_sync_copy_file(ConnectionInfo *pStorageServer,
  function storage_sync_modify_file (line 406) | static int storage_sync_modify_file(ConnectionInfo *pStorageServer, \
  function storage_sync_truncate_file (line 577) | static int storage_sync_truncate_file(ConnectionInfo *pStorageServer, \
  function storage_sync_delete_file (line 719) | static int storage_sync_delete_file(ConnectionInfo *pStorageServer, \
  function storage_report_my_server_id (line 794) | static int storage_report_my_server_id(ConnectionInfo *pStorageServer)
  function storage_sync_link_file (line 841) | static int storage_sync_link_file(ConnectionInfo *pStorageServer, \
  function storage_sync_rename_file (line 1082) | static int storage_sync_rename_file(ConnectionInfo *pStorageServer,
  function storage_check_need_sync (line 1195) | static int storage_check_need_sync(StorageBinLogReader *pReader,
  function storage_sync_data (line 1232) | static int storage_sync_data(StorageBinLogReader *pReader,
  function sync_data_func (line 1318) | static void sync_data_func(StorageSyncTaskInfo *task, void *thread_data)
  function storage_batch_sync_data (line 1339) | static int storage_batch_sync_data(StorageDispatchContext *dispatch_ctx)
  function write_to_binlog_index (line 1421) | static int write_to_binlog_index(const int binlog_index)
  function get_binlog_index_from_file_old (line 1478) | static int get_binlog_index_from_file_old()
  function get_binlog_index_from_file (line 1521) | static int get_binlog_index_from_file()
  function open_next_writable_binlog (line 1637) | static int open_next_writable_binlog()
  function storage_sync_init (line 1681) | int storage_sync_init()
  function storage_sync_destroy (line 1789) | int storage_sync_destroy()
  function kill_storage_sync_threads (line 1817) | int kill_storage_sync_threads()
  function fdfs_binlog_sync_func (line 1854) | int fdfs_binlog_sync_func(void *args)
  function storage_binlog_fsync (line 1866) | static int storage_binlog_fsync(const bool bNeedLock)
  function storage_binlog_write_ex (line 1944) | int storage_binlog_write_ex(const time_t timestamp, const char op_type,
  function get_binlog_flag_file (line 1997) | static void get_binlog_flag_file(const char *filepath,
  function uncompress_binlog_file (line 2048) | static int uncompress_binlog_file(StorageBinLogReader *pReader,
  function compress_binlog_file (line 2124) | static int compress_binlog_file(const char *filename)
  function storage_open_readable_binlog (line 2196) | int storage_open_readable_binlog(StorageBinLogReader *pReader, \
  function storage_report_storage_status (line 2334) | int storage_report_storage_status(const char *storage_id, \
  function storage_reader_sync_init_req (line 2437) | static int storage_reader_sync_init_req(StorageBinLogReader *pReader)
  function storage_reader_init (line 2543) | int storage_reader_init(FDFSStorageBrief *pStorage,
  function storage_reader_destroy (line 2748) | void storage_reader_destroy(StorageBinLogReader *pReader)
  function storage_write_to_mark_file (line 2765) | static int storage_write_to_mark_file(StorageBinLogReader *pReader)
  function rewind_to_prev_rec_end_ex (line 2853) | static int rewind_to_prev_rec_end_ex(StorageBinLogReader *pReader,
  function rewind_to_prev_rec_end (line 2870) | static inline int rewind_to_prev_rec_end(StorageBinLogReader *pReader)
  function storage_binlog_preread (line 2875) | static int storage_binlog_preread(StorageBinLogReader *pReader)
  function storage_binlog_do_line_read (line 2923) | static int storage_binlog_do_line_read(StorageBinLogReader *pReader,
  function storage_binlog_read_line (line 2963) | static int storage_binlog_read_line(StorageBinLogReader *pReader, \
  function storage_binlog_read (line 2985) | int storage_binlog_read(StorageBinLogReader *pReader,
  function storage_binlog_reader_skip (line 3115) | static int storage_binlog_reader_skip(StorageBinLogReader *pReader)
  function storage_check_conflict (line 3155) | static inline int storage_check_conflict(
  function storage_binlog_rewind_buff (line 3204) | static inline void storage_binlog_rewind_buff(StorageBinLogReader *pReader,
  function storage_binlog_batch_read (line 3211) | static int storage_binlog_batch_read(StorageDispatchContext *dispatch_ctx)
  function storage_unlink_mark_file (line 3325) | int storage_unlink_mark_file(const char *storage_id)
  function storage_rename_mark_file (line 3358) | int storage_rename_mark_file(const char *old_ip_addr, const int old_port, \
  function storage_sync_get_start_end_times (line 3395) | static void storage_sync_get_start_end_times(time_t current_time, \
  function storage_sync_thread_exit (line 3428) | static void storage_sync_thread_exit(const FDFSStorageBrief *pStorage)
  function init_task_array (line 3478) | static int init_task_array(StorageDispatchContext *dispatch_ctx,
  function init_dispatch_ctx (line 3506) | static int init_dispatch_ctx(StorageDispatchContext *dispatch_ctx,
  function dispatch_ctx_close (line 3535) | static void dispatch_ctx_close(StorageDispatchContext *dispatch_ctx)
  function storage_sync_thread_start (line 3868) | int storage_sync_thread_start(const FDFSStorageBrief *pStorage)
  function storage_reader_add_to_list (line 3956) | void storage_reader_add_to_list(StorageBinLogReader *pReader)
  function storage_reader_remove_from_list (line 3963) | void storage_reader_remove_from_list(StorageBinLogReader *pReader)
  function calc_compress_until_binlog_index (line 3970) | static int calc_compress_until_binlog_index()
  function fdfs_binlog_compress_func (line 3991) | int fdfs_binlog_compress_func(void *args)

FILE: storage/storage_sync.h
  type StorageBinLogReader (line 41) | typedef struct
  type StorageBinLogRecord (line 61) | typedef struct

FILE: storage/storage_sync_func.c
  function storage_sync_connect_storage_server_ex (line 48) | int storage_sync_connect_storage_server_ex(const char *module_name,

FILE: storage/storage_sync_func.h
  function storage_sync_connect_storage_server_always (line 24) | static inline int storage_sync_connect_storage_server_always(
  function storage_sync_connect_storage_server_once (line 33) | static inline int storage_sync_connect_storage_server_once(

FILE: storage/storage_types.h
  type fast_task_info (line 34) | struct fast_task_info
  type fast_task_info (line 37) | struct fast_task_info
  type fast_task_info (line 39) | struct fast_task_info
  type fast_task_info (line 42) | struct fast_task_info
  type fast_task_info (line 45) | struct fast_task_info
  type fast_task_info (line 48) | struct fast_task_info
  type fast_task_info (line 49) | struct fast_task_info
  type FDFSStorageServer (line 57) | typedef struct
  type StorageStatusPerTracker (line 63) | typedef struct
  type StorageUploadInfo (line 72) | typedef struct
  type StorageSetMetaInfo (line 88) | typedef struct
  type StorageFileContext (line 95) | typedef struct
  type StorageClientInfo (line 137) | typedef struct

FILE: storage/tracker_client_thread.c
  function tracker_report_init (line 69) | int tracker_report_init()
  function tracker_report_destroy (line 83) | int tracker_report_destroy()
  function kill_tracker_report_threads (line 99) | int kill_tracker_report_threads()
  function thracker_report_thread_exit (line 130) | static void thracker_report_thread_exit(TrackerServerInfo *pTrackerServer)
  function tracker_unlink_mark_files (line 178) | static int tracker_unlink_mark_files(const char *storage_id)
  function tracker_rename_mark_files (line 188) | static int tracker_rename_mark_files(const char *old_ip_addr, \
  function tracker_insert_into_sorted_servers (line 571) | static bool tracker_insert_into_sorted_servers( \
  function tracker_sync_diff_servers (line 606) | int tracker_sync_diff_servers(ConnectionInfo *pTrackerServer, \
  function tracker_report_storage_status (line 672) | int tracker_report_storage_status(ConnectionInfo *pTrackerServer, \
  function tracker_start_sync_threads (line 728) | static int tracker_start_sync_threads(const FDFSStorageBrief *pStorage)
  function tracker_check_my_status (line 749) | static void tracker_check_my_status(const int tracker_index)
  function tracker_merge_servers (line 788) | static int tracker_merge_servers(ConnectionInfo *pTrackerServer,
  function _notify_reselect_tleader (line 1051) | static int _notify_reselect_tleader(ConnectionInfo *conn)
  function notify_reselect_tracker_leader (line 1094) | static int notify_reselect_tracker_leader(TrackerServerInfo *pTrackerSer...
  function check_my_status_for_all_trackers (line 1110) | static void check_my_status_for_all_trackers()
  function set_tracker_leader (line 1125) | static void set_tracker_leader(const int leader_index)
  function get_tracker_leader (line 1172) | static void get_tracker_leader()
  function set_trunk_server (line 1202) | static void set_trunk_server(const char *ip_addr, const int port)
  function do_set_trunk_server_myself (line 1231) | static int do_set_trunk_server_myself(ConnectionInfo *pTrackerServer)
  function do_unset_trunk_server_myself (line 1277) | static void do_unset_trunk_server_myself(ConnectionInfo *pTrackerServer)
  function tracker_check_response (line 1297) | static int tracker_check_response(ConnectionInfo *pTrackerServer,
  function tracker_sync_src_req (line 1587) | int tracker_sync_src_req(ConnectionInfo *pTrackerServer, \
  function tracker_sync_dest_req (line 1657) | static int tracker_sync_dest_req(ConnectionInfo *pTrackerServer)
  function tracker_sync_dest_query (line 1712) | static int tracker_sync_dest_query(ConnectionInfo *pTrackerServer)
  function tracker_report_trunk_fid (line 1768) | static int tracker_report_trunk_fid(ConnectionInfo *pTrackerServer)
  function tracker_report_trunk_free_space (line 1815) | static int tracker_report_trunk_free_space(ConnectionInfo *pTrackerServer)
  function tracker_fetch_trunk_fid (line 1861) | static int tracker_fetch_trunk_fid(ConnectionInfo *pTrackerServer)
  function tracker_sync_notify (line 1931) | static int tracker_sync_notify(ConnectionInfo *pTrackerServer, const int...
  function tracker_report_join (line 2001) | int tracker_report_join(ConnectionInfo *pTrackerServer,
  function tracker_report_sync_timestamp (line 2150) | static int tracker_report_sync_timestamp(ConnectionInfo *pTrackerServer,
  function tracker_report_df_stat (line 2200) | static int tracker_report_df_stat(ConnectionInfo *pTrackerServer,
  function tracker_heart_beat (line 2316) | static int tracker_heart_beat(ConnectionInfo *pTrackerServer,
  function tracker_storage_change_status (line 2448) | static int tracker_storage_change_status(ConnectionInfo *pTrackerServer,
  function tracker_storage_changelog_req (line 2526) | static int tracker_storage_changelog_req(ConnectionInfo *pTrackerServer)
  function tracker_deal_changelog_response (line 2553) | int tracker_deal_changelog_response(ConnectionInfo *pTrackerServer)
  function tracker_report_thread_start (line 2674) | int tracker_report_thread_start()

FILE: storage/trunk_mgr/trunk_client.c
  function trunk_client_trunk_do_alloc_space (line 31) | static int trunk_client_trunk_do_alloc_space(ConnectionInfo *pTrunkServe...
  function trunk_client_connect_trunk_server (line 96) | static int trunk_client_connect_trunk_server(TrackerServerInfo *trunk_se...
  function trunk_client_trunk_alloc_space (line 129) | int trunk_client_trunk_alloc_space(const int file_size, \
  function trunk_client_trunk_confirm_or_free (line 162) | static int trunk_client_trunk_confirm_or_free(ConnectionInfo *pTrunkServ...
  function trunk_client_trunk_alloc_confirm (line 222) | int trunk_client_trunk_alloc_confirm(const FDFSTrunkFullInfo *pTrunkInfo, \
  function trunk_client_trunk_free_space (line 247) | int trunk_client_trunk_free_space(const FDFSTrunkFullInfo *pTrunkInfo)

FILE: storage/trunk_mgr/trunk_free_block_checker.c
  function storage_trunk_node_compare_entry (line 35) | static int storage_trunk_node_compare_entry(void *p1, void *p2)
  function trunk_free_block_checker_init (line 42) | int trunk_free_block_checker_init()
  function trunk_free_block_checker_destroy (line 58) | void trunk_free_block_checker_destroy()
  function trunk_free_block_tree_node_count (line 63) | int trunk_free_block_tree_node_count()
  function block_tree_count_walk_callback (line 68) | static int block_tree_count_walk_callback(void *data, void *args)
  function trunk_free_block_total_count (line 77) | int trunk_free_block_total_count()
  function trunk_free_block_check_duplicate (line 90) | int trunk_free_block_check_duplicate(FDFSTrunkFullInfo *pTrunkInfo)
  function trunk_free_block_realloc (line 205) | static int trunk_free_block_realloc(FDFSBlockArray *pArray, const int ne...
  function trunk_free_block_do_insert (line 228) | static int trunk_free_block_do_insert(FDFSTrunkFullInfo *pTrunkInfo, \
  function trunk_free_block_insert (line 310) | int trunk_free_block_insert(FDFSTrunkFullInfo *pTrunkInfo)
  function trunk_free_block_delete (line 351) | int trunk_free_block_delete(FDFSTrunkFullInfo *pTrunkInfo)
  function block_tree_print_walk_callback (line 449) | static int block_tree_print_walk_callback(void *data, void *args)
  function trunk_free_block_tree_print (line 525) | int trunk_free_block_tree_print(const char *filename)

FILE: storage/tr
Condensed preview — 529 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (7,765K chars).
[
  {
    "path": ".gitignore",
    "chars": 1824,
    "preview": "# Makefile.in\nstorage/Makefile\ntracker/Makefile\nclient/test/Makefile\nclient/Makefile\n\n# client/fdfs_link_library.sh.in \n"
  },
  {
    "path": "COPYING-3_0.txt",
    "chars": 35067,
    "preview": "\t\t    GNU GENERAL PUBLIC LICENSE\n\t\t       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <h"
  },
  {
    "path": "HISTORY",
    "chars": 40418,
    "preview": "\nVersion 6.15.4  2026-03-07\n * download_file offset and bytes's logic is consistent with the range of HTTP\n\nVersion 6.15"
  },
  {
    "path": "INSTALL",
    "chars": 8923,
    "preview": "Copy right 2009 Happy Fish / YuQing\n\nFastDFS may be copied only under the terms of the GNU General\nPublic License V3, wh"
  },
  {
    "path": "README.md",
    "chars": 4122,
    "preview": "FastDFS is an open source high performance distributed file system. Its major\nfunctions include: file storing, file sync"
  },
  {
    "path": "README_zh.md",
    "chars": 1487,
    "preview": "  FastDFS是一款开源的分布式文件系统,功能主要包括:文件存储、文件同步、文件访问(文件上传、文件下载)等,解决了文件大容量存储和高性能访问的问题。FastDFS特别适合以文件为载体的在线服务,如图片、视频、文档等等服务。\n\n  Fa"
  },
  {
    "path": "benchmarks/.gitignore",
    "chars": 469,
    "preview": "# Compiled binaries\nbenchmark_upload\nbenchmark_download\nbenchmark_concurrent\nbenchmark_small_files\nbenchmark_large_files"
  },
  {
    "path": "benchmarks/Makefile",
    "chars": 3518,
    "preview": "# FastDFS Benchmark Suite Makefile\n\nCC = gcc\nCFLAGS = -Wall -Wextra -O2 -pthread -I../client -I../common\nLDFLAGS = -L../"
  },
  {
    "path": "benchmarks/README.md",
    "chars": 10798,
    "preview": "# FastDFS Benchmarking & Performance Testing Suite\n\n## Overview\n\nComprehensive performance testing suite for FastDFS tha"
  },
  {
    "path": "benchmarks/benchmark_concurrent.c",
    "chars": 15425,
    "preview": "/**\n * FastDFS Concurrent Operations Benchmark\n * \n * Simulates multiple concurrent users performing mixed operations\n *"
  },
  {
    "path": "benchmarks/benchmark_download.c",
    "chars": 16867,
    "preview": "/**\n * FastDFS Download Performance Benchmark\n * \n * Measures download throughput, IOPS, and latency percentiles\n */\n\n#i"
  },
  {
    "path": "benchmarks/benchmark_large_files.c",
    "chars": 10767,
    "preview": "/**\n * FastDFS Large Files Performance Benchmark\n * \n * Tests performance with large files (>100MB)\n */\n\n#include <stdio"
  },
  {
    "path": "benchmarks/benchmark_metadata.c",
    "chars": 16866,
    "preview": "/**\n * FastDFS Metadata Operations Benchmark\n * \n * Tests performance of metadata query, update, and delete operations\n "
  },
  {
    "path": "benchmarks/benchmark_small_files.c",
    "chars": 9398,
    "preview": "/**\n * FastDFS Small Files Performance Benchmark\n * \n * Tests performance with small files (<1MB) to identify optimizati"
  },
  {
    "path": "benchmarks/benchmark_upload.c",
    "chars": 14111,
    "preview": "/**\n * FastDFS Upload Performance Benchmark\n * \n * Measures upload throughput, IOPS, and latency percentiles\n */\n\n#inclu"
  },
  {
    "path": "benchmarks/config/benchmark.conf",
    "chars": 2577,
    "preview": "# FastDFS Benchmark Configuration\n\n# Tracker Server Configuration\ntracker_server = 127.0.0.1:22122\n\n# Storage Server Con"
  },
  {
    "path": "benchmarks/results/template.json",
    "chars": 2150,
    "preview": "{\n  \"benchmark\": \"template\",\n  \"version\": \"1.0.0\",\n  \"fastdfs_version\": \"6.12.1\",\n  \"timestamp\": \"2024-01-15T10:30:00Z\","
  },
  {
    "path": "benchmarks/scripts/compare_versions.py",
    "chars": 12933,
    "preview": "#!/usr/bin/env python3\n\"\"\"\nFastDFS Version Comparison Tool\n\nCompares performance between two FastDFS versions\n\"\"\"\n\nimpor"
  },
  {
    "path": "benchmarks/scripts/generate_report.py",
    "chars": 20505,
    "preview": "#!/usr/bin/env python3\n\"\"\"\nFastDFS Benchmark Report Generator\n\nGenerates HTML/PDF reports from benchmark results\n\"\"\"\n\nim"
  },
  {
    "path": "benchmarks/scripts/run_all_benchmarks.sh",
    "chars": 7964,
    "preview": "#!/bin/bash\n\n###############################################################################\n# FastDFS Benchmark Runner\n"
  },
  {
    "path": "cli/Makefile.in",
    "chars": 915,
    "preview": ".SUFFIXES: .c .o\n\nCOMPILE = $(CC) $(CFLAGS)\nINC_PATH = -I../common -I../tracker -I../client -I/usr/include/fastcommon\nLI"
  },
  {
    "path": "cli/README.md",
    "chars": 8158,
    "preview": "# FastDFS Modern CLI Tool\n\nA modern, feature-rich command-line interface for FastDFS with enhanced usability and product"
  },
  {
    "path": "cli/fdfs_cli.c",
    "chars": 20966,
    "preview": "/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public "
  },
  {
    "path": "client/Makefile.in",
    "chars": 3238,
    "preview": ".SUFFIXES: .c .o .lo\n\nCOMPILE = $(CC) $(CFLAGS)\nENABLE_STATIC_LIB = $(ENABLE_STATIC_LIB)\nENABLE_SHARED_LIB = $(ENABLE_SH"
  },
  {
    "path": "client/client_func.c",
    "chars": 14838,
    "preview": "/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public "
  },
  {
    "path": "client/client_func.h",
    "chars": 4328,
    "preview": "/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public "
  },
  {
    "path": "client/client_global.c",
    "chars": 565,
    "preview": "/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public "
  },
  {
    "path": "client/client_global.h",
    "chars": 959,
    "preview": "/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public "
  },
  {
    "path": "client/fdfs_append_file.c",
    "chars": 1445,
    "preview": "/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public "
  },
  {
    "path": "client/fdfs_appender_test.c",
    "chars": 11208,
    "preview": "/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public "
  },
  {
    "path": "client/fdfs_appender_test1.c",
    "chars": 10768,
    "preview": "/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public "
  },
  {
    "path": "client/fdfs_bulk_import.c",
    "chars": 13939,
    "preview": "/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public "
  },
  {
    "path": "client/fdfs_client.h",
    "chars": 541,
    "preview": "/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public "
  },
  {
    "path": "client/fdfs_crc32.c",
    "chars": 2071,
    "preview": "/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public "
  },
  {
    "path": "client/fdfs_delete_file.c",
    "chars": 1313,
    "preview": "/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public "
  },
  {
    "path": "client/fdfs_download_file.c",
    "chars": 2004,
    "preview": "/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public "
  },
  {
    "path": "client/fdfs_file_info.c",
    "chars": 3306,
    "preview": "/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public "
  },
  {
    "path": "client/fdfs_link_library.sh.in",
    "chars": 686,
    "preview": "tmp_src_filename=_fdfs_check_bits_.c\ncat <<EOF > $tmp_src_filename\n#include <stdio.h>\n#include <unistd.h>\n#include <fcnt"
  },
  {
    "path": "client/fdfs_monitor.c",
    "chars": 17449,
    "preview": "/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public "
  },
  {
    "path": "client/fdfs_regenerate_filename.c",
    "chars": 1620,
    "preview": "/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public "
  },
  {
    "path": "client/fdfs_test.c",
    "chars": 17246,
    "preview": "/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public "
  },
  {
    "path": "client/fdfs_test1.c",
    "chars": 16093,
    "preview": "/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public "
  },
  {
    "path": "client/fdfs_upload_appender.c",
    "chars": 1998,
    "preview": "/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public "
  },
  {
    "path": "client/fdfs_upload_file.c",
    "chars": 2488,
    "preview": "/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public "
  },
  {
    "path": "client/storage_client.c",
    "chars": 71663,
    "preview": "/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public "
  },
  {
    "path": "client/storage_client.h",
    "chars": 23139,
    "preview": "/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public "
  },
  {
    "path": "client/storage_client1.h",
    "chars": 21088,
    "preview": "/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public "
  },
  {
    "path": "client/test/Makefile.in",
    "chars": 624,
    "preview": ".SUFFIXES: .c .o\n\nCOMPILE = $(CC) $(CFLAGS)\nINC_PATH = -I/usr/include/fastcommon -I/usr/include/fastdfs \\\n           -I/"
  },
  {
    "path": "client/tracker_client.c",
    "chars": 50631,
    "preview": "/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public "
  },
  {
    "path": "client/tracker_client.h",
    "chars": 11609,
    "preview": "/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public "
  },
  {
    "path": "common/Makefile",
    "chars": 790,
    "preview": ".SUFFIXES: .c .o\n\nCOMPILE = $(CC) -Wall -O2 -D_FILE_OFFSET_BITS=64 -DOS_LINUX\n#COMPILE = $(CC) -Wall -g -D_FILE_OFFSET_B"
  },
  {
    "path": "common/fdfs_define.h",
    "chars": 957,
    "preview": "/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public "
  },
  {
    "path": "common/fdfs_global.c",
    "chars": 3741,
    "preview": "/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public "
  },
  {
    "path": "common/fdfs_global.h",
    "chars": 1021,
    "preview": "/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public "
  },
  {
    "path": "common/fdfs_http_shared.c",
    "chars": 9174,
    "preview": "\n/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public"
  },
  {
    "path": "common/fdfs_http_shared.h",
    "chars": 3209,
    "preview": "/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public "
  },
  {
    "path": "common/mime_file_parser.c",
    "chars": 2748,
    "preview": "\n/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public"
  },
  {
    "path": "common/mime_file_parser.h",
    "chars": 1001,
    "preview": "/**\n* Copyright (C) 2008 Happy Fish / YuQing\n*\n* FastDFS may be copied only under the terms of the GNU General\n* Public "
  },
  {
    "path": "conf/client.conf",
    "chars": 2173,
    "preview": "# connect timeout in seconds\n# default value is 30s\n# Note: in the intranet network (LAN), 2 seconds is enough.\nconnect_"
  },
  {
    "path": "conf/http.conf",
    "chars": 965,
    "preview": "# HTTP default content type\nhttp.default_content_type = application/octet-stream\n\n# MIME types mapping filename\n# MIME t"
  },
  {
    "path": "conf/mime.types",
    "chars": 31172,
    "preview": "# This is a comment. I love comments.\n\n# This file controls what Internet media types are sent to the client for\n# given"
  },
  {
    "path": "conf/storage.conf",
    "chars": 12053,
    "preview": "# is this config file disabled\n# false for enabled\n# true for disabled\ndisabled = false\n\n# the name of the group this st"
  },
  {
    "path": "conf/storage_ids.conf",
    "chars": 1342,
    "preview": "# <id>  <group_name>  <ip_or_hostname[:port]> [options]\n#\n# id is a natural number (1, 2, 3 etc.),\n# 6 bits of the id le"
  },
  {
    "path": "conf/tracker.conf",
    "chars": 10946,
    "preview": "# is this config file disabled\n# false for enabled\n# true for disabled\ndisabled = false\n\n# bind an address of this host\n"
  },
  {
    "path": "cpp_client/CMakeLists.txt",
    "chars": 2089,
    "preview": "cmake_minimum_required(VERSION 3.12)\nproject(fastdfs-client VERSION 1.0.0 LANGUAGES CXX)\n\nset(CMAKE_CXX_STANDARD 17)\nset"
  },
  {
    "path": "cpp_client/README.md",
    "chars": 6223,
    "preview": "# FastDFS C++ Client\n\nOfficial C++ client library for FastDFS - A high-performance distributed file system.\n\n## Features"
  },
  {
    "path": "cpp_client/examples/CMakeLists.txt",
    "chars": 1742,
    "preview": "cmake_minimum_required(VERSION 3.12)\n\n# Basic usage example\nadd_executable(basic_usage basic_usage.cpp)\ntarget_link_libr"
  },
  {
    "path": "cpp_client/examples/advanced_metadata_example.cpp",
    "chars": 29822,
    "preview": "/**\n * Copyright (C) 2025 FastDFS C++ Client Contributors\n *\n * FastDFS Advanced Metadata Example\n *\n * This comprehensi"
  },
  {
    "path": "cpp_client/examples/appender_example.cpp",
    "chars": 3811,
    "preview": "/**\n * Copyright (C) 2025 FastDFS C++ Client Contributors\n *\n * Appender file operations example for FastDFS C++ client\n"
  },
  {
    "path": "cpp_client/examples/basic_usage.cpp",
    "chars": 3741,
    "preview": "/**\n * Copyright (C) 2025 FastDFS C++ Client Contributors\n *\n * Basic usage example for FastDFS C++ client\n */\n\n#include"
  },
  {
    "path": "cpp_client/examples/batch_operations_example.cpp",
    "chars": 19437,
    "preview": "/**\n * Copyright (C) 2025 FastDFS C++ Client Contributors\n *\n * FastDFS Batch Operations Example\n *\n * This example demo"
  },
  {
    "path": "cpp_client/examples/cancellation_example.cpp",
    "chars": 25786,
    "preview": "/**\n * Copyright (C) 2025 FastDFS C++ Client Contributors\n *\n * FastDFS Cancellation Example\n *\n * This comprehensive ex"
  },
  {
    "path": "cpp_client/examples/concurrent_operations_example.cpp",
    "chars": 20562,
    "preview": "/**\n * Copyright (C) 2025 FastDFS C++ Client Contributors\n *\n * FastDFS Concurrent Operations Example\n *\n * This example"
  },
  {
    "path": "cpp_client/examples/configuration_example.cpp",
    "chars": 32487,
    "preview": "/**\n * Copyright (C) 2025 FastDFS C++ Client Contributors\n *\n * FastDFS Configuration Example\n *\n * This comprehensive e"
  },
  {
    "path": "cpp_client/examples/connection_pool_example.cpp",
    "chars": 22218,
    "preview": "/**\n * Copyright (C) 2025 FastDFS C++ Client Contributors\n *\n * FastDFS Connection Pool Example\n *\n * This example demon"
  },
  {
    "path": "cpp_client/examples/error_handling_example.cpp",
    "chars": 21988,
    "preview": "/**\n * Copyright (C) 2025 FastDFS C++ Client Contributors\n *\n * FastDFS Error Handling Example\n *\n * This example demons"
  },
  {
    "path": "cpp_client/examples/file_info_example.cpp",
    "chars": 21943,
    "preview": "/**\n * Copyright (C) 2025 FastDFS C++ Client Contributors\n *\n * FastDFS File Information Retrieval Example\n *\n * This co"
  },
  {
    "path": "cpp_client/examples/metadata_example.cpp",
    "chars": 3163,
    "preview": "/**\n * Copyright (C) 2025 FastDFS C++ Client Contributors\n *\n * Metadata operations example for FastDFS C++ client\n */\n\n"
  },
  {
    "path": "cpp_client/examples/partial_download_example.cpp",
    "chars": 18684,
    "preview": "/**\n * Copyright (C) 2025 FastDFS C++ Client Contributors\n *\n * FastDFS Partial Download Example\n *\n * This example demo"
  },
  {
    "path": "cpp_client/examples/performance_example.cpp",
    "chars": 28379,
    "preview": "/**\n * Copyright (C) 2025 FastDFS C++ Client Contributors\n *\n * FastDFS Performance Example\n *\n * This comprehensive exa"
  },
  {
    "path": "cpp_client/examples/slave_file_example.cpp",
    "chars": 18398,
    "preview": "/**\n * Copyright (C) 2025 FastDFS C++ Client Contributors\n *\n * FastDFS Slave File Example\n *\n * This example demonstrat"
  },
  {
    "path": "cpp_client/examples/streaming_example.cpp",
    "chars": 24946,
    "preview": "/**\n * Copyright (C) 2025 FastDFS C++ Client Contributors\n *\n * FastDFS Streaming Example\n *\n * This comprehensive examp"
  },
  {
    "path": "cpp_client/examples/upload_buffer_example.cpp",
    "chars": 20971,
    "preview": "/**\n * Copyright (C) 2025 FastDFS C++ Client Contributors\n *\n * FastDFS Upload from Memory Buffer Example\n *\n * This com"
  },
  {
    "path": "cpp_client/include/fastdfs/client.hpp",
    "chars": 7280,
    "preview": "/**\n * Copyright (C) 2025 FastDFS C++ Client Contributors\n *\n * FastDFS may be copied only under the terms of the GNU Ge"
  },
  {
    "path": "cpp_client/include/fastdfs/errors.hpp",
    "chars": 2091,
    "preview": "/**\n * Copyright (C) 2025 FastDFS C++ Client Contributors\n *\n * FastDFS may be copied only under the terms of the GNU Ge"
  },
  {
    "path": "cpp_client/include/fastdfs/types.hpp",
    "chars": 2953,
    "preview": "/**\n * Copyright (C) 2025 FastDFS C++ Client Contributors\n *\n * FastDFS may be copied only under the terms of the GNU Ge"
  },
  {
    "path": "cpp_client/src/client.cpp",
    "chars": 9096,
    "preview": "/**\n * Copyright (C) 2025 FastDFS C++ Client Contributors\n *\n * FastDFS may be copied only under the terms of the GNU Ge"
  },
  {
    "path": "cpp_client/src/internal/connection.cpp",
    "chars": 8297,
    "preview": "/**\n * Copyright (C) 2025 FastDFS C++ Client Contributors\n *\n * FastDFS may be copied only under the terms of the GNU Ge"
  },
  {
    "path": "cpp_client/src/internal/connection.hpp",
    "chars": 1883,
    "preview": "/**\n * Copyright (C) 2025 FastDFS C++ Client Contributors\n *\n * FastDFS may be copied only under the terms of the GNU Ge"
  },
  {
    "path": "cpp_client/src/internal/connection_pool.cpp",
    "chars": 4378,
    "preview": "/**\n * Copyright (C) 2025 FastDFS C++ Client Contributors\n *\n * FastDFS may be copied only under the terms of the GNU Ge"
  },
  {
    "path": "cpp_client/src/internal/connection_pool.hpp",
    "chars": 1803,
    "preview": "/**\n * Copyright (C) 2025 FastDFS C++ Client Contributors\n *\n * FastDFS may be copied only under the terms of the GNU Ge"
  },
  {
    "path": "cpp_client/src/internal/operations.cpp",
    "chars": 29071,
    "preview": "/**\n * Copyright (C) 2025 FastDFS C++ Client Contributors\n *\n * FastDFS may be copied only under the terms of the GNU Ge"
  },
  {
    "path": "cpp_client/src/internal/operations.hpp",
    "chars": 2902,
    "preview": "/**\n * Copyright (C) 2025 FastDFS C++ Client Contributors\n *\n * FastDFS may be copied only under the terms of the GNU Ge"
  },
  {
    "path": "cpp_client/src/internal/protocol.cpp",
    "chars": 4248,
    "preview": "/**\n * Copyright (C) 2025 FastDFS C++ Client Contributors\n *\n * FastDFS may be copied only under the terms of the GNU Ge"
  },
  {
    "path": "cpp_client/src/internal/protocol.hpp",
    "chars": 1454,
    "preview": "/**\n * Copyright (C) 2025 FastDFS C++ Client Contributors\n *\n * FastDFS may be copied only under the terms of the GNU Ge"
  },
  {
    "path": "csharp_client/ConnectionPool.cs",
    "chars": 17141,
    "preview": "// ============================================================================\n// FastDFS Connection Pool\n// =========="
  },
  {
    "path": "csharp_client/FastDFSClient.cs",
    "chars": 61714,
    "preview": "// ============================================================================\n// FastDFS C# Client Library\n// ========"
  },
  {
    "path": "csharp_client/FastDFSClientConfig.cs",
    "chars": 17952,
    "preview": "// ============================================================================\n// FastDFS Client Configuration\n// ====="
  },
  {
    "path": "csharp_client/FastDFSConstants.cs",
    "chars": 19810,
    "preview": "// ============================================================================\n// FastDFS Protocol Constants\n// ======="
  },
  {
    "path": "csharp_client/FastDFSErrors.cs",
    "chars": 12805,
    "preview": "// ============================================================================\n// FastDFS Exception Classes\n// ========"
  },
  {
    "path": "csharp_client/FastDFSTypes.cs",
    "chars": 16788,
    "preview": "// ============================================================================\n// FastDFS Type Definitions\n// ========="
  },
  {
    "path": "csharp_client/ProtocolBuilder.cs",
    "chars": 20079,
    "preview": "// ============================================================================\n// FastDFS Protocol Builder\n// ========="
  },
  {
    "path": "csharp_client/ProtocolParser.cs",
    "chars": 11642,
    "preview": "// ============================================================================\n// FastDFS Protocol Parser\n// =========="
  },
  {
    "path": "csharp_client/README.md",
    "chars": 6692,
    "preview": "# FastDFS C# Client\n\nOfficial C# client library for FastDFS - A high-performance distributed file system.\n\n## Features\n\n"
  },
  {
    "path": "csharp_client/examples/AdvancedMetadataExample.cs",
    "chars": 71333,
    "preview": "// ============================================================================\n// FastDFS C# Client - Advanced Metadata"
  },
  {
    "path": "csharp_client/examples/AppenderFileExample.cs",
    "chars": 31279,
    "preview": "// ============================================================================\n// FastDFS C# Client - Appender File Exa"
  },
  {
    "path": "csharp_client/examples/BasicExample.cs",
    "chars": 8713,
    "preview": "// ============================================================================\n// FastDFS C# Client - Basic Example\n// "
  },
  {
    "path": "csharp_client/examples/BatchOperationsExample.cs",
    "chars": 72799,
    "preview": "// ============================================================================\n// FastDFS C# Client - Batch Operations "
  },
  {
    "path": "csharp_client/examples/CancellationExample.cs",
    "chars": 63042,
    "preview": "// ============================================================================\n// FastDFS C# Client - Cancellation Exam"
  },
  {
    "path": "csharp_client/examples/ConcurrentOperationsExample.cs",
    "chars": 52924,
    "preview": "// ============================================================================\n// FastDFS C# Client - Concurrent Operat"
  },
  {
    "path": "csharp_client/examples/ConfigurationExample.cs",
    "chars": 53556,
    "preview": "// ============================================================================\n// FastDFS C# Client - Configuration Exa"
  },
  {
    "path": "csharp_client/examples/ConnectionPoolExample.cs",
    "chars": 44712,
    "preview": "// ============================================================================\n// FastDFS C# Client - Connection Pool E"
  },
  {
    "path": "csharp_client/examples/ErrorHandlingExample.cs",
    "chars": 56085,
    "preview": "// ============================================================================\n// FastDFS C# Client - Error Handling Ex"
  },
  {
    "path": "csharp_client/examples/FileInfoExample.cs",
    "chars": 65171,
    "preview": "// ============================================================================\n// FastDFS C# Client - File Information "
  },
  {
    "path": "csharp_client/examples/IntegrationExample.cs",
    "chars": 51447,
    "preview": "// ============================================================================\n// FastDFS C# Client - Integration Examp"
  },
  {
    "path": "csharp_client/examples/MetadataExample.cs",
    "chars": 6125,
    "preview": "// ============================================================================\n// FastDFS C# Client - Metadata Example\n"
  },
  {
    "path": "csharp_client/examples/PartialDownloadExample.cs",
    "chars": 47742,
    "preview": "// ============================================================================\n// FastDFS C# Client - Partial Download "
  },
  {
    "path": "csharp_client/examples/PerformanceExample.cs",
    "chars": 50739,
    "preview": "// ============================================================================\n// FastDFS C# Client - Performance Examp"
  },
  {
    "path": "csharp_client/examples/SlaveFileExample.cs",
    "chars": 45045,
    "preview": "// ============================================================================\n// FastDFS C# Client - Slave File Exampl"
  },
  {
    "path": "csharp_client/examples/StreamingExample.cs",
    "chars": 54311,
    "preview": "// ============================================================================\n// FastDFS C# Client - Streaming Example"
  },
  {
    "path": "csharp_client/examples/UploadBufferExample.cs",
    "chars": 35258,
    "preview": "// ============================================================================\n// FastDFS C# Client - Upload Buffer Exa"
  },
  {
    "path": "debian/README.Debian",
    "chars": 378,
    "preview": "FastDFS is an open source high performance distributed file system. Its major\nfunctions include: file storing, file sync"
  },
  {
    "path": "debian/changelog",
    "chars": 224,
    "preview": "fastdfs (6.15.2-1) stable; urgency=medium\n\n  * move finish_callback from fast_task_info to TrackerClientInfo\n  * use lib"
  },
  {
    "path": "debian/compat",
    "chars": 3,
    "preview": "11\n"
  },
  {
    "path": "debian/control",
    "chars": 1742,
    "preview": "Source: fastdfs\nSection: admin\nPriority: optional\nMaintainer: YuQing <384681@qq.com>\nBuild-Depends: debhelper (>=11~),\n "
  },
  {
    "path": "debian/copyright",
    "chars": 35067,
    "preview": "\t\t    GNU GENERAL PUBLIC LICENSE\n\t\t       Version 3, 29 June 2007\n\n Copyright (C) 2007 Free Software Foundation, Inc. <h"
  },
  {
    "path": "debian/fastdfs-config.install",
    "chars": 16,
    "preview": "etc/fdfs/*.conf\n"
  },
  {
    "path": "debian/fastdfs-server.dirs",
    "chars": 12,
    "preview": "opt/fastdfs\n"
  },
  {
    "path": "debian/fastdfs-server.install",
    "chars": 44,
    "preview": "usr/bin/fdfs_trackerd\nusr/bin/fdfs_storaged\n"
  },
  {
    "path": "debian/fastdfs-tool.dirs",
    "chars": 12,
    "preview": "opt/fastdfs\n"
  },
  {
    "path": "debian/fastdfs-tool.install",
    "chars": 319,
    "preview": "usr/bin/fdfs_monitor\nusr/bin/fdfs_test\nusr/bin/fdfs_test1\nusr/bin/fdfs_crc32\nusr/bin/fdfs_upload_file\nusr/bin/fdfs_downl"
  },
  {
    "path": "debian/libfdfsclient-dev.install",
    "chars": 22,
    "preview": "usr/include/fastdfs/*\n"
  },
  {
    "path": "debian/libfdfsclient.install",
    "chars": 23,
    "preview": "usr/lib/libfdfsclient*\n"
  },
  {
    "path": "debian/rules",
    "chars": 808,
    "preview": "#!/usr/bin/make -f\n\nexport DH_VERBOSE=1\nexport DESTDIR=$(CURDIR)/debian/tmp\n\nexport CONFDIR=$(DESTDIR)/etc/fdfs/\n\n%:\n\tdh"
  },
  {
    "path": "debian/source/format",
    "chars": 12,
    "preview": "3.0 (quilt)\n"
  },
  {
    "path": "debian/substvars",
    "chars": 88,
    "preview": "libfastcommon:Version=1.0.83\nlibserverframe:Version=1.2.11\nfastdfs-config:Version=1.0.0\n"
  },
  {
    "path": "debian/watch",
    "chars": 111,
    "preview": "version=3\nopts=\"mode=git\" https://github.com/happyfish100/fastdfs.git \\\n   refs/tags/v([\\d\\.]+) debian uupdate\n"
  },
  {
    "path": "docker/dockerfile_local/Dockerfile",
    "chars": 1285,
    "preview": "# centos 7\nFROM centos:7\n# 添加配置文件\n# add profiles\nADD conf/client.conf /etc/fdfs/\nADD conf/http.conf /etc/fdfs/\nADD conf/"
  },
  {
    "path": "docker/dockerfile_local/README.md",
    "chars": 1592,
    "preview": "# FastDFS Dockerfile local (本地版本)\n\n## 声明\n其实并没什么区别 教程是在上一位huayanYu(小锅盖)和 Wiki的作者 的基础上进行了一些修改,本质上还是huayanYu(小锅盖) 和 Wiki 上的"
  },
  {
    "path": "docker/dockerfile_local/conf/client.conf",
    "chars": 1460,
    "preview": "# connect timeout in seconds\n# default value is 30s\nconnect_timeout=30\n\n# network timeout in seconds\n# default value is "
  },
  {
    "path": "docker/dockerfile_local/conf/http.conf",
    "chars": 955,
    "preview": "# HTTP default content type\nhttp.default_content_type = application/octet-stream\n\n# MIME types mapping filename\n# MIME t"
  },
  {
    "path": "docker/dockerfile_local/conf/mime.types",
    "chars": 31172,
    "preview": "# This is a comment. I love comments.\n\n# This file controls what Internet media types are sent to the client for\n# given"
  },
  {
    "path": "docker/dockerfile_local/conf/mod_fastdfs.conf",
    "chars": 3729,
    "preview": "# connect timeout in seconds\n# default value is 30s\nconnect_timeout=2\n\n# network recv and send timeout in seconds\n# defa"
  },
  {
    "path": "docker/dockerfile_local/conf/nginx.conf",
    "chars": 2919,
    "preview": "\n#user  nobody;\nworker_processes  1;\n\n#error_log  logs/error.log;\n#error_log  logs/error.log  notice;\n#error_log  logs/e"
  },
  {
    "path": "docker/dockerfile_local/conf/storage.conf",
    "chars": 7960,
    "preview": "# is this config file disabled\n# false for enabled\n# true for disabled\ndisabled=false\n\n# the name of the group this stor"
  },
  {
    "path": "docker/dockerfile_local/conf/tracker.conf",
    "chars": 7431,
    "preview": "# is this config file disabled\n# false for enabled\n# true for disabled\ndisabled=false\n\n# bind an address of this host\n# "
  },
  {
    "path": "docker/dockerfile_local/fastdfs.sh",
    "chars": 679,
    "preview": "#!/bin/bash\n\nnew_val=$FASTDFS_IPADDR\nold=\"com.ikingtech.ch116221\"\n\nsed -i \"s/$old/$new_val/g\" /etc/fdfs/client.conf\nsed "
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/README.md",
    "chars": 605,
    "preview": "# FastDFS Dockerfile local (本地包构建)\r\n\r\n感谢余大的杰作!\r\n\r\n本目录包含了docker构建镜像,集群安装帮助手册\r\n\r\n1、目录结构\r\n    ./build_image-v6.0.9      fas"
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/build_image-v6.0.8/Dockerfile",
    "chars": 2626,
    "preview": "# 选择系统镜像作为基础镜像,可以使用超小的Linux镜像alpine\n#FROM centos:7\nFROM alpine:3.12\n\nLABEL MAINTAINER  liyanjing 284223249@qq.com\n\n# 0.安"
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/build_image-v6.0.8/conf/client.conf",
    "chars": 1979,
    "preview": "# connect timeout in seconds\r\n# default value is 30s\r\n# Note: in the intranet network (LAN), 2 seconds is enough.\r\nconne"
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/build_image-v6.0.8/conf/http.conf",
    "chars": 994,
    "preview": "# HTTP default content type\r\nhttp.default_content_type = application/octet-stream\r\n\r\n# MIME types mapping filename\r\n# MI"
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/build_image-v6.0.8/conf/mime.types",
    "chars": 32237,
    "preview": "# This is a comment. I love comments.\r\n\r\n# This file controls what Internet media types are sent to the client for\r\n# gi"
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/build_image-v6.0.8/conf/mod_fastdfs.conf",
    "chars": 4044,
    "preview": "# connect timeout in seconds\r\n# default value is 30s\r\nconnect_timeout=15\r\n\r\n# network recv and send timeout in seconds\r\n"
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/build_image-v6.0.8/conf/storage.conf",
    "chars": 10603,
    "preview": "# is this config file disabled\r\n# false for enabled\r\n# true for disabled\r\ndisabled = false\r\n\r\n# the name of the group th"
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/build_image-v6.0.8/conf/storage_ids.conf",
    "chars": 638,
    "preview": "# <id>  <group_name>  <ip_or_hostname[:port]>\r\n#\r\n# id is a natural number (1, 2, 3 etc.),\r\n# 6 bits of the id length is"
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/build_image-v6.0.8/conf/tracker.conf",
    "chars": 9466,
    "preview": "# is this config file disabled\r\n# false for enabled\r\n# true for disabled\r\ndisabled = false\r\n\r\n# bind an address of this "
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/build_image-v6.0.8/nginx_conf/nginx.conf",
    "chars": 971,
    "preview": "worker_processes  1;\r\nworker_rlimit_nofile 65535; #务必先修改服务器的max open files 数。\r\n\r\nerror_log  /data/fastdfs_data/logs/ngin"
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/build_image-v6.0.8/nginx_conf.d/default.conf",
    "chars": 782,
    "preview": "#http server\r\n#\r\n\r\nserver {\r\n     listen       9088;\r\n     server_name  localhost;\r\n\r\n    #open() “/usr/local/nginx/html"
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/build_image-v6.0.8/start.sh",
    "chars": 1134,
    "preview": "#!/bin/sh\n\n# fastdfs 配置文件,我设置的存储路径,需要提前创建\nFASTDFS_BASE_PATH=/data/fastdfs_data \\\nFASTDFS_STORE_PATH=/data/fastdfs/upload"
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/build_image-v6.0.9/Dockerfile",
    "chars": 3026,
    "preview": "# 选择系统镜像作为基础镜像,可以使用超小的Linux镜像alpine\n#FROM centos:7\nFROM alpine:3.16\n\nLABEL MAINTAINER  liyanjing 284223249@qq.com\n\n# 注意\n"
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/build_image-v6.0.9/conf/client.conf",
    "chars": 1978,
    "preview": "# connect timeout in seconds\r\n# default value is 30s\r\n# Note: in the intranet network (LAN), 2 seconds is enough.\r\nconne"
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/build_image-v6.0.9/conf/http.conf",
    "chars": 994,
    "preview": "# HTTP default content type\r\nhttp.default_content_type = application/octet-stream\r\n\r\n# MIME types mapping filename\r\n# MI"
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/build_image-v6.0.9/conf/mime.types",
    "chars": 32237,
    "preview": "# This is a comment. I love comments.\r\n\r\n# This file controls what Internet media types are sent to the client for\r\n# gi"
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/build_image-v6.0.9/conf/mod_fastdfs.conf",
    "chars": 4044,
    "preview": "# connect timeout in seconds\r\n# default value is 30s\r\nconnect_timeout=15\r\n\r\n# network recv and send timeout in seconds\r\n"
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/build_image-v6.0.9/conf/storage.conf",
    "chars": 10603,
    "preview": "# is this config file disabled\r\n# false for enabled\r\n# true for disabled\r\ndisabled = false\r\n\r\n# the name of the group th"
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/build_image-v6.0.9/conf/storage_ids.conf",
    "chars": 638,
    "preview": "# <id>  <group_name>  <ip_or_hostname[:port]>\r\n#\r\n# id is a natural number (1, 2, 3 etc.),\r\n# 6 bits of the id length is"
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/build_image-v6.0.9/conf/tracker.conf",
    "chars": 9466,
    "preview": "# is this config file disabled\r\n# false for enabled\r\n# true for disabled\r\ndisabled = false\r\n\r\n# bind an address of this "
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/build_image-v6.0.9/nginx_conf/nginx.conf",
    "chars": 971,
    "preview": "worker_processes  1;\r\nworker_rlimit_nofile 65535; #务必先修改服务器的max open files 数。\r\n\r\nerror_log  /data/fastdfs_data/logs/ngin"
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/build_image-v6.0.9/nginx_conf.d/default.conf",
    "chars": 782,
    "preview": "#http server\r\n#\r\n\r\nserver {\r\n     listen       9088;\r\n     server_name  localhost;\r\n\r\n    #open() “/usr/local/nginx/html"
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/build_image-v6.0.9/start.sh",
    "chars": 1134,
    "preview": "#!/bin/sh\n\n# fastdfs 配置文件,我设置的存储路径,需要提前创建\nFASTDFS_BASE_PATH=/data/fastdfs_data \\\nFASTDFS_STORE_PATH=/data/fastdfs/upload"
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/fastdfs-conf/conf/client.conf",
    "chars": 1978,
    "preview": "# connect timeout in seconds\r\n# default value is 30s\r\n# Note: in the intranet network (LAN), 2 seconds is enough.\r\nconne"
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/fastdfs-conf/conf/http.conf",
    "chars": 994,
    "preview": "# HTTP default content type\r\nhttp.default_content_type = application/octet-stream\r\n\r\n# MIME types mapping filename\r\n# MI"
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/fastdfs-conf/conf/mime.types",
    "chars": 32237,
    "preview": "# This is a comment. I love comments.\r\n\r\n# This file controls what Internet media types are sent to the client for\r\n# gi"
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/fastdfs-conf/conf/mod_fastdfs.conf",
    "chars": 4044,
    "preview": "# connect timeout in seconds\r\n# default value is 30s\r\nconnect_timeout=15\r\n\r\n# network recv and send timeout in seconds\r\n"
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/fastdfs-conf/conf/storage.conf",
    "chars": 10603,
    "preview": "# is this config file disabled\r\n# false for enabled\r\n# true for disabled\r\ndisabled = false\r\n\r\n# the name of the group th"
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/fastdfs-conf/conf/storage_ids.conf",
    "chars": 638,
    "preview": "# <id>  <group_name>  <ip_or_hostname[:port]>\r\n#\r\n# id is a natural number (1, 2, 3 etc.),\r\n# 6 bits of the id length is"
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/fastdfs-conf/conf/tracker.conf",
    "chars": 9466,
    "preview": "# is this config file disabled\r\n# false for enabled\r\n# true for disabled\r\ndisabled = false\r\n\r\n# bind an address of this "
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/fastdfs-conf/nginx_conf/nginx.conf",
    "chars": 971,
    "preview": "worker_processes  1;\r\nworker_rlimit_nofile 65535; #务必先修改服务器的max open files 数。\r\n\r\nerror_log  /data/fastdfs_data/logs/ngin"
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/fastdfs-conf/nginx_conf.d/default.conf",
    "chars": 821,
    "preview": "#http server\r\n#\r\n\r\nserver {\r\n     listen       9088;\r\n     server_name  localhost;\r\n\r\n    #open() “/usr/local/nginx/html"
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/fastdfs-conf/setting_conf.sh",
    "chars": 4158,
    "preview": "#!/bin/sh\n#\n# 用途:配置tracker \\ storage的配置文件参数,liyanjing 2022.08.10\n#\n\n\n# 1. tracker 主要参数,生产环境中建议更改一下端口\ntracker_port=22122\n"
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/fastdfs自定义镜像和安装手册.txt",
    "chars": 6132,
    "preview": "### 创建镜像\r\n\r\n参考:\r\nhttps://github.com/qbanxiaoli/fastdfs/blob/master/Dockerfile\r\nhttps://github.com/ygqygq2/fastdfs-nginx/"
  },
  {
    "path": "docker/dockerfile_local-v6.0.9/qa.txt",
    "chars": 5478,
    "preview": "fastdfs源自bbs论坛的问题整理:http://bbs.chinaunix.net/forum-240-1.html\r\n\r\n##### Q0、上传文件,如何选择存储地址的?\r\n\r\ntracker是各协调器, 是如何查询存储地址返回给客"
  },
  {
    "path": "docker/dockerfile_network/Dockerfile",
    "chars": 3697,
    "preview": "# centos 7\nFROM centos:7\n# 添加配置文件\nADD conf/client.conf /etc/fdfs/\nADD conf/http.conf /etc/fdfs/\nADD conf/mime.types /etc"
  },
  {
    "path": "docker/dockerfile_network/README.md",
    "chars": 1261,
    "preview": "# FastDFS Dockerfile network (网络版本)\n\n## 声明\n其实并没什么区别 教程是在上一位huayanYu(小锅盖)和 Wiki的作者 的基础上进行了一些修改,本质上还是huayanYu(小锅盖) 和 Wiki "
  },
  {
    "path": "docker/dockerfile_network/conf/client.conf",
    "chars": 1460,
    "preview": "# connect timeout in seconds\n# default value is 30s\nconnect_timeout=30\n\n# network timeout in seconds\n# default value is "
  },
  {
    "path": "docker/dockerfile_network/conf/http.conf",
    "chars": 955,
    "preview": "# HTTP default content type\nhttp.default_content_type = application/octet-stream\n\n# MIME types mapping filename\n# MIME t"
  },
  {
    "path": "docker/dockerfile_network/conf/mime.types",
    "chars": 31172,
    "preview": "# This is a comment. I love comments.\n\n# This file controls what Internet media types are sent to the client for\n# given"
  },
  {
    "path": "docker/dockerfile_network/conf/mod_fastdfs.conf",
    "chars": 3729,
    "preview": "# connect timeout in seconds\n# default value is 30s\nconnect_timeout=2\n\n# network recv and send timeout in seconds\n# defa"
  },
  {
    "path": "docker/dockerfile_network/conf/nginx.conf",
    "chars": 2919,
    "preview": "\n#user  nobody;\nworker_processes  1;\n\n#error_log  logs/error.log;\n#error_log  logs/error.log  notice;\n#error_log  logs/e"
  },
  {
    "path": "docker/dockerfile_network/conf/storage.conf",
    "chars": 7953,
    "preview": "# is this config file disabled\n# false for enabled\n# true for disabled\ndisabled=false\n\n# the name of the group this stor"
  },
  {
    "path": "docker/dockerfile_network/conf/tracker.conf",
    "chars": 7430,
    "preview": "# is this config file disabled\n# false for enabled\n# true for disabled\ndisabled=false\n\n# bind an address of this host\n# "
  },
  {
    "path": "docker/dockerfile_network/fastdfs.sh",
    "chars": 679,
    "preview": "#!/bin/bash\n\nnew_val=$FASTDFS_IPADDR\nold=\"com.ikingtech.ch116221\"\n\nsed -i \"s/$old/$new_val/g\" /etc/fdfs/client.conf\nsed "
  },
  {
    "path": "examples/c_examples/01_basic_upload.c",
    "chars": 12031,
    "preview": "/**\n * FastDFS Basic Upload Example\n * \n * This example demonstrates how to upload a file to FastDFS storage server.\n * "
  },
  {
    "path": "examples/c_examples/02_basic_download.c",
    "chars": 16166,
    "preview": "/**\n * FastDFS Basic Download Example\n * \n * This example demonstrates how to download a file from FastDFS storage serve"
  },
  {
    "path": "examples/c_examples/03_metadata_operations.c",
    "chars": 17083,
    "preview": "/**\n * FastDFS Metadata Operations Example\n * \n * This example demonstrates how to set and retrieve metadata for files\n "
  },
  {
    "path": "examples/c_examples/04_appender_file.c",
    "chars": 15736,
    "preview": "/**\n * FastDFS Appender File Example\n * \n * This example demonstrates how to work with appender files in FastDFS.\n * App"
  },
  {
    "path": "examples/c_examples/05_slave_file.c",
    "chars": 17344,
    "preview": "/**\n * FastDFS Slave File Example\n * \n * This example demonstrates how to work with slave files in FastDFS.\n * Slave fil"
  },
  {
    "path": "examples/c_examples/06_batch_upload.c",
    "chars": 18696,
    "preview": "/**\n * FastDFS Batch Upload Example\n * \n * This example demonstrates how to efficiently upload multiple files to FastDFS"
  },
  {
    "path": "examples/c_examples/07_connection_pool.c",
    "chars": 15356,
    "preview": "/**\n * FastDFS Connection Pool Example\n * \n * This example demonstrates how to use connection pooling with FastDFS\n * to"
  },
  {
    "path": "examples/c_examples/08_error_handling.c",
    "chars": 25766,
    "preview": "/**\n * FastDFS Error Handling Example\n * \n * This example demonstrates comprehensive error handling techniques when work"
  }
]

// ... and 329 more files (download for full content)

About this extraction

This page contains the full source code of the happyfish100/fastdfs GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 529 files (7.0 MB), approximately 1.9M tokens, and a symbol index with 3425 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!