Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
*.exe
*.out
*.app
./tests/go/kvtest/cmd/kvtest/kvtest
./tests/go/kvtest/kvtest

# Project-specific
*.bak
Expand All @@ -46,3 +48,6 @@ build
var
tmp
current

# Compiled Protobufs
*.pb.*
1 change: 1 addition & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ ARG BUILD_TYPE=release
RUN apt-get update && \
apt-get -y install \
cmake \
ninja-build \
python3 \
python3-pip \
python3-virtualenv && \
Expand Down
4 changes: 2 additions & 2 deletions conan/profiles/debug-clang
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[buildenv]
CC=/usr/bin/clang-20
CXX=/usr/bin/clang++-20
CC=/usr/bin/clang
CXX=/usr/bin/clang++

[settings]
arch=x86_64
Expand Down
61 changes: 0 additions & 61 deletions flake.lock

This file was deleted.

54 changes: 0 additions & 54 deletions flake.nix

This file was deleted.

12 changes: 6 additions & 6 deletions infra/assets/tkvpp_config_standalone.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"loggingLevel": "debug"
},
"database": {
"path": "./var/tkvpp",
"path": "/var/tkvpp",
"walFilename": "wal",
"manifestFilenamePrefix": "manifest_",
"mode": "standalone"
Expand All @@ -14,24 +14,24 @@
"storageType": "persistent"
},
"lsm": {
"flushThreshold": 1024,
"flushThreshold": 64000000,
"maximumLevels": 12,
"levelZeroCompaction": {
"compactionStrategy": "levelled",
"compactionThreshold": 1024
"compactionThreshold": 256000000
},
"levelNonZeroCompaction": {
"compactionStrategy": "tiered",
"compactionThreshold": 1024
"compactionThreshold": 256000000
}
},
"server": {
"transport": "grpc",
"host": "0.0.0.0",
"port": 8081,
"port": 9891,
"id": 1,
"peers": [
"0.0.0.0:8081"
"0.0.0.0:9891"
]
Comment on lines +31 to 35
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Peers should not use 0.0.0.0; make empty for standalone or use real endpoints

"0.0.0.0" is valid for binding but invalid as a remote peer address. In standalone mode, use an empty list; in clustered mode, list concrete host:port values for other nodes.

Apply:

-        "peers": [
-            "0.0.0.0:9891"
-        ]
+        "peers": []
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
"port": 9891,
"id": 1,
"peers": [
"0.0.0.0:8081"
"0.0.0.0:9891"
]
"port": 9891,
"id": 1,
"peers": []
🤖 Prompt for AI Agents
In infra/assets/tkvpp_config_standalone.json around lines 31 to 35, the peers
array contains "0.0.0.0:9891" which is incorrect for remote peer addresses;
update the peers field to be an empty array for standalone mode (i.e., "peers":
[]) or replace with concrete host:port entries when configuring a cluster, and
ensure the bind address remains the correct separate setting if needed.

}
}
14 changes: 11 additions & 3 deletions infra/docker-compose.standalone.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
---
version: '3.8'
services:
app:
tkvpp-node-standalone:
image: tinykvpp-clang:latest
container_name: tkvpp-node-1
security_opt:
- seccomp:unconfined
container_name: tkvpp-node-standalone
command: ["/app/tkvpp", "-c", "/app/config.json"]
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Don’t repeat the binary when image has ENTRYPOINT

With ENTRYPOINT ["/app/tkvpp"] in the image, your current command repeats the binary, leading to "/app/tkvpp /app/tkvpp -c ...". Pass only flags.

Apply:

-    command: ["/app/tkvpp", "-c", "/app/config.json"]
+    command: ["-c", "/app/config.json"]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
command: ["/app/tkvpp", "-c", "/app/config.json"]
command: ["-c", "/app/config.json"]
🤖 Prompt for AI Agents
In infra/docker-compose.standalone.yaml around line 8 the docker-compose service
command redundantly repeats the image ENTRYPOINT ("/app/tkvpp"), resulting in
"/app/tkvpp /app/tkvpp -c ..."; change the command to pass only the
flags/arguments (e.g. "-c", "/app/config.json") so Docker uses the image
ENTRYPOINT with these flags rather than invoking the binary twice.

ports:
- "9891:9891"
volumes:
- ./assets/tkvpp_config_standalone.json:/app/config.json
- tkvpp-node-standalone:/var/tkvpp
volumes:
tkvpp-node-standalone:
8 changes: 6 additions & 2 deletions lib/db/db.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ auto serializeOperation(const db::client_request_t &request) -> std::string
}
default:
{
spdlog::critical("Unknown operation type: {}", magic_enum::enum_name(request.type));
spdlog::critical(
"(serializeOperation): Unknown operation type: {}", magic_enum::enum_name(request.type)
);
break;
}
}
Expand Down Expand Up @@ -398,7 +400,9 @@ auto db_t::onRaftCommit(const raft::v1::LogEntry &entry) -> bool
}
default:
{
spdlog::critical("Unknown operation type: {}", magic_enum::enum_name(op.type()));
spdlog::critical(
"(onRaftCommit): Unknown operation type: {}", magic_enum::enum_name(op.type())
);
return false;
}
}
Expand Down
2 changes: 1 addition & 1 deletion lib/raft/raft.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ const std::string_view gRaftFilename = "RAFT_PERSISTENCE";

auto constructFilename(std::string_view filename, std::uint32_t peerId) -> std::string
{
return fmt::format("./var/tkvpp/{}_NODE_{}", filename, peerId);
return fmt::format("/var/tkvpp/{}_NODE_{}", filename, peerId);
}

auto generate_random_timeout(const int minTimeout, const int maxTimeout) -> int
Expand Down
31 changes: 17 additions & 14 deletions lib/structures/lsmtree/levels/level.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,11 +119,17 @@ auto level_t::compact() const noexcept -> segments::regular_segment::shared_ptr_
const auto bytesUsedForLevel{bytes_used()};

// If level size hasn't reached the size limit then skip the compaction
if ((index() == 0 &&
bytesUsedForLevel < m_pConfig->LSMTreeConfig.LevelZeroCompactionThreshold) ||
(index() != 0 &&
bytesUsedForLevel <
m_pConfig->LSMTreeConfig.LevelNonZeroCompactionThreshold * std::pow(10, index())))
const bool isZeroLevel{index() == 0};
const auto zeroLevelThreshold{m_pConfig->LSMTreeConfig.LevelZeroCompactionThreshold};
if (isZeroLevel && bytesUsedForLevel < zeroLevelThreshold)
{
return nullptr;
}

const auto nonZeroLevelThreshold{
m_pConfig->LSMTreeConfig.LevelNonZeroCompactionThreshold * std::pow(10, index())
};
if (!isZeroLevel && bytesUsedForLevel < nonZeroLevelThreshold)
{
return nullptr;
}
Expand All @@ -135,13 +141,13 @@ auto level_t::compact() const noexcept -> segments::regular_segment::shared_ptr_
std::vector<std::pair<
typename memtable::memtable_t::const_iterator,
typename memtable::memtable_t::const_iterator>>,
IteratorCompare<memtable_t, memtable_t>>
IteratorCompare<memtable_t>>
minHeap;

for (const auto &segment : m_storage)
{
// TODO(lnikon): reset memtable inside regular_segment_t at the of the
// flush() and recover it here e.g. segment->recover_memtable();
// TODO(lnikon): reset memtable inside regular_segment_t at the of the flush() and recover
// it here e.g. segment->recover_memtable();
const auto &currentMemtable = segment->memtable().value();
minHeap.emplace(currentMemtable.begin(), currentMemtable.end());
}
Expand All @@ -154,8 +160,7 @@ auto level_t::compact() const noexcept -> segments::regular_segment::shared_ptr_
minHeap.pop();

// Add the smallest element to the merged sequence.
// If two elements have the same key, then choose the one with the
// greatest timestamp
// If two elements have the same key, then choose the one with the greatest timestamp
if (mergedMemtable.empty() || lastKey != current.first->m_key)
{
mergedMemtable.emplace(*current.first);
Expand All @@ -171,8 +176,7 @@ auto level_t::compact() const noexcept -> segments::regular_segment::shared_ptr_
}

// Create a new segment from the compacted segment.
// The postfix "_compacted" signals that the segment is an intermediate
// result
// The postfix "_compacted" signals that the segment is an intermediate result
auto name{fmt::format("{}_{}_compacted", helpers::segment_name(), index())};
return segments::factories::lsmtree_segment_factory(
name, helpers::segment_path(m_pConfig->datadir_path(), name), mergedMemtable
Expand Down Expand Up @@ -231,14 +235,13 @@ void level_t::merge(const segments::regular_segment::shared_ptr_t &pSegment) noe

// TODO(lnikon): Make this parameter configurable. Use measurement
// units(mb).
const std::size_t segmentSize{1024};
memtable::memtable_t newMemtable;
segments::storage::segment_storage_t newSegments;

for (const auto &currentRecord : mergedMemtable)
{
newMemtable.emplace(currentRecord);
if (newMemtable.size() >= segmentSize)
if (newMemtable.size() >= m_pConfig->LSMTreeConfig.SegmentSize)
{
auto name{fmt::format("{}_{}", helpers::segment_name(), index())};
newSegments.emplace(
Expand Down
37 changes: 22 additions & 15 deletions lib/structures/lsmtree/levels/levels.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,14 +98,17 @@ auto levels_t::compact() -> segments::regular_segment::shared_ptr_t
}
));

// Update manifest with new segment
ASSERT(m_pManifest->add(
db::manifest::manifest_t::segment_record_t{
.op = segment_operation_k::add_segment_k,
.name = compactedCurrentLevelSegment->get_name(),
.level = currentLevel->index()
}
));
{
// Update manifest with new segment
auto ok{m_pManifest->add(
db::manifest::manifest_t::segment_record_t{
.op = segment_operation_k::add_segment_k,
.name = compactedCurrentLevelSegment->get_name(),
.level = currentLevel->index()
}
)};
ASSERT(ok);
}

// If computation succeeded, then flush the compacted segment into disk
compactedCurrentLevelSegment->flush();
Expand All @@ -121,13 +124,16 @@ auto levels_t::compact() -> segments::regular_segment::shared_ptr_t

// Purge the segment representing the compacted level and update the
// manifest
ASSERT(m_pManifest->add(
db::manifest::manifest_t::segment_record_t{
.op = segment_operation_k::remove_segment_k,
.name = compactedCurrentLevelSegment->get_name(),
.level = currentLevel->index()
}
));
{
bool ok{m_pManifest->add(
db::manifest::manifest_t::segment_record_t{
.op = segment_operation_k::remove_segment_k,
.name = compactedCurrentLevelSegment->get_name(),
.level = currentLevel->index()
}
)};
ASSERT(ok);
}
compactedCurrentLevelSegment->remove_from_disk();

// After merging current level into the next level purge the current
Expand Down Expand Up @@ -183,6 +189,7 @@ auto levels_t::size() const noexcept -> levels_t::levels_storage_t::size_type
[[nodiscard]] auto levels_t::flush_to_level0(memtable::memtable_t memtable) const noexcept
-> segments::regular_segment::shared_ptr_t
{

absl::MutexLock lock{&m_mutex};

assert(m_levels[0]);
Expand Down
Loading