-
Notifications
You must be signed in to change notification settings - Fork 24
feat: support partition group #423
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,6 +5,7 @@ | |
| #include <cstdint> | ||
| #include <cstring> | ||
| #include <functional> | ||
| #include <optional> | ||
| #include <string> | ||
| #include <vector> | ||
|
|
||
|
|
@@ -20,6 +21,9 @@ constexpr int64_t TB = 1LL << 40; | |
|
|
||
| constexpr uint8_t max_overflow_pointers = 128; | ||
| constexpr uint16_t max_read_pages_batch = max_overflow_pointers; | ||
| using PartitionFilter = | ||
| std::function<std::optional<PartitionGroupId>(const TableIdent &)>; | ||
|
|
||
| struct KvOptions | ||
| { | ||
| int LoadFromIni(const char *path); | ||
|
|
@@ -304,15 +308,15 @@ struct KvOptions | |
| uint16_t prewarm_task_count = 3; | ||
|
|
||
| /** | ||
| * @brief Filter function to determine which partitions belong to this | ||
| * instance. | ||
| * The filter returning true means that this table partition belongs to the | ||
| * current instance and should be included in operations like prewarming, | ||
| * snapshotting, etc. | ||
| * @brief Classify which partition group a table partition belongs to. | ||
| * Returning std::nullopt means that this partition does not belong to this | ||
| * instance. If the function returns a partition group id, runtime | ||
| * partition-group state decides whether that partition is currently active | ||
| * for operations like prewarming, snapshotting, and reopen. | ||
| * If not set (empty), all partitions are considered to belong to this | ||
| * instance. | ||
| */ | ||
| std::function<bool(const TableIdent &)> partition_filter; | ||
| PartitionFilter partition_filter; | ||
|
Comment on lines
+311
to
+319
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There’s still one stale bool-era doc block above. The comment at Lines 299-301 still says the filter "returns true", but the public contract is now 🤖 Prompt for AI Agents |
||
| }; | ||
|
|
||
| } // namespace eloqstore | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -115,10 +115,19 @@ class KvTask | |
| int WaitIoResult(); | ||
| void WaitIo(); | ||
| void FinishIo(); | ||
| void ForceAbort() | ||
| { | ||
| force_aborted_ = true; | ||
| } | ||
| bool ForceAborted() const | ||
| { | ||
| return force_aborted_; | ||
| } | ||
|
Comment on lines
+118
to
+125
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
set -euo pipefail
echo "Assignments to force_aborted_:"
rg -n -C2 '\bforce_aborted_\s*='
echo
echo "Task acquisition/reset sites:"
rg -n -C5 'TaskManager::Get(BatchWriteTask|BackgroundWrite|ReadTask|ScanTask|ListObjectTask|ListStandbyPartitionTask|ReopenTask)|\bFreeTask\s*\('Repository: eloqdata/eloqstore Length of output: 9054 🏁 Script executed: # Find Reset() implementations in task classes
ast-grep --pattern 'void Reset($$$) {
$$$
}'Repository: eloqdata/eloqstore Length of output: 1731 🏁 Script executed: # Also check the base KvTask class and derived task classes for initialization
rg -n 'class.*Task.*:' include/tasks/ | head -20Repository: eloqdata/eloqstore Length of output: 606 🏁 Script executed: # Check if force_aborted_ is initialized in constructors
rg -n -B5 -A10 'force_aborted_' include/tasks/task.hRepository: eloqdata/eloqstore Length of output: 634 🏁 Script executed: # Search for Reset() in WriteTask and derived classes
rg -n -A15 'void Reset' include/tasks/write_task.hRepository: eloqdata/eloqstore Length of output: 1552 🏁 Script executed: # Search for Reset() in ReadTask
rg -n -A15 'void Reset' include/tasks/read_task.hRepository: eloqdata/eloqstore Length of output: 44 🏁 Script executed: # Search for Reset() in ScanTask
rg -n -A15 'void Reset' include/tasks/scan_task.hRepository: eloqdata/eloqstore Length of output: 465 🏁 Script executed: # Check ListObjectTask and ListStandbyPartitionTask
rg -n -A15 'void Reset' include/tasks/list_object_task.h include/tasks/list_standby_partition_task.hRepository: eloqdata/eloqstore Length of output: 44 🏁 Script executed: # Find WriteTask::Reset() implementation
rg -n -A20 'void WriteTask::Reset' src/Repository: eloqdata/eloqstore Length of output: 1727 🏁 Script executed: # Check if ReadTask constructor/destructor or any Reset exists
cat -n include/tasks/read_task.hRepository: eloqdata/eloqstore Length of output: 1215 🏁 Script executed: # Check KvTask base class for any Reset method
rg -n 'virtual.*Reset|void Reset' include/tasks/task.hRepository: eloqdata/eloqstore Length of output: 44 Force-aborted state persists on task pool reuse—all task types need explicit reset.
Add
🤖 Prompt for AI Agents |
||
|
|
||
| uint32_t inflight_io_{0}; | ||
| int io_res_{0}; | ||
| uint32_t io_flags_{0}; | ||
| bool force_aborted_{false}; | ||
|
|
||
| TaskStatus status_{TaskStatus::Idle}; | ||
| KvRequest *req_{nullptr}; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -14,6 +14,8 @@ | |
|
|
||
| namespace eloqstore | ||
| { | ||
| using PartitionGroupId = uint32_t; | ||
|
|
||
| enum class StoreMode | ||
| { | ||
| Local = 0, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -992,12 +992,41 @@ KvError ToKvError(int err_no) | |
| return KvError::OpenFileLimit; | ||
| case -ENOSPC: | ||
| return KvError::OutOfSpace; | ||
| case -ECANCELED: | ||
| return KvError::Aborted; | ||
| default: | ||
| LOG(ERROR) << "ToKvError: " << err_no; | ||
| return KvError::IoFail; | ||
| } | ||
| } | ||
|
|
||
| int KvErrorToIoResult(KvError err) | ||
| { | ||
| switch (err) | ||
| { | ||
| case KvError::NoError: | ||
| return 0; | ||
| case KvError::NoPermission: | ||
| return -EPERM; | ||
| case KvError::NotFound: | ||
| return -ENOENT; | ||
| case KvError::TryAgain: | ||
| return -EAGAIN; | ||
| case KvError::OutOfMem: | ||
| return -ENOMEM; | ||
| case KvError::Busy: | ||
| return -EBUSY; | ||
| case KvError::OpenFileLimit: | ||
| return -EMFILE; | ||
| case KvError::OutOfSpace: | ||
| return -ENOSPC; | ||
| case KvError::Aborted: | ||
| return -ECANCELED; | ||
| default: | ||
| return -EIO; | ||
| } | ||
| } | ||
|
Comment on lines
+1003
to
+1028
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Unmapped values fall back to 🔧 Proposed fix (make conversion symmetric for standby-produced errors) KvError ToKvError(int err_no)
{
if (err_no >= 0)
{
return KvError::NoError;
}
switch (err_no)
{
+ case -EINVAL:
+ return KvError::InvalidArgs;
case -EPERM:
return KvError::NoPermission;
case -ENOENT:
return KvError::NotFound;
+ case -ESTALE:
+ return KvError::ExpiredTerm;
+ case -ESHUTDOWN:
+ return KvError::NotRunning;
case -EINTR:
case -EAGAIN:
case -ENOBUFS:
return KvError::TryAgain;
case -ENOMEM:
@@
int KvErrorToIoResult(KvError err)
{
switch (err)
{
case KvError::NoError:
return 0;
+ case KvError::InvalidArgs:
+ return -EINVAL;
case KvError::NoPermission:
return -EPERM;
case KvError::NotFound:
return -ENOENT;
+ case KvError::ExpiredTerm:
+ return -ESTALE;
+ case KvError::NotRunning:
+ return -ESHUTDOWN;
case KvError::TryAgain:
return -EAGAIN;🤖 Prompt for AI Agents |
||
|
|
||
| std::pair<void *, IouringMgr::UserDataType> IouringMgr::DecodeUserData( | ||
| uint64_t user_data) | ||
| { | ||
|
|
@@ -4673,7 +4702,7 @@ std::pair<ManifestFilePtr, KvError> StandbyStoreMgr::GetManifest( | |
| return {nullptr, prep_err}; | ||
| } | ||
| current_task->WaitIo(); | ||
| prep_err = static_cast<KvError>(current_task->io_res_); | ||
| prep_err = ToKvError(current_task->io_res_); | ||
| if (prep_err != KvError::NoError) | ||
| { | ||
| return {nullptr, prep_err}; | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pending_needs owned lifetime across shard queues.The implementation at Lines 1555-1576 in
src/eloq_store.cpppoints this field at a stackstd::atomic<uint32_t>and enqueues rawApplyPartitionChangeRequest*owned by a localsub_reqsvector. If any laterAddKvRequest()fails, the function returns while already-queued shards still hold dangling pointers to both the counter and the request objects. Please switch this to heap/shared state or drain already-enqueued work before returning.🤖 Prompt for AI Agents