已有数据同步功能完成
This commit is contained in:
@@ -2,15 +2,16 @@
|
||||
#define __KVS_DUMP_H__
|
||||
|
||||
#include "kvstore.h"
|
||||
#include "diskuring/diskuring.h"
|
||||
|
||||
extern char global_oplog_file[256];
|
||||
extern char global_array_file[256];
|
||||
extern char global_rbtree_file[256];
|
||||
extern char global_hash_file[256];
|
||||
|
||||
int kvs_create_snapshot(const char* array_file, const char* rbtree_file, const char* hash_file);
|
||||
int kvs_create_snapshot(iouring_ctx_t *uring, const char* array_file, const char* rbtree_file, const char* hash_file);
|
||||
int kvs_create_snapshot_async(const char *ip, int port);
|
||||
void __create_snapshot_ok(const char* array_file, const char* rbtree_file, const char* hash_file);
|
||||
void __complete_snapshot(const char *ip, int port, const char *array_file, const char *rbtree_file, const char *hash_file);
|
||||
|
||||
extern int global_oplog_fd;
|
||||
|
||||
|
||||
@@ -1,16 +1,20 @@
|
||||
#include "kvstore.h"
|
||||
#include "diskuring/diskuring.h"
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
char global_oplog_file[256] = "kvs_oplog.default.db";
|
||||
char global_array_file[256] = "kvs_array.default.db";
|
||||
char global_rbtree_file[256] = "kvs_rbtree.default.db";
|
||||
char global_hash_file[256] = "kvs_hash.default.db";
|
||||
|
||||
int kvs_create_snapshot(const char* array_file, const char* rbtree_file, const char* hash_file){
|
||||
int kvs_create_snapshot(iouring_ctx_t *uring, const char* array_file, const char* rbtree_file, const char* hash_file){
|
||||
int ret = 0;
|
||||
int rc = 0;
|
||||
#if ENABLE_ARRAY
|
||||
rc = kvs_array_save(&global_array, array_file);
|
||||
rc = kvs_array_save(uring, &global_array, array_file);
|
||||
if(rc < 0){
|
||||
printf("kvs_engine_array save error\n");
|
||||
ret = -1;
|
||||
@@ -18,7 +22,7 @@ int kvs_create_snapshot(const char* array_file, const char* rbtree_file, const c
|
||||
#endif
|
||||
|
||||
#if ENABLE_RBTREE
|
||||
rc = kvs_rbtree_save(&global_rbtree, rbtree_file);
|
||||
rc = kvs_rbtree_save(uring, &global_rbtree, rbtree_file);
|
||||
if(rc < 0){
|
||||
printf("kvs_engine_rbtree save error\n");
|
||||
ret = -1;
|
||||
@@ -26,7 +30,7 @@ int kvs_create_snapshot(const char* array_file, const char* rbtree_file, const c
|
||||
#endif
|
||||
|
||||
#if ENABLE_HASH
|
||||
rc = kvs_hash_save(&global_hash, hash_file);
|
||||
rc = kvs_hash_save(uring, &global_hash, hash_file);
|
||||
if(rc < 0){
|
||||
printf("kvs_engine_hash save error\n");
|
||||
ret = -1;
|
||||
@@ -35,44 +39,93 @@ int kvs_create_snapshot(const char* array_file, const char* rbtree_file, const c
|
||||
return ret;
|
||||
}
|
||||
|
||||
void __create_snapshot_ok(const char* array_file, const char* rbtree_file, const char* hash_file){
|
||||
void __complete_snapshot(const char *ip, int port, const char *array_file, const char *rbtree_file, const char *hash_file){
|
||||
|
||||
}
|
||||
|
||||
int kvs_create_snapshot_async(const char *ip, int port){
|
||||
int pipefd[2]; // 用于子进程通知主进程
|
||||
if (pipe(pipefd) == -1) { perror("pipe"); return -1; }
|
||||
pid_t pid = fork();
|
||||
if (pid == -1) { perror("fork"); return -1; }
|
||||
static int send_file_to_ipport(const char *ip, int port, const char *filename) {
|
||||
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (sockfd < 0) { perror("socket"); return -1; }
|
||||
|
||||
if (pid == 0) { // 子进程
|
||||
close(pipefd[0]); // 关闭读端
|
||||
// 指定临时文件路径,避免覆盖 global_xxx_file
|
||||
char tmp_array[128]; // 可写缓冲区
|
||||
char tmp_rbtree[128];
|
||||
char tmp_hash[128];
|
||||
struct sockaddr_in addr;
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_port = htons(port);
|
||||
addr.sin_addr.s_addr = inet_addr(ip);
|
||||
|
||||
snprintf(tmp_array, sizeof(tmp_array), "snapshot_array_%s.tmp", ip);
|
||||
snprintf(tmp_rbtree, sizeof(tmp_rbtree), "snapshot_rbtree_%s.tmp", ip);
|
||||
snprintf(tmp_hash, sizeof(tmp_hash), "snapshot_hash_%s.tmp", ip);
|
||||
|
||||
int ret = kvs_create_snapshot(tmp_array, tmp_rbtree, tmp_hash);
|
||||
if (ret == 0) {
|
||||
// 成功:rename 到最终路径,或直接通知
|
||||
write(pipefd[1], "OK", 2); // 通知主进程
|
||||
} else {
|
||||
write(pipefd[1], "ERR", 3);
|
||||
}
|
||||
close(pipefd[1]);
|
||||
_exit(0); // 子进程退出
|
||||
|
||||
// hook point
|
||||
__create_snapshot_ok(tmp_array, tmp_rbtree, tmp_hash);
|
||||
} else { // 主进程
|
||||
close(pipefd[1]); // 关闭写端
|
||||
// 立即返回,继续处理其他请求(不阻塞)
|
||||
// 可以记录 pid,在别处 waitpid(pid, NULL, WNOHANG) 检查完成
|
||||
// 或用信号:signal(SIGCHLD, handler); 在 handler 中 read(pipefd[0]) 检查 "OK"
|
||||
return 0; // SYNC 响应成功,主进程继续
|
||||
if (connect(sockfd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
|
||||
perror("connect"); close(sockfd); return -1;
|
||||
}
|
||||
|
||||
FILE *fp = fopen(filename, "rb");
|
||||
if (!fp) { perror("fopen"); close(sockfd); return -1; }
|
||||
|
||||
char buf[4096];
|
||||
size_t n;
|
||||
|
||||
while ((n = fread(buf, 1, sizeof(buf), fp)) > 0) {
|
||||
ssize_t written = 0;
|
||||
while (written < n) {
|
||||
ssize_t ret = write(sockfd, buf + written, n - written);
|
||||
if (ret < 0) {
|
||||
perror("write");
|
||||
fclose(fp);
|
||||
close(sockfd);
|
||||
return -1;
|
||||
}
|
||||
written += ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (ferror(fp)) {
|
||||
perror("fread");
|
||||
fclose(fp);
|
||||
close(sockfd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
shutdown(sockfd, SHUT_WR);
|
||||
close(sockfd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kvs_create_snapshot_async(const char *ip, int port){
|
||||
pid_t pid = fork();
|
||||
if (pid == -1) { perror("fork"); return -1; }
|
||||
|
||||
if (pid == 0) {
|
||||
char tmp_array[128];
|
||||
char tmp_rbtree[128];
|
||||
char tmp_hash[128];
|
||||
|
||||
snprintf(tmp_array, sizeof(tmp_array), "data/snapshot_array_%s.tmp.db", ip);
|
||||
snprintf(tmp_rbtree, sizeof(tmp_rbtree), "data/snapshot_rbtree_%s.tmp.db", ip);
|
||||
snprintf(tmp_hash, sizeof(tmp_hash), "data/snapshot_hash_%s.tmp.db", ip);
|
||||
|
||||
iouring_ctx_t uring;
|
||||
iouring_init(&uring, 256);
|
||||
|
||||
int ret = kvs_create_snapshot(&uring, tmp_array, tmp_rbtree, tmp_hash);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr, "snapshot creation failed\n");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
// 发送快照到目标 IP:port
|
||||
if (send_file_to_ipport(ip, port, tmp_array) != 0 ||
|
||||
send_file_to_ipport(ip, port, tmp_rbtree) != 0 ||
|
||||
send_file_to_ipport(ip, port, tmp_hash) != 0) {
|
||||
fprintf(stderr, "snapshot send failed\n");
|
||||
_exit(1);
|
||||
}
|
||||
|
||||
// hook 通知 eBPF
|
||||
__complete_snapshot(ip, port, tmp_array, tmp_rbtree, tmp_hash);
|
||||
|
||||
iouring_shutdown(&uring);
|
||||
_exit(0);
|
||||
} else {
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user