refactor: extract QList move helper and ZSTD dict predicates#7755
Conversation
Route QList move construction and assignment through MoveFrom() so the shared state transfer lives in one place. Rename the ZSTD bulk-compression failure flag and helper entry point to better reflect their roles, and add IsZstdDictMode(), IsInterior(), and CanCompressWithZstdDict() to collapse repeated guard logic. No functional changes intended.
PR Summary by QodoRefactor QList move logic and ZSTD dict-mode guard helpers
AI Description
Diagram
High-Level Assessment
Files changed (2)
|
🤖 Augment PR SummarySummary: This PR refactors Changes:
Technical Notes: The ZSTD dict mode remains mutually exclusive with LZF depth-compression; the refactor aims to keep the same control flow while centralizing the conditions. 🤖 Was this summary useful? React with 👍 or 👎 |
| return *this; | ||
| } | ||
|
|
||
| void QList::MoveFrom(QList&& other) { |
There was a problem hiding this comment.
MoveFrom() copies most state, but it doesn’t transfer fields like malloc_size_ (used by MallocUsed(false) and ZSTD training thresholds) or per-list configuration like db_id_/zstd_threshold_, so a moved-to populated QList may end up with inconsistent accounting/config. Is it guaranteed that populated lists are never moved in a way that relies on these fields afterwards?
Severity: medium
🤖 Was this useful? React with 👍 or 👎, or 🚀 if it prevented an incident/outage.
Code Review by Qodo
1. Move drops QList state
|
| void QList::MoveFrom(QList&& other) { | ||
| head_ = other.head_; | ||
| len_ = other.len_; | ||
| count_ = other.count_; | ||
| fill_ = other.fill_; | ||
| dict_learning_failed_ = other.dict_learning_failed_; | ||
| dict_bulk_failed_ = other.dict_bulk_failed_; | ||
| dict_bulk_finished_ = other.dict_bulk_finished_; | ||
| tiering_enabled_ = other.tiering_enabled_; | ||
| compress_ = other.compress_; | ||
| bookmark_count_ = other.bookmark_count_; | ||
| tiering_params_ = std::move(other.tiering_params_); | ||
|
|
||
| other.head_ = nullptr; | ||
| other.len_ = other.count_ = 0; | ||
| } |
There was a problem hiding this comment.
1. Move drops qlist state 🐞 Bug ≡ Correctness
QList::MoveFrom transfers the node chain but does not move malloc_size_, zstd_threshold_, or db_id_, so moved-to lists lose memory accounting and ZSTD-dict enablement/configuration even though they still own nodes. This can under-report MallocUsed(false) and prevent ZSTD dict training/compression decisions that depend on malloc_size_ and zstd_threshold_.
Agent Prompt
## Issue description
`QList::MoveFrom(QList&&)` copies only a subset of member fields. After a move, the destination list owns the nodes but retains default values for `malloc_size_`, `zstd_threshold_`, and `db_id_`, which are used for memory accounting and ZSTD dict compression gating.
## Issue Context
- `MallocUsed(false)` returns `node_size + malloc_size_`, so `malloc_size_` must remain accurate after a move.
- ZSTD dict mode is enabled/gated via `set_compr_threshold()` (`zstd_threshold_`) and compares against `malloc_size_` in `CoolOff()` / `CompressAfterLoad()`.
- `db_id_` is set via `SetDbIndex()` and is part of QList's operational state (tiering path checks/materialization decisions depend on it).
## Fix Focus Areas
- src/core/qlist.cc[496-511]
- src/core/qlist.cc[661-675]
- src/core/qlist.h[272-276]
- src/core/qlist.h[386-402]
## Suggested fix
1. In `MoveFrom`, also transfer:
- `malloc_size_ = other.malloc_size_;`
- `zstd_threshold_ = other.zstd_threshold_;`
- `db_id_ = other.db_id_;`
2. Reset the moved-from fields to safe defaults (`other.malloc_size_ = 0; other.zstd_threshold_ = 0; other.db_id_ = kInvalidDbId;`) alongside the existing `head_/len_/count_` resets.
3. (Optional hardening) Mark `MoveFrom` as `noexcept` since it is used by `noexcept` move ctor/assignment.
ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools
|
@romange before you merge this plz double check bot's comment. I understand you just moved the code as it was but it's write we don't copy/omit some fields |
you are correct, the next PR fixes this, it was too confusing to do all the changes in the same commit. |
Summary
MoveFrom()path forQListmove construction and move assignmentChanges
src/core/qlist.ccto reuseMoveFrom()from the move constructor and assignment operatordict_compress_failed_todict_bulk_failed_andCompressWithZstdDict()toBackfillCompressWithZstdDict()IsZstdDictMode(),IsInterior(), andCanCompressWithZstdDict()insrc/core/qlist.hand use them in the ZSTD compression pathsTest plan