mirror of
https://github.com/dragonflydb/dragonfly.git
synced 2025-05-11 10:25:47 +02:00
feat(replica): support multi transaction command (#634)
This commit is contained in:
parent
b944324bbf
commit
3065946b9a
16 changed files with 223 additions and 106 deletions
|
@ -42,6 +42,11 @@ void JournalWriter::Write(std::string_view sv) {
|
|||
|
||||
void JournalWriter::Write(CmdArgList args) {
|
||||
Write(args.size());
|
||||
size_t cmd_size = 0;
|
||||
for (auto v : args) {
|
||||
cmd_size += v.size();
|
||||
}
|
||||
Write(cmd_size);
|
||||
for (auto v : args)
|
||||
Write(facade::ToSV(v));
|
||||
}
|
||||
|
@ -50,6 +55,13 @@ void JournalWriter::Write(std::pair<std::string_view, ArgSlice> args) {
|
|||
auto [cmd, tail_args] = args;
|
||||
|
||||
Write(1 + tail_args.size());
|
||||
|
||||
size_t cmd_size = cmd.size();
|
||||
for (auto v : tail_args) {
|
||||
cmd_size += v.size();
|
||||
}
|
||||
Write(cmd_size);
|
||||
|
||||
Write(cmd);
|
||||
for (auto v : tail_args)
|
||||
Write(v);
|
||||
|
@ -71,6 +83,8 @@ void JournalWriter::Write(const journal::Entry& entry) {
|
|||
case journal::Op::SELECT:
|
||||
return Write(entry.dbid);
|
||||
case journal::Op::COMMAND:
|
||||
case journal::Op::MULTI_COMMAND:
|
||||
case journal::Op::EXEC:
|
||||
Write(entry.txid);
|
||||
Write(entry.shard_cnt);
|
||||
return std::visit([this](const auto& payload) { return Write(payload); }, entry.payload);
|
||||
|
@ -80,7 +94,7 @@ void JournalWriter::Write(const journal::Entry& entry) {
|
|||
}
|
||||
|
||||
JournalReader::JournalReader(io::Source* source, DbIndex dbid)
|
||||
: str_buf_{}, source_{source}, buf_{4096}, dbid_{dbid} {
|
||||
: source_{source}, buf_{4_KB}, dbid_{dbid} {
|
||||
}
|
||||
|
||||
void JournalReader::SetDb(DbIndex dbid) {
|
||||
|
@ -134,63 +148,63 @@ template io::Result<uint16_t> JournalReader::ReadUInt<uint16_t>();
|
|||
template io::Result<uint32_t> JournalReader::ReadUInt<uint32_t>();
|
||||
template io::Result<uint64_t> JournalReader::ReadUInt<uint64_t>();
|
||||
|
||||
io::Result<size_t> JournalReader::ReadString() {
|
||||
io::Result<size_t> JournalReader::ReadString(char* buffer) {
|
||||
size_t size = 0;
|
||||
SET_OR_UNEXPECT(ReadUInt<uint64_t>(), size);
|
||||
|
||||
if (auto ec = EnsureRead(size); ec)
|
||||
return make_unexpected(ec);
|
||||
|
||||
unsigned offset = str_buf_.size();
|
||||
str_buf_.resize(offset + size);
|
||||
buf_.ReadAndConsume(size, str_buf_.data() + offset);
|
||||
buf_.ReadAndConsume(size, buffer);
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
std::error_code JournalReader::Read(CmdArgVec* vec) {
|
||||
std::error_code JournalReader::ReadCommand(journal::ParsedEntry::CmdData* data) {
|
||||
size_t num_strings = 0;
|
||||
SET_OR_RETURN(ReadUInt<uint64_t>(), num_strings);
|
||||
vec->resize(num_strings);
|
||||
data->cmd_args.resize(num_strings);
|
||||
|
||||
size_t cmd_size = 0;
|
||||
SET_OR_RETURN(ReadUInt<uint64_t>(), cmd_size);
|
||||
|
||||
// Read all strings consecutively.
|
||||
str_buf_.clear();
|
||||
for (auto& span : *vec) {
|
||||
data->command_buf = make_unique<char[]>(cmd_size);
|
||||
char* ptr = data->command_buf.get();
|
||||
for (auto& span : data->cmd_args) {
|
||||
size_t size;
|
||||
SET_OR_RETURN(ReadString(), size);
|
||||
span = MutableSlice{nullptr, size};
|
||||
SET_OR_RETURN(ReadString(ptr), size);
|
||||
span = MutableSlice{ptr, size};
|
||||
ptr += size;
|
||||
}
|
||||
|
||||
// Set span pointers, now that string buffer won't reallocate.
|
||||
char* ptr = str_buf_.data();
|
||||
for (auto& span : *vec) {
|
||||
span = {ptr, span.size()};
|
||||
ptr += span.size();
|
||||
}
|
||||
|
||||
return std::error_code{};
|
||||
}
|
||||
|
||||
io::Result<journal::ParsedEntry> JournalReader::ReadEntry() {
|
||||
uint8_t opcode;
|
||||
SET_OR_UNEXPECT(ReadUInt<uint8_t>(), opcode);
|
||||
uint8_t int_op;
|
||||
SET_OR_UNEXPECT(ReadUInt<uint8_t>(), int_op);
|
||||
journal::Op opcode = static_cast<journal::Op>(int_op);
|
||||
|
||||
journal::ParsedEntry entry{static_cast<journal::Op>(opcode), dbid_};
|
||||
if (opcode == journal::Op::SELECT) {
|
||||
SET_OR_UNEXPECT(ReadUInt<uint16_t>(), dbid_);
|
||||
return ReadEntry();
|
||||
}
|
||||
|
||||
journal::ParsedEntry entry;
|
||||
entry.dbid = dbid_;
|
||||
entry.opcode = opcode;
|
||||
|
||||
SET_OR_UNEXPECT(ReadUInt<uint64_t>(), entry.txid);
|
||||
SET_OR_UNEXPECT(ReadUInt<uint32_t>(), entry.shard_cnt);
|
||||
|
||||
if (opcode == journal::Op::EXEC) {
|
||||
return entry;
|
||||
}
|
||||
|
||||
auto ec = ReadCommand(&entry.cmd);
|
||||
if (ec)
|
||||
return make_unexpected(ec);
|
||||
|
||||
switch (entry.opcode) {
|
||||
case journal::Op::COMMAND:
|
||||
SET_OR_UNEXPECT(ReadUInt<uint64_t>(), entry.txid);
|
||||
SET_OR_UNEXPECT(ReadUInt<uint32_t>(), entry.shard_cnt);
|
||||
entry.payload = CmdArgVec{};
|
||||
if (auto ec = Read(&*entry.payload); ec)
|
||||
return make_unexpected(ec);
|
||||
break;
|
||||
case journal::Op::SELECT:
|
||||
SET_OR_UNEXPECT(ReadUInt<uint16_t>(), dbid_);
|
||||
return ReadEntry();
|
||||
default:
|
||||
break;
|
||||
};
|
||||
return entry;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue