refactor: split monolithic modules and extract shared components
- Remove dead socket.c/socket.h (accumulated duplicate symbols) - Extract compression.h/c (data_compress/decompress from data.c) - Extract io.h/c (low-level I/O from protocol.c) - Extract metadata.h/c (unified metadata wire format from file.c, chunk.c, utils.c) - Split client.c into client_cli.c (CLI parsing) + client_send.c (send logic) - Move receiver pipeline threads from server.c to multiprocessing.c - Move to_disk/file_restore_metadata from utils.c to file.c/metadata.c - Fix const qualifiers on to_disk and str_dup signatures - Suppress chown unused-result warning
This commit is contained in:
@@ -0,0 +1,150 @@
|
||||
#include "client_send.h"
|
||||
#include "config.h"
|
||||
#include "log.h"
|
||||
#include "utils.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
char *server_host = "127.0.0.1";
|
||||
int server_port = 8080;
|
||||
|
||||
static void print_usage(void) {
|
||||
printf("Usage:\n");
|
||||
printf(" fastsync [options] <source> <destination>\n");
|
||||
printf(" fastsync [options] --source-dir <src> --dest-dir <dst>\n");
|
||||
printf("\n");
|
||||
printf("Destination formats:\n");
|
||||
printf(" user@host:/path SSH transport (rsync-style)\n");
|
||||
printf(" host:/path SSH transport (current user)\n");
|
||||
printf(" /local/path TCP transport (requires server on localhost:8080)\n");
|
||||
printf("\n");
|
||||
printf("Options:\n");
|
||||
printf(" -c [level] Enable compression (level 1-22, default 5)\n");
|
||||
printf(" -m Enable multithreading\n");
|
||||
printf(" -s Enable chunk serialization\n");
|
||||
printf(" -f Enable sendfile (TCP only, not with -c or -s)\n");
|
||||
printf(" -v, --verbose Enable debug logging\n");
|
||||
printf(" -M, --preserve Preserve file metadata\n");
|
||||
printf(" --source-dir <path> Source directory\n");
|
||||
printf(" --dest-dir <path> Destination directory\n");
|
||||
printf(" --save-to-disk Write received files to disk\n");
|
||||
printf(" --server-host <ip> Server IP address (default: 127.0.0.1)\n");
|
||||
printf(" --server-port <n> Server port (default: 8080)\n");
|
||||
printf(" --help Show this help\n");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
const char *env_source = getenv("FASTSYNC_SOURCE_DIR");
|
||||
const char *env_dest = getenv("FASTSYNC_DEST_DIR");
|
||||
const char *env_save = getenv("FASTSYNC_SAVE_TO_DISK");
|
||||
|
||||
bool save_to_disk = false;
|
||||
if (env_save &&
|
||||
(strcmp(env_save, "true") == 0 || strcmp(env_save, "1") == 0)) {
|
||||
save_to_disk = true;
|
||||
}
|
||||
|
||||
Config *config = config_create(str_dup("1.0.0"), NULL, NULL,
|
||||
save_to_disk, false, false, false, false, 5, 20, false);
|
||||
|
||||
int positional_args[2];
|
||||
int positional_count = 0;
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "--help") == 0) {
|
||||
print_usage();
|
||||
return 0;
|
||||
} else if (strcmp(argv[i], "-c") == 0) {
|
||||
config->use_compression = true;
|
||||
log_message(LOG_LEVEL_INFO, "Enabled Compression");
|
||||
if (i + 1 < argc) {
|
||||
char *end_ptr;
|
||||
int level = strtol(argv[i + 1], &end_ptr, 10);
|
||||
if (*end_ptr == '\0') {
|
||||
config->compression_level = level;
|
||||
log_message(LOG_LEVEL_INFO, "Set Compression level to %d",
|
||||
config->compression_level);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
} else if (strcmp(argv[i], "--source-dir") == 0 && i + 1 < argc) {
|
||||
free(config->send_directory);
|
||||
config->send_directory = str_dup(argv[++i]);
|
||||
} else if (strcmp(argv[i], "--dest-dir") == 0 && i + 1 < argc) {
|
||||
free(config->receive_root_directory);
|
||||
config->receive_root_directory = str_dup(argv[++i]);
|
||||
} else if (strcmp(argv[i], "--save-to-disk") == 0) {
|
||||
config->save_to_disk = true;
|
||||
} else if (strcmp(argv[i], "-M") == 0 || strcmp(argv[i], "--preserve") == 0) {
|
||||
config->use_metadata = true;
|
||||
log_message(LOG_LEVEL_INFO, "Enabled metadata preservation");
|
||||
} else if (strcmp(argv[i], "-f") == 0 || strcmp(argv[i], "--sendfile") == 0) {
|
||||
config->use_sendfile = true;
|
||||
log_message(LOG_LEVEL_INFO, "Enabled sendfile");
|
||||
} else if (strcmp(argv[i], "-m") == 0) {
|
||||
config->use_multithreading = true;
|
||||
log_message(LOG_LEVEL_INFO, "Enabled Multithreading");
|
||||
} else if (strcmp(argv[i], "-s") == 0) {
|
||||
config->use_chunk_serialization = true;
|
||||
log_message(LOG_LEVEL_INFO, "Enabled Chunk Serialization");
|
||||
} else if (strcmp(argv[i], "--server-host") == 0 && i + 1 < argc) {
|
||||
free(server_host);
|
||||
server_host = str_dup(argv[++i]);
|
||||
} else if (strcmp(argv[i], "--server-port") == 0 && i + 1 < argc) {
|
||||
server_port = atoi(argv[++i]);
|
||||
} else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) {
|
||||
set_log_level(LOG_LEVEL_DEBUG);
|
||||
} else if (argv[i][0] == '-') {
|
||||
fprintf(stderr, "Unknown option: %s\n", argv[i]);
|
||||
print_usage();
|
||||
return 1;
|
||||
} else {
|
||||
if (positional_count < 2)
|
||||
positional_args[positional_count++] = i;
|
||||
else {
|
||||
fprintf(stderr, "Unexpected argument: %s\n", argv[i]);
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (positional_count == 2) {
|
||||
free(config->send_directory);
|
||||
free(config->receive_root_directory);
|
||||
config->send_directory = str_dup(argv[positional_args[0]]);
|
||||
config->receive_root_directory = str_dup(argv[positional_args[1]]);
|
||||
config->save_to_disk = true;
|
||||
|
||||
config_parse_ssh_dest(config);
|
||||
} else if (positional_count == 1) {
|
||||
fprintf(stderr, "Error: missing destination argument\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
} else {
|
||||
if (!config->send_directory && env_source)
|
||||
config->send_directory = str_dup((char *)env_source);
|
||||
if (!config->receive_root_directory && env_dest)
|
||||
config->receive_root_directory = str_dup((char *)env_dest);
|
||||
}
|
||||
|
||||
if (!config->send_directory || !config->receive_root_directory) {
|
||||
fprintf(stderr, "Error: source and destination directories are required\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
if (config->use_sendfile && (config->use_chunk_serialization || config->use_compression)) {
|
||||
fprintf(stderr, "Error: -f/--sendfile cannot be combined with -c (compression) or -s (chunk serialization)\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (config->transport == TRANSPORT_SSH && config->use_sendfile) {
|
||||
fprintf(stderr, "Error: -f/--sendfile is not supported with SSH transport\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (config->use_multithreading)
|
||||
return send_files_multithreaded(config);
|
||||
return send_files(config);
|
||||
}
|
||||
@@ -1,23 +1,21 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <threads.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "client_send.h"
|
||||
#include "chunk.h"
|
||||
#include "compression.h"
|
||||
#include "config.h"
|
||||
#include "data.h"
|
||||
#include "file.h"
|
||||
#include "log.h"
|
||||
#include "multiprocessing.h"
|
||||
#include "protocol.h"
|
||||
#include "queue.h"
|
||||
#include "scanner.h"
|
||||
#include "socket.h"
|
||||
#include "transport_tcp.h"
|
||||
#include "transport_ssh.h"
|
||||
#include "utils.h"
|
||||
#include <dirent.h>
|
||||
|
||||
static char *server_host = "127.0.0.1";
|
||||
static int server_port = 8080;
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <threads.h>
|
||||
|
||||
int send_chunk(Client *client, Chunk *chunk, Config *config) {
|
||||
if (config->use_chunk_serialization) {
|
||||
@@ -53,54 +51,7 @@ int send_chunk(Client *client, Chunk *chunk, Config *config) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int scan_directory_multithreaded(void *pipeline_context) {
|
||||
PipelineContextSender *context = (PipelineContextSender *)pipeline_context;
|
||||
mtx_lock(&context->mutex_scanner);
|
||||
DirectoryScanner *scanner =
|
||||
directory_scanner_create(context->config->send_directory, context->config->use_metadata);
|
||||
mtx_unlock(&context->mutex_scanner);
|
||||
|
||||
Chunk *current_chunk;
|
||||
while ((current_chunk = directory_scanner_next(scanner)) != NULL)
|
||||
queue_enqueue_multithreaded(context->queue_scanner, current_chunk,
|
||||
&context->mutex_scanner,
|
||||
&context->condition_not_empty_scanner,
|
||||
&context->condition_not_full_scanner);
|
||||
mtx_lock(&context->mutex_scanner);
|
||||
context->scanner_done = true;
|
||||
cnd_signal(&context->condition_not_empty_scanner);
|
||||
mtx_unlock(&context->mutex_scanner);
|
||||
|
||||
directory_scanner_destroy(scanner);
|
||||
return thrd_success;
|
||||
}
|
||||
|
||||
int load_files_multithreaded(void *pipeline_context) {
|
||||
PipelineContextSender *context = (PipelineContextSender *)pipeline_context;
|
||||
while (true) {
|
||||
Chunk *chunk = queue_dequeue_multithreaded(
|
||||
context->queue_scanner, &context->mutex_scanner,
|
||||
&context->condition_not_empty_scanner,
|
||||
&context->condition_not_full_scanner, &context->scanner_done);
|
||||
if (chunk == NULL) {
|
||||
mtx_lock(&context->mutex_loader);
|
||||
context->loader_done = true;
|
||||
cnd_signal(&context->condition_not_empty_loader);
|
||||
mtx_unlock(&context->mutex_loader);
|
||||
return thrd_success;
|
||||
}
|
||||
if (!context->config->use_sendfile) {
|
||||
for (int i = 0; i < chunk->element_count; i++)
|
||||
file_load_data(chunk->items[i]);
|
||||
}
|
||||
queue_enqueue_multithreaded(context->queue_loader, chunk,
|
||||
&context->mutex_loader,
|
||||
&context->condition_not_empty_loader,
|
||||
&context->condition_not_full_loader);
|
||||
}
|
||||
}
|
||||
|
||||
int send_chunks_multithreaded(void *pipeline_context) {
|
||||
static int send_chunks_multithreaded(void *pipeline_context) {
|
||||
PipelineContextSender *context = (PipelineContextSender *)pipeline_context;
|
||||
Client *client;
|
||||
if (context->config->transport == TRANSPORT_SSH) {
|
||||
@@ -135,6 +86,53 @@ int send_chunks_multithreaded(void *pipeline_context) {
|
||||
}
|
||||
}
|
||||
|
||||
static int scan_directory_multithreaded(void *pipeline_context) {
|
||||
PipelineContextSender *context = (PipelineContextSender *)pipeline_context;
|
||||
mtx_lock(&context->mutex_scanner);
|
||||
DirectoryScanner *scanner =
|
||||
directory_scanner_create(context->config->send_directory, context->config->use_metadata);
|
||||
mtx_unlock(&context->mutex_scanner);
|
||||
|
||||
Chunk *current_chunk;
|
||||
while ((current_chunk = directory_scanner_next(scanner)) != NULL)
|
||||
queue_enqueue_multithreaded(context->queue_scanner, current_chunk,
|
||||
&context->mutex_scanner,
|
||||
&context->condition_not_empty_scanner,
|
||||
&context->condition_not_full_scanner);
|
||||
mtx_lock(&context->mutex_scanner);
|
||||
context->scanner_done = true;
|
||||
cnd_signal(&context->condition_not_empty_scanner);
|
||||
mtx_unlock(&context->mutex_scanner);
|
||||
|
||||
directory_scanner_destroy(scanner);
|
||||
return thrd_success;
|
||||
}
|
||||
|
||||
static int load_files_multithreaded(void *pipeline_context) {
|
||||
PipelineContextSender *context = (PipelineContextSender *)pipeline_context;
|
||||
while (true) {
|
||||
Chunk *chunk = queue_dequeue_multithreaded(
|
||||
context->queue_scanner, &context->mutex_scanner,
|
||||
&context->condition_not_empty_scanner,
|
||||
&context->condition_not_full_scanner, &context->scanner_done);
|
||||
if (chunk == NULL) {
|
||||
mtx_lock(&context->mutex_loader);
|
||||
context->loader_done = true;
|
||||
cnd_signal(&context->condition_not_empty_loader);
|
||||
mtx_unlock(&context->mutex_loader);
|
||||
return thrd_success;
|
||||
}
|
||||
if (!context->config->use_sendfile) {
|
||||
for (int i = 0; i < chunk->element_count; i++)
|
||||
file_load_data(chunk->items[i]);
|
||||
}
|
||||
queue_enqueue_multithreaded(context->queue_loader, chunk,
|
||||
&context->mutex_loader,
|
||||
&context->condition_not_empty_loader,
|
||||
&context->condition_not_full_loader);
|
||||
}
|
||||
}
|
||||
|
||||
int send_files(Config *config) {
|
||||
Client *client;
|
||||
if (config->transport == TRANSPORT_SSH) {
|
||||
@@ -188,143 +186,3 @@ int send_files_multithreaded(Config *config) {
|
||||
pipeline_context_sender_destroy(context);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void print_usage(void) {
|
||||
printf("Usage:\n");
|
||||
printf(" fastsync [options] <source> <destination>\n");
|
||||
printf(" fastsync [options] --source-dir <src> --dest-dir <dst>\n");
|
||||
printf("\n");
|
||||
printf("Destination formats:\n");
|
||||
printf(" user@host:/path SSH transport (rsync-style)\n");
|
||||
printf(" host:/path SSH transport (current user)\n");
|
||||
printf(" /local/path TCP transport (requires server on localhost:8080)\n");
|
||||
printf("\n");
|
||||
printf("Options:\n");
|
||||
printf(" -c [level] Enable compression (level 1-22, default 5)\n");
|
||||
printf(" -m Enable multithreading\n");
|
||||
printf(" -s Enable chunk serialization\n");
|
||||
printf(" -f Enable sendfile (TCP only, not with -c or -s)\n");
|
||||
printf(" -v, --verbose Enable debug logging\n");
|
||||
printf(" -M, --preserve Preserve file metadata\n");
|
||||
printf(" --source-dir <path> Source directory\n");
|
||||
printf(" --dest-dir <path> Destination directory\n");
|
||||
printf(" --save-to-disk Write received files to disk\n");
|
||||
printf(" --server-host <ip> Server IP address (default: 127.0.0.1)\n");
|
||||
printf(" --server-port <n> Server port (default: 8080)\n");
|
||||
printf(" --help Show this help\n");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
const char *env_source = getenv("FASTSYNC_SOURCE_DIR");
|
||||
const char *env_dest = getenv("FASTSYNC_DEST_DIR");
|
||||
const char *env_save = getenv("FASTSYNC_SAVE_TO_DISK");
|
||||
|
||||
bool save_to_disk = false;
|
||||
if (env_save &&
|
||||
(strcmp(env_save, "true") == 0 || strcmp(env_save, "1") == 0)) {
|
||||
save_to_disk = true;
|
||||
}
|
||||
|
||||
Config *config = config_create(str_dup("1.0.0"), NULL, NULL,
|
||||
save_to_disk, false, false, false, false, 5, 20, false);
|
||||
|
||||
int positional_args[2];
|
||||
int positional_count = 0;
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
if (strcmp(argv[i], "--help") == 0) {
|
||||
print_usage();
|
||||
return 0;
|
||||
} else if (strcmp(argv[i], "-c") == 0) {
|
||||
config->use_compression = true;
|
||||
log_message(LOG_LEVEL_INFO, "Enabled Compression");
|
||||
if (i + 1 < argc) {
|
||||
char *end_ptr;
|
||||
int level = strtol(argv[i + 1], &end_ptr, 10);
|
||||
if (*end_ptr == '\0') {
|
||||
config->compression_level = level;
|
||||
log_message(LOG_LEVEL_INFO, "Set Compression level to %d",
|
||||
config->compression_level);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
} else if (strcmp(argv[i], "--source-dir") == 0 && i + 1 < argc) {
|
||||
free(config->send_directory);
|
||||
config->send_directory = str_dup(argv[++i]);
|
||||
} else if (strcmp(argv[i], "--dest-dir") == 0 && i + 1 < argc) {
|
||||
free(config->receive_root_directory);
|
||||
config->receive_root_directory = str_dup(argv[++i]);
|
||||
} else if (strcmp(argv[i], "--save-to-disk") == 0) {
|
||||
config->save_to_disk = true;
|
||||
} else if (strcmp(argv[i], "-M") == 0 || strcmp(argv[i], "--preserve") == 0) {
|
||||
config->use_metadata = true;
|
||||
log_message(LOG_LEVEL_INFO, "Enabled metadata preservation");
|
||||
} else if (strcmp(argv[i], "-f") == 0 || strcmp(argv[i], "--sendfile") == 0) {
|
||||
config->use_sendfile = true;
|
||||
log_message(LOG_LEVEL_INFO, "Enabled sendfile");
|
||||
} else if (strcmp(argv[i], "-m") == 0) {
|
||||
config->use_multithreading = true;
|
||||
log_message(LOG_LEVEL_INFO, "Enabled Multithreading");
|
||||
} else if (strcmp(argv[i], "-s") == 0) {
|
||||
config->use_chunk_serialization = true;
|
||||
log_message(LOG_LEVEL_INFO, "Enabled Chunk Serialization");
|
||||
} else if (strcmp(argv[i], "--server-host") == 0 && i + 1 < argc) {
|
||||
free(server_host);
|
||||
server_host = str_dup(argv[++i]);
|
||||
} else if (strcmp(argv[i], "--server-port") == 0 && i + 1 < argc) {
|
||||
server_port = atoi(argv[++i]);
|
||||
} else if (strcmp(argv[i], "-v") == 0 || strcmp(argv[i], "--verbose") == 0) {
|
||||
set_log_level(LOG_LEVEL_DEBUG);
|
||||
} else if (argv[i][0] == '-') {
|
||||
fprintf(stderr, "Unknown option: %s\n", argv[i]);
|
||||
print_usage();
|
||||
return 1;
|
||||
} else {
|
||||
if (positional_count < 2)
|
||||
positional_args[positional_count++] = i;
|
||||
else {
|
||||
fprintf(stderr, "Unexpected argument: %s\n", argv[i]);
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (positional_count == 2) {
|
||||
free(config->send_directory);
|
||||
free(config->receive_root_directory);
|
||||
config->send_directory = str_dup(argv[positional_args[0]]);
|
||||
config->receive_root_directory = str_dup(argv[positional_args[1]]);
|
||||
config->save_to_disk = true;
|
||||
|
||||
config_parse_ssh_dest(config);
|
||||
} else if (positional_count == 1) {
|
||||
fprintf(stderr, "Error: missing destination argument\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
} else {
|
||||
if (!config->send_directory && env_source)
|
||||
config->send_directory = str_dup((char *)env_source);
|
||||
if (!config->receive_root_directory && env_dest)
|
||||
config->receive_root_directory = str_dup((char *)env_dest);
|
||||
}
|
||||
|
||||
if (!config->send_directory || !config->receive_root_directory) {
|
||||
fprintf(stderr, "Error: source and destination directories are required\n");
|
||||
print_usage();
|
||||
return 1;
|
||||
}
|
||||
if (config->use_sendfile && (config->use_chunk_serialization || config->use_compression)) {
|
||||
fprintf(stderr, "Error: -f/--sendfile cannot be combined with -c (compression) or -s (chunk serialization)\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (config->transport == TRANSPORT_SSH && config->use_sendfile) {
|
||||
fprintf(stderr, "Error: -f/--sendfile is not supported with SSH transport\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (config->use_multithreading)
|
||||
return send_files_multithreaded(config);
|
||||
return send_files(config);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
#ifndef CLIENT_SEND_H
|
||||
#define CLIENT_SEND_H
|
||||
|
||||
#include "chunk.h"
|
||||
#include "config.h"
|
||||
#include "transport_tcp.h"
|
||||
|
||||
extern char *server_host;
|
||||
extern int server_port;
|
||||
|
||||
int send_chunk(Client *client, Chunk *chunk, Config *config);
|
||||
int send_files(Config *config);
|
||||
int send_files_multithreaded(Config *config);
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user