Skip to content

Fix underflow dirty size#401

Merged
liunyl merged 1 commit intomainfrom
dirty_size
Feb 12, 2026
Merged

Fix underflow dirty size#401
liunyl merged 1 commit intomainfrom
dirty_size

Conversation

@liunyl
Copy link
Contributor

@liunyl liunyl commented Feb 9, 2026

Here are some reminders before you submit the pull request

  • Add tests for the change
  • Document changes
  • Reference the link of issue using fixes eloqdb/tx_service#issue_id
  • Reference the link of RFC if exists
  • Pass ./mtr --suite=mono_main,mono_multi,mono_basic

Summary by CodeRabbit

  • Bug Fixes
    • Improved dirty-state detection so flush/commit notifications reflect an entry’s actual modified state.
    • Ensured template overwrite paths propagate prior dirty state when updating and committing entries.
    • Tightened synchronization during cache updates to maintain consistent shard statistics.
    • Added safeguards to prevent underflow in shard-level counters and keep counts non-negative.

@liunyl liunyl requested a review from MrGuin February 9, 2026 06:35
@coderabbitai
Copy link

coderabbitai bot commented Feb 9, 2026

Walkthrough

Replaces timestamp-based dirty checks with direct IsDirty() calls, wires prior-entry dirty state into flush/commit callbacks, and clamps counters to prevent underflow when adjusting data and dirty-key counts.

Changes

Cohort / File(s) Summary
Dirty-state condition replacement
tx_service/include/cc/object_cc_map.h
Replaced CommitTs() > 1 && !IsPersistent() logic with direct IsDirty() checks in standby-forward and buffered-commit code paths.
Post-update dirty sync
tx_service/include/cc/template_cc_map.h
When overwriting existing entries, capture prior IsDirty() and call OnFlushed(...) and OnCommittedUpdate(...) with that flag after payload updates.
Flush-time dirty propagation
tx_service/src/cc/cc_req_misc.cpp
Capture was_dirty = v_entry->IsDirty() before flush and pass the dynamic flag into OnEntryFlushed() across entry-type branches instead of hardcoding true.
Count underflow protection
tx_service/src/cc/cc_shard.cpp
Clamp computed sizes and dirty-count deltas to avoid negative results/underflow when adjusting data_key_count_ and dirty_data_key_count_.

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

Suggested reviewers

  • lokax

Poem

🐰 I sniffed the dirty flags today,
I swapped the timestamps right away,
I nudged the counts so none could fall,
I told the flush to heed them all —
Hooray, our cache is tidy! 🥕

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description is incomplete; it only contains a template checklist with all items unchecked, lacking actual substance about the changes, rationale, or issue references. Replace template checklist with concrete description of changes, the underflow issue being fixed, and add proper issue/RFC references and test/documentation status.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Fix underflow dirty size' directly reflects the main objective of the PR: fixing underflow issues in dirty size calculations as evidenced by the changes to AdjustDataKeyStats and other related code.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch dirty_size

No actionable comments were generated in the recent review. 🎉


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

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

🤖 Fix all issues with AI agents
In `@tx_service/src/cc/cc_shard.cpp`:
- Around line 406-421: The assert guarding the underflow case in the dirty count
path (assert(dirty_delta >= 0 || dirty_data_key_count_ >=
static_cast<size_t>(-dirty_delta))) must be relaxed because underflow can
legitimately occur when an entry is flushed but was never counted dirty (see
OnCommittedUpdate flows); replace the assert with a runtime check that logs a
warning via the appropriate logger (mentioning dirty_data_key_count_ and
dirty_delta) instead of aborting in debug builds, then continue with the
existing clamp logic that computes new_dirty and sets dirty_data_key_count_
accordingly.

Comment on lines +406 to +421
// Sanity check in debug mode.
assert(dirty_delta >= 0 ||
dirty_data_key_count_ >= static_cast<size_t>(-dirty_delta));
dirty_data_key_count_ = static_cast<size_t>(
static_cast<int64_t>(dirty_data_key_count_) + dirty_delta);
// Clamp to avoid underflow when an entry is flushed but was never
// counted dirty (e.g. became dirty via a path that doesn't call
// OnCommittedUpdate).
int64_t new_dirty =
static_cast<int64_t>(dirty_data_key_count_) + dirty_delta;
if (new_dirty < 0)
{
dirty_data_key_count_ = 0;
}
else
{
dirty_data_key_count_ = static_cast<size_t>(new_dirty);
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Avoid debug-only aborts if underflow is now a tolerated path.

You clamp dirty_data_key_count_ to zero, but the existing assert will still fire in debug/test runs when the “flushed but never counted dirty” scenario happens. If this is now expected, consider downgrading the assert to a warning so debug builds don’t fail.

🔧 Proposed adjustment
-        // Sanity check in debug mode.
-        assert(dirty_delta >= 0 ||
-               dirty_data_key_count_ >= static_cast<size_t>(-dirty_delta));
+        if (dirty_delta < 0 &&
+            dirty_data_key_count_ < static_cast<size_t>(-dirty_delta))
+        {
+            DLOG(WARNING) << "dirty_data_key_count_ underflow; clamping to 0";
+        }
         // Clamp to avoid underflow when an entry is flushed but was never
         // counted dirty (e.g. became dirty via a path that doesn't call
         // OnCommittedUpdate).
         int64_t new_dirty =
             static_cast<int64_t>(dirty_data_key_count_) + dirty_delta;
📝 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
// Sanity check in debug mode.
assert(dirty_delta >= 0 ||
dirty_data_key_count_ >= static_cast<size_t>(-dirty_delta));
dirty_data_key_count_ = static_cast<size_t>(
static_cast<int64_t>(dirty_data_key_count_) + dirty_delta);
// Clamp to avoid underflow when an entry is flushed but was never
// counted dirty (e.g. became dirty via a path that doesn't call
// OnCommittedUpdate).
int64_t new_dirty =
static_cast<int64_t>(dirty_data_key_count_) + dirty_delta;
if (new_dirty < 0)
{
dirty_data_key_count_ = 0;
}
else
{
dirty_data_key_count_ = static_cast<size_t>(new_dirty);
}
// Clamp to avoid underflow when an entry is flushed but was never
// counted dirty (e.g. became dirty via a path that doesn't call
// OnCommittedUpdate).
if (dirty_delta < 0 &&
dirty_data_key_count_ < static_cast<size_t>(-dirty_delta))
{
DLOG(WARNING) << "dirty_data_key_count_ underflow; clamping to 0";
}
int64_t new_dirty =
static_cast<int64_t>(dirty_data_key_count_) + dirty_delta;
if (new_dirty < 0)
{
dirty_data_key_count_ = 0;
}
else
{
dirty_data_key_count_ = static_cast<size_t>(new_dirty);
}
🤖 Prompt for AI Agents
In `@tx_service/src/cc/cc_shard.cpp` around lines 406 - 421, The assert guarding
the underflow case in the dirty count path (assert(dirty_delta >= 0 ||
dirty_data_key_count_ >= static_cast<size_t>(-dirty_delta))) must be relaxed
because underflow can legitimately occur when an entry is flushed but was never
counted dirty (see OnCommittedUpdate flows); replace the assert with a runtime
check that logs a warning via the appropriate logger (mentioning
dirty_data_key_count_ and dirty_delta) instead of aborting in debug builds, then
continue with the existing clamp logic that computes new_dirty and sets
dirty_data_key_count_ accordingly.

@liunyl liunyl merged commit 77767f7 into main Feb 12, 2026
4 checks passed
@liunyl liunyl deleted the dirty_size branch February 12, 2026 03:38
@liunyl liunyl self-assigned this Feb 12, 2026
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.

2 participants