Files
ldb/kvs_oplog.c

132 lines
3.0 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "kvstore.h"
#include "kvs_rw_tools.h"
#include "mem_pool/mem_pool.h"
#include "kvs_protocol_resp.h"
#include "diskuring/diskuring.h"
#include <arpa/inet.h>
#include <fcntl.h>
#include <unistd.h>
int global_cmd_log_fd = -1;
static off_t g_log_off = -1;
int init_cmd_log(const char *file, int *logfd){
if(!file) return -1;
int fd = open(file, O_RDWR | O_CREAT , 0644);
if(fd < 0) return -2;
g_log_off = lseek(fd, 0, SEEK_END);
*logfd = fd;
return 0;
}
int destroy_cmd_log(int logfd){
fsync(logfd);
close(logfd);
global_cmd_log_fd = -1;
return 0;
}
int kvs_oplog_append(const uint8_t *cmd, size_t len, int logfd){
if (logfd < 0 || !cmd || len == 0) return -1;
if (len > UINT32_MAX) return -2;
uint32_t nlen = htonl((uint32_t)len);
void *bufs[2];
size_t lens[2];
bufs[0] = (void *)&nlen;
lens[0] = sizeof(nlen);
bufs[1] = (void *)cmd;
lens[1] = len;
size_t total = sizeof(nlen) + len;
off_t myoff = g_log_off;
g_log_off += (off_t)total;
task_t *t = submit_write(&global_uring_ctx, logfd, bufs, lens, 2, myoff);
if (!t) {
return -4;
}
task_wait(t);
task_destroy(t);
return 0;
}
int kvs_replay_log(int logfd){
if (logfd < 0) return -1;
if (lseek(logfd, 0, SEEK_SET) < 0) {
return -1;
}
for (;;) {
uint32_t nlen = 0;
int hr = read_full(logfd, &nlen, sizeof(nlen));
if (hr == 0) break; /* EOF正常结束 */
if (hr < 0) { return -2; } /* 半截头 */
uint32_t len = ntohl(nlen);
if (len == 0) { return -3; }
uint8_t *cmd_bytes = (uint8_t *)kvs_malloc(len);
if (!cmd_bytes ) { return -5; }
int pr = read_full(logfd, cmd_bytes, len);
if (pr <= 0) { /* 半截 payload */
kvs_free(cmd_bytes );
return -6;
}
/* -------- RESP parse -------- */
resp_cmd_t cmd;
memset(&cmd, 0, sizeof(cmd));
int clen = resp_parse_one_cmd(cmd_bytes, (int)len, &cmd);
if (clen <= 0 || clen != (int)len) {
/* clen==0: need more data但日志记录必须是一条完整命令所以视为坏日志 */
kvs_free(cmd_bytes);
return -7;
}
/* -------- execute -------- */
resp_value_t outvalue;
memset(&outvalue, 0, sizeof(outvalue));
int dr = resp_dispatch(&cmd, &outvalue);
if (dr < 0) {
kvs_free(cmd_bytes);
return -8;
}
/* 注意:
* outv 可能引用存储内存,但我们不 build response因此无需处理。
* cmd_bytes 可以释放,因为 cmd slice 指向 cmd_bytes仅在 dispatch 期间使用。
* */
kvs_free(cmd_bytes);
}
g_log_off = lseek(logfd, 0, SEEK_CUR);
return 0;
}
/**
* clear log file not close
*/
int ksv_clear_log(int logfd){
if(logfd < 0) return -1;
ftruncate(logfd, 0);
lseek(logfd, 0, SEEK_SET);
g_log_off = 0;
return 0;
}