Skip to content
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

feat: Add log size calculation by index range #10

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

LHG41278
Copy link

@LHG41278 LHG41278 commented Jan 26, 2025

  1. Multiplex the LogManager::get_entry() interface to access cached log entries, manage memory/disk consistency, and minimize code changes.
  2. Design a Node::get_log_size_diff_by_index() interface to calculate the log size difference within a specified index range [index1, index2].

Associated kiwi Issue : arana-db/kiwi#70

Summary by CodeRabbit

  • New Features

    • Added a method to calculate log size differences between specified indices.
    • Introduced a virtual first log ID for improved log management.
  • Tests

    • Added a comprehensive test case for the log size difference calculation method.

These updates enhance log management and tracking capabilities, providing detailed insights into log entry sizes and positioning.

Copy link

coderabbitai bot commented Jan 26, 2025

Walkthrough

The pull request introduces a new private member variable _virtual_first_log_id in the LogManager class to assist with log management. Additionally, it adds the method get_log_size_diff_by_index across multiple files, enabling the calculation of the total size of log entries between two specified indices in the NodeImpl and Node classes. Corresponding updates include header definitions and a new test case in test_node.cpp to validate the new functionality.

Changes

File Change Summary
src/braft/log_manager.h Added private member LogId _virtual_first_log_id to LogManager class
src/braft/node.h Added method int get_log_size_diff_by_index(int64_t index1, int64_t index2) to NodeImpl class
src/braft/node.cpp Implemented get_log_size_diff_by_index method to calculate log entry sizes between indices
src/braft/raft.h Added method int get_log_size_diff_by_index(int index1, int index2) to Node class
src/braft/raft.cpp Implemented method to call corresponding implementation in _impl object
test/test_node.cpp Added test case GetLogSizeDiffByIndex to validate log size difference calculation

Sequence Diagram

sequenceDiagram
    participant Node
    participant NodeImpl
    participant LogManager
    
    Node->>NodeImpl: get_log_size_diff_by_index(index1, index2)
    NodeImpl->>LogManager: Retrieve log entries
    LogManager-->>NodeImpl: Return log entries
    NodeImpl->>NodeImpl: Calculate total log size
    NodeImpl-->>Node: Return log size difference
Loading

Poem

🐰 A Rabbit's Log Tale 🐰

Indices dancing, sizes in flight,
Logs measured with algorithmic might.
From first to last, a size we'll trace,
Through braft's magical logging space.
A computational bunny's delight! 🥕

✨ Finishing Touches
  • 📝 Generate Docstrings (Beta)

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR. (Beta)
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (3)
test/test_node.cpp (2)

3923-3929: Consider making log sizes explicit for better test maintainability.

The test data setup could be more explicit about the expected sizes of each log entry.

 const std::vector<std::string> test_logs = {
-    "log1",        // 4 bytes
-    "longer_log2", // 11 bytes
-    "log3",        // 4 bytes
-    "very_very_long_log4" // 19 bytes
+    "log1",                 // size = 4 bytes
+    "longer_log2",         // size = 11 bytes  
+    "log3",                // size = 4 bytes
+    "very_very_long_log4"  // size = 19 bytes
 };
-const int expected_total_size = 4 + 11 + 4 + 19;
+// Total size of all log entries
+const int expected_total_size = 4 + 11 + 4 + 19; // 38 bytes

3942-3943: Add clarifying comment about initial configuration log.

The test assumes knowledge about an initial configuration log. This should be explicitly documented.

 const int64_t last_idx = leader->get_last_log_index();
-ASSERT_EQ(last_idx, test_logs.size() + 1); // Initial config log + 4 test logs
+// last_idx should be test_logs.size() + 1 because:
+// - Index 1: Initial configuration log (automatically added)
+// - Index 2-5: Our 4 test log entries
+ASSERT_EQ(last_idx, test_logs.size() + 1);
src/braft/node.cpp (1)

2276-2288: Consider optimizing memory management and logging.

  1. The log entry memory management could be improved by using RAII patterns.
  2. The INFO level logging for each entry size might be too verbose for production.

Consider these improvements:

-    LogEntry* entry = _log_manager->get_entry(i);
-    if (!entry) {
-        LOG(ERROR) << "node " << _group_id << ":" << _server_id
-                   << " failed to get log entry at index=" << i;
-        return -1;
-    }
-    LOG(INFO) << "node entry index " << i << " : size " << entry->data.length();
-
-    total_size += entry->data.length();
-    entry->Release();
+    std::unique_ptr<LogEntry> entry(_log_manager->get_entry(i));
+    if (!entry) {
+        LOG(ERROR) << "node " << _group_id << ":" << _server_id
+                   << " failed to get log entry at index=" << i;
+        return -1;
+    }
+    BRAFT_VLOG << "node entry index " << i << " : size " << entry->data.length();
+
+    total_size += entry->data.length();
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 26eee3a and e06b9cf.

📒 Files selected for processing (6)
  • src/braft/log_manager.h (1 hunks)
  • src/braft/node.cpp (1 hunks)
  • src/braft/node.h (1 hunks)
  • src/braft/raft.cpp (1 hunks)
  • src/braft/raft.h (1 hunks)
  • test/test_node.cpp (1 hunks)
🔇 Additional comments (4)
test/test_node.cpp (1)

3945-3962: Well-structured test cases covering key scenarios.

The test cases comprehensively cover:

  1. Same index calculation
  2. Full range calculation
  3. Reverse index order
  4. Partial range calculation
  5. Out-of-bounds detection

The test implementation is thorough and well-organized.

src/braft/node.cpp (3)

2255-2259: LGTM! Parameter validation is handled correctly.

The implementation correctly handles the case where index1 > index2 by swapping them to ensure proper range calculation.


2260-2274: LGTM! Range validation is thorough and provides clear error messages.

The code properly validates that both indices are within the valid range of log entries, checking against both first_log_index and last_log_index.


2290-2291: LGTM! Return value is appropriate.

The method correctly returns the total size or -1 on error.

Comment on lines +156 to +157


Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Initialize and document thread safety for the new member variable.

The new _virtual_first_log_id member variable needs:

  1. Initialization in the constructor
  2. Documentation about thread safety and synchronization with _last_snapshot_id
  3. Validation logic to ensure no gaps with _last_snapshot_id

Comment on lines +275 to +277
int Node::get_log_size_diff_by_index(int index1, int index2) {
return _impl->get_log_size_diff_by_index(index1, index2);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add parameter validation and documentation.

The new method needs:

  1. Parameter validation for index1 and index2
  2. Documentation about:
    • Valid index ranges
    • Return value meaning
    • Error cases
  3. Error handling for invalid indices

Example documentation:

// Calculate the total size of log entries between index1 and index2 (inclusive).
// Returns:
//   >0: Total size in bytes
//   -1: If indices are invalid or out of range
//   -2: If index2 < index1
// Note: Both indices must be within the valid log range [first_log_index, last_log_index]

src/braft/node.h Outdated
Comment on lines 266 to 267
int get_log_size_diff_by_index(int index1, int index2);

Copy link

@coderabbitai coderabbitai bot Jan 26, 2025

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add method documentation.

Add documentation to describe:

  1. Method purpose
  2. Parameter constraints
  3. Return value semantics
  4. Thread safety guarantees

Example:

// Calculate the total size of log entries between index1 and index2 (inclusive).
// Thread-safe.
// @param index1 Start index, must be >= first_log_index
// @param index2 End index, must be <= last_log_index and >= index1
// @return Total size in bytes if successful, negative value on error

Copy link
Collaborator

Choose a reason for hiding this comment

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

请跟进兔子 AI 的建议,添加注释

Copy link

Choose a reason for hiding this comment

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

@AlexStocks Here's the documented version of the method:

    // Calculate the total size of log entries between index1 and index2 (inclusive).
    // Thread-safe.
    // @param index1 Start index, must be >= first_log_index
    // @param index2 End index, must be <= last_log_index
    // @return Total size in bytes if successful, -1 on error (e.g. invalid indices)
    int get_log_size_diff_by_index(int index1, int index2);

✏️ Learnings added
Learnt from: AlexStocks
PR: arana-db/braft#10
File: src/braft/node.h:266-267
Timestamp: 2025-02-05T07:08:44.949Z
Learning: The method `get_log_size_diff_by_index` in NodeImpl class calculates total size of log entries between two indices (inclusive). It is thread-safe and returns -1 on error.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Comment on lines +820 to +821
int get_log_size_diff_by_index(int index1, int index2);

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Add comprehensive API documentation.

As this is a public API, add detailed documentation including:

  1. Method purpose and use cases
  2. Parameter requirements and valid ranges
  3. Return value semantics and error codes
  4. Thread safety guarantees
  5. Performance implications

Example:

// Calculate the total size of log entries between two indices.
// This method is useful for:
// - Estimating storage requirements
// - Managing log compaction
// - Monitoring log growth
//
// Thread-safe.
//
// @param index1 Start index of the range (inclusive)
// @param index2 End index of the range (inclusive)
//
// @return
//   >0: Total size in bytes of all log entries in the range
//   -1: If indices are invalid or out of range
//   -2: If index2 < index1
//
// @note Both indices must be within [first_log_index, last_log_index].
//       Large ranges may impact performance.

const int64_t last_log_index = _log_manager->last_log_index();

if (index1 < first_log_index) {
LOG(ERROR) << "node " << _group_id << ":" << _server_id
Copy link
Collaborator

Choose a reason for hiding this comment

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

这行的效果,冒号前面有一个空格,后面不需要空格么?

return -1;
}
if (index2 > last_log_index) {
LOG(ERROR) << "node " << _group_id << ":" << _server_id
Copy link
Collaborator

Choose a reason for hiding this comment

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

这行的效果,冒号前面有一个空格,后面不需要空格么?

Copy link
Author

Choose a reason for hiding this comment

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

ok, 我修改一下

@@ -2252,6 +2252,44 @@ void NodeImpl::on_learner_config_apply(LogEntry *entry) {
}
}

int NodeImpl::get_log_size_diff_by_index(int index1, int index2) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

感觉可以考虑再增加一个参数 step,因为计算两个 index 之间的日志量大小只需要一个粗略的估计,不需要很精确的计算,直接每 step 间隔用最前面的日志大小来代替这一段的平均大小,这样可以得到一个估计值。

Copy link
Author

Choose a reason for hiding this comment

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

了解

Copy link
Author

Choose a reason for hiding this comment

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

这样改动量比较大 暂时先以这一版合入吧 我后续跟进一下改成这个按step间日志估算的feature

@@ -2252,6 +2252,44 @@ void NodeImpl::on_learner_config_apply(LogEntry *entry) {
}
}

int NodeImpl::get_log_size_diff_by_index(int index1, int index2) {
Copy link
Collaborator

Choose a reason for hiding this comment

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

我看braft里的index都用int64t表示,这里要不统一一下

Copy link
Collaborator

Choose a reason for hiding this comment

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

我看braft里的index都用int64t表示,这里要不统一一下

看了下实现比较简单,其它地方问题不大,远哥的这个点比较关键,函数声明啥的都可以同步改一下。

Copy link
Author

Choose a reason for hiding this comment

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

了解

if (!entry) {
LOG(ERROR) << "node " << _group_id << ":" << _server_id
<< " failed to get log entry at index=" << i;
return -1;
Copy link
Collaborator

Choose a reason for hiding this comment

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

FATAL等级是不是可以直接异常退出?省个 return -1

Copy link
Author

@LHG41278 LHG41278 Feb 10, 2025

Choose a reason for hiding this comment

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

了解, 翻阅了一下braft的源码发现LOG(ERROR)不能直接退出, 所以需要保留 return -1

Copy link
Collaborator

Choose a reason for hiding this comment

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

这个不是 glog 吗 ? glog 我记得有 FATAL 等级吗?

@KKorpse KKorpse self-requested a review February 10, 2025 03:31
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e06b9cf and 25f901e.

📒 Files selected for processing (2)
  • src/braft/node.cpp (1 hunks)
  • src/braft/node.h (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/braft/node.h
🧰 Additional context used
🧠 Learnings (1)
src/braft/node.cpp (1)
Learnt from: AlexStocks
PR: arana-db/braft#10
File: src/braft/node.h:266-267
Timestamp: 2025-02-05T07:08:45.052Z
Learning: The method `get_log_size_diff_by_index` in NodeImpl class calculates total size of log entries between two indices (inclusive). It is thread-safe and returns -1 on error.

Comment on lines 2255 to 2297
// Calculate the total size of log entries between index1 and index2 (inclusive).
// Returns:
// >0: Total size in bytes
// -1: If indices are invalid or out of range
// -2: If index2 < index1
// Note: Both indices must be within the valid log range [first_log_index, last_log_index]
int NodeImpl::get_log_size_diff_by_index(int64_t index1, int64_t index2) {
if (index1 > index2) {
std::swap(index1, index2);
}

const int64_t first_log_index = _log_manager->first_log_index();
const int64_t last_log_index = _log_manager->last_log_index();

if (index1 < first_log_index) {
LOG(ERROR) << "node " << _group_id << " : " << _server_id
<< " index1=" << index1 << " is out of range, first_log_index="
<< first_log_index;
return -1;
}
if (index2 > last_log_index) {
LOG(ERROR) << "node " << _group_id << " : " << _server_id
<< " index2=" << index2 << " is out of range, last_log_index="
<< last_log_index;
return -1;
}

int total_size = 0;
for (int64_t i = index1; i <= index2; ++i) {
LogEntry* entry = _log_manager->get_entry(i);
if (!entry) {
LOG(ERROR) << "node " << _group_id << " : " << _server_id
<< " failed to get log entry at index=" << i;
return -1;
}
LOG(INFO) << "node entry index " << i << " : size " << entry->data.length();

total_size += entry->data.length();
entry->Release();
}

return total_size;
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Fix potential memory leak and integer overflow issues.

The implementation has the following issues:

  1. Memory leak: If get_entry succeeds but data.length() causes integer overflow, entry->Release() is not called.
  2. Integer overflow: No protection against overflow when accumulating total_size.
  3. Logging: Error logs could be more descriptive.

Apply this diff to fix the issues:

 int NodeImpl::get_log_size_diff_by_index(int64_t index1, int64_t index2) {
     if (index1 > index2) {
         std::swap(index1, index2);
     }

     const int64_t first_log_index = _log_manager->first_log_index();
     const int64_t last_log_index = _log_manager->last_log_index();

     if (index1 < first_log_index) {
         LOG(ERROR) << "node " << _group_id << ":" << _server_id
                    << " index1=" << index1 << " is out of range, first_log_index=" 
                    << first_log_index;
         return -1;
     }
     if (index2 > last_log_index) {
         LOG(ERROR) << "node " << _group_id << ":" << _server_id
                    << " index2=" << index2 << " is out of range, last_log_index=" 
                    << last_log_index;
         return -1;
     }

     int64_t total_size = 0;
     for (int64_t i = index1; i <= index2; ++i) {
         LogEntry* entry = _log_manager->get_entry(i);
         if (!entry) {
             LOG(ERROR) << "node " << _group_id << ":" << _server_id
                        << " failed to get log entry at index=" << i;
             return -1;
         }
+        const int64_t entry_size = entry->data.length();
+        if (entry_size > std::numeric_limits<int>::max() - total_size) {
+            LOG(ERROR) << "node " << _group_id << ":" << _server_id
+                       << " integer overflow when calculating total size at index=" << i
+                       << ", current total_size=" << total_size
+                       << ", entry_size=" << entry_size;
+            entry->Release();
+            return -1;
+        }
-        LOG(INFO) << "node entry index " << i << " : size " << entry->data.length();
+        LOG(INFO) << "node " << _group_id << ":" << _server_id
+                  << " entry index=" << i << " size=" << entry_size;

-        total_size += entry->data.length();
+        total_size += entry_size;
         entry->Release();
     }

     return total_size;
 }
📝 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
// Calculate the total size of log entries between index1 and index2 (inclusive).
// Returns:
// >0: Total size in bytes
// -1: If indices are invalid or out of range
// -2: If index2 < index1
// Note: Both indices must be within the valid log range [first_log_index, last_log_index]
int NodeImpl::get_log_size_diff_by_index(int64_t index1, int64_t index2) {
if (index1 > index2) {
std::swap(index1, index2);
}
const int64_t first_log_index = _log_manager->first_log_index();
const int64_t last_log_index = _log_manager->last_log_index();
if (index1 < first_log_index) {
LOG(ERROR) << "node " << _group_id << " : " << _server_id
<< " index1=" << index1 << " is out of range, first_log_index="
<< first_log_index;
return -1;
}
if (index2 > last_log_index) {
LOG(ERROR) << "node " << _group_id << " : " << _server_id
<< " index2=" << index2 << " is out of range, last_log_index="
<< last_log_index;
return -1;
}
int total_size = 0;
for (int64_t i = index1; i <= index2; ++i) {
LogEntry* entry = _log_manager->get_entry(i);
if (!entry) {
LOG(ERROR) << "node " << _group_id << " : " << _server_id
<< " failed to get log entry at index=" << i;
return -1;
}
LOG(INFO) << "node entry index " << i << " : size " << entry->data.length();
total_size += entry->data.length();
entry->Release();
}
return total_size;
}
// Calculate the total size of log entries between index1 and index2 (inclusive).
// Returns:
// >0: Total size in bytes
// -1: If indices are invalid or out of range
// -2: If index2 < index1
// Note: Both indices must be within the valid log range [first_log_index, last_log_index]
int NodeImpl::get_log_size_diff_by_index(int64_t index1, int64_t index2) {
if (index1 > index2) {
std::swap(index1, index2);
}
const int64_t first_log_index = _log_manager->first_log_index();
const int64_t last_log_index = _log_manager->last_log_index();
if (index1 < first_log_index) {
LOG(ERROR) << "node " << _group_id << ":" << _server_id
<< " index1=" << index1 << " is out of range, first_log_index="
<< first_log_index;
return -1;
}
if (index2 > last_log_index) {
LOG(ERROR) << "node " << _group_id << ":" << _server_id
<< " index2=" << index2 << " is out of range, last_log_index="
<< last_log_index;
return -1;
}
int64_t total_size = 0;
for (int64_t i = index1; i <= index2; ++i) {
LogEntry* entry = _log_manager->get_entry(i);
if (!entry) {
LOG(ERROR) << "node " << _group_id << ":" << _server_id
<< " failed to get log entry at index=" << i;
return -1;
}
const int64_t entry_size = entry->data.length();
if (entry_size > std::numeric_limits<int>::max() - total_size) {
LOG(ERROR) << "node " << _group_id << ":" << _server_id
<< " integer overflow when calculating total size at index=" << i
<< ", current total_size=" << total_size
<< ", entry_size=" << entry_size;
entry->Release();
return -1;
}
LOG(INFO) << "node " << _group_id << ":" << _server_id
<< " entry index=" << i << " size=" << entry_size;
total_size += entry_size;
entry->Release();
}
return total_size;
}

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/braft/node.cpp (1)

2269-2271: Improve logging consistency and verbosity.

  1. The log format should be consistent with other logs in the file (using ":" between group_id and server_id).
  2. Logging entry sizes at INFO level for each entry could be noisy and impact performance.

Apply this diff to improve the logging:

-        LOG(ERROR) << "node " << _group_id << " : " << _server_id
+        LOG(ERROR) << "node " << _group_id << ":" << _server_id
                    << " index1=" << index1 << " is out of range, first_log_index=" 
                    << first_log_index;
-        LOG(ERROR) << "node " << _group_id << " : " << _server_id
+        LOG(ERROR) << "node " << _group_id << ":" << _server_id
                    << " index2=" << index2 << " is out of range, last_log_index=" 
                    << last_log_index;
-        LOG(ERROR) << "node " << _group_id << " : " << _server_id
+        LOG(ERROR) << "node " << _group_id << ":" << _server_id
                    << " failed to get log entry at index=" << i;
-        LOG(INFO) << "node entry index " << i << " : size " << entry->data.length();
+        BRAFT_VLOG << "node " << _group_id << ":" << _server_id
+                   << " entry index=" << i << " size=" << entry_size;

Also applies to: 2275-2277, 2285-2287, 2289-2289

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 25f901e and c672317.

📒 Files selected for processing (1)
  • src/braft/node.cpp (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
src/braft/node.cpp (1)
Learnt from: AlexStocks
PR: arana-db/braft#10
File: src/braft/node.h:266-267
Timestamp: 2025-02-05T07:08:45.052Z
Learning: The method `get_log_size_diff_by_index` in NodeImpl class calculates total size of log entries between two indices (inclusive). It is thread-safe and returns -1 on error.

Comment on lines +2255 to +2296
// Calculate the total size of log entries between index1 and index2 (inclusive).
// Returns:
// >0: Total size in bytes
// -1: If indices are invalid or out of range
// Note: Both indices must be within the valid log range [first_log_index, last_log_index]
int NodeImpl::get_log_size_diff_by_index(int64_t index1, int64_t index2) {
if (index1 > index2) {
std::swap(index1, index2);
}

const int64_t first_log_index = _log_manager->first_log_index();
const int64_t last_log_index = _log_manager->last_log_index();

if (index1 < first_log_index) {
LOG(ERROR) << "node " << _group_id << " : " << _server_id
<< " index1=" << index1 << " is out of range, first_log_index="
<< first_log_index;
return -1;
}
if (index2 > last_log_index) {
LOG(ERROR) << "node " << _group_id << " : " << _server_id
<< " index2=" << index2 << " is out of range, last_log_index="
<< last_log_index;
return -1;
}

int total_size = 0;
for (int64_t i = index1; i <= index2; ++i) {
LogEntry* entry = _log_manager->get_entry(i);
if (!entry) {
LOG(ERROR) << "node " << _group_id << " : " << _server_id
<< " failed to get log entry at index=" << i;
return -1;
}
LOG(INFO) << "node entry index " << i << " : size " << entry->data.length();

total_size += entry->data.length();
entry->Release();
}

return total_size;
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Add thread safety and fix integer overflow issues.

The implementation has several issues:

  1. Thread safety: The method accesses shared resources without proper synchronization.
  2. Integer overflow: No protection against overflow when accumulating total_size.
  3. Type consistency: Using int for total_size while braft uses int64_t for sizes.

Apply this diff to fix the issues:

-int NodeImpl::get_log_size_diff_by_index(int64_t index1, int64_t index2) {
+int64_t NodeImpl::get_log_size_diff_by_index(int64_t index1, int64_t index2) {
     if (index1 > index2) {
         std::swap(index1, index2);
     }
 
+    std::unique_lock<raft_mutex_t> lck(_mutex);
     const int64_t first_log_index = _log_manager->first_log_index();
     const int64_t last_log_index = _log_manager->last_log_index();
 
     if (index1 < first_log_index) {
         LOG(ERROR) << "node " << _group_id << " : " << _server_id
                    << " index1=" << index1 << " is out of range, first_log_index=" 
                    << first_log_index;
         return -1;
     }
     if (index2 > last_log_index) {
         LOG(ERROR) << "node " << _group_id << " : " << _server_id
                    << " index2=" << index2 << " is out of range, last_log_index=" 
                    << last_log_index;
         return -1;
     }
 
-    int total_size = 0;
+    int64_t total_size = 0;
     for (int64_t i = index1; i <= index2; ++i) {
         LogEntry* entry = _log_manager->get_entry(i);
         if (!entry) {
             LOG(ERROR) << "node " << _group_id << " : " << _server_id
                        << " failed to get log entry at index=" << i;
             return -1;
         }
+        const int64_t entry_size = entry->data.length();
+        if (entry_size > std::numeric_limits<int64_t>::max() - total_size) {
+            LOG(ERROR) << "node " << _group_id << " : " << _server_id
+                       << " integer overflow when calculating total size at index=" << i
+                       << ", current total_size=" << total_size
+                       << ", entry_size=" << entry_size;
+            entry->Release();
+            return -1;
+        }
         LOG(INFO) << "node entry index " << i << " : size " << entry->data.length();
 
-        total_size += entry->data.length();
+        total_size += entry_size;
         entry->Release();
     }
 
     return total_size;
 }
📝 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
// Calculate the total size of log entries between index1 and index2 (inclusive).
// Returns:
// >0: Total size in bytes
// -1: If indices are invalid or out of range
// Note: Both indices must be within the valid log range [first_log_index, last_log_index]
int NodeImpl::get_log_size_diff_by_index(int64_t index1, int64_t index2) {
if (index1 > index2) {
std::swap(index1, index2);
}
const int64_t first_log_index = _log_manager->first_log_index();
const int64_t last_log_index = _log_manager->last_log_index();
if (index1 < first_log_index) {
LOG(ERROR) << "node " << _group_id << " : " << _server_id
<< " index1=" << index1 << " is out of range, first_log_index="
<< first_log_index;
return -1;
}
if (index2 > last_log_index) {
LOG(ERROR) << "node " << _group_id << " : " << _server_id
<< " index2=" << index2 << " is out of range, last_log_index="
<< last_log_index;
return -1;
}
int total_size = 0;
for (int64_t i = index1; i <= index2; ++i) {
LogEntry* entry = _log_manager->get_entry(i);
if (!entry) {
LOG(ERROR) << "node " << _group_id << " : " << _server_id
<< " failed to get log entry at index=" << i;
return -1;
}
LOG(INFO) << "node entry index " << i << " : size " << entry->data.length();
total_size += entry->data.length();
entry->Release();
}
return total_size;
}
int64_t NodeImpl::get_log_size_diff_by_index(int64_t index1, int64_t index2) {
if (index1 > index2) {
std::swap(index1, index2);
}
std::unique_lock<raft_mutex_t> lck(_mutex);
const int64_t first_log_index = _log_manager->first_log_index();
const int64_t last_log_index = _log_manager->last_log_index();
if (index1 < first_log_index) {
LOG(ERROR) << "node " << _group_id << " : " << _server_id
<< " index1=" << index1 << " is out of range, first_log_index="
<< first_log_index;
return -1;
}
if (index2 > last_log_index) {
LOG(ERROR) << "node " << _group_id << " : " << _server_id
<< " index2=" << index2 << " is out of range, last_log_index="
<< last_log_index;
return -1;
}
int64_t total_size = 0;
for (int64_t i = index1; i <= index2; ++i) {
LogEntry* entry = _log_manager->get_entry(i);
if (!entry) {
LOG(ERROR) << "node " << _group_id << " : " << _server_id
<< " failed to get log entry at index=" << i;
return -1;
}
const int64_t entry_size = entry->data.length();
if (entry_size > std::numeric_limits<int64_t>::max() - total_size) {
LOG(ERROR) << "node " << _group_id << " : " << _server_id
<< " integer overflow when calculating total size at index=" << i
<< ", current total_size=" << total_size
<< ", entry_size=" << entry_size;
entry->Release();
return -1;
}
LOG(INFO) << "node entry index " << i << " : size " << entry->data.length();
total_size += entry_size;
entry->Release();
}
return total_size;
}

}
LOG(INFO) << "node entry index " << i << " : size " << entry->data.length();

total_size += entry->data.length();
Copy link
Collaborator

Choose a reason for hiding this comment

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

这个 length() 返回类型是什么?麻烦确认一下,total_size 最好与其保持一致

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants