Copilot commented on code in PR #65915:
URL: https://github.com/apache/doris/pull/65915#discussion_r3629882438


##########
be/src/cloud/cloud_cumulative_compaction.cpp:
##########
@@ -47,6 +50,18 @@ 
CloudCumulativeCompaction::CloudCumulativeCompaction(CloudStorageEngine& engine,
 
 CloudCumulativeCompaction::~CloudCumulativeCompaction() = default;
 
+int64_t CloudCumulativeCompaction::_refresh_conflict_versions() {
+    std::vector<std::shared_ptr<CloudCumulativeCompaction>> cumu_compactions;
+    _engine.get_cumu_compaction(_tablet->tablet_id(), cumu_compactions);
+    for (const auto& cumu : cumu_compactions) {
+        _min_conflict_version =
+                std::min(_min_conflict_version, 
cumu->_input_rowsets.front()->start_version());
+        _max_conflict_version =
+                std::max(_max_conflict_version, 
cumu->_input_rowsets.back()->end_version());
+    }
+    return _max_conflict_version;
+}

Review Comment:
   `_refresh_conflict_versions()` accumulates into `_min_conflict_version` / 
`_max_conflict_version` without resetting them, so the conflict window can 
become permanently stale after in-flight compactions complete. This can cause 
`pick_rowsets_to_compact()` to keep avoiding version ranges that are no longer 
conflicting, potentially stalling cumulative compaction. Reset to defaults at 
the start of this method (e.g., min=INT64_MAX, max=0) and recompute from 
current in-flight compactions; if none exist, keep defaults.



##########
be/src/cloud/cloud_cumulative_compaction.cpp:
##########
@@ -47,6 +50,18 @@ 
CloudCumulativeCompaction::CloudCumulativeCompaction(CloudStorageEngine& engine,
 
 CloudCumulativeCompaction::~CloudCumulativeCompaction() = default;
 
+int64_t CloudCumulativeCompaction::_refresh_conflict_versions() {
+    std::vector<std::shared_ptr<CloudCumulativeCompaction>> cumu_compactions;
+    _engine.get_cumu_compaction(_tablet->tablet_id(), cumu_compactions);
+    for (const auto& cumu : cumu_compactions) {
+        _min_conflict_version =
+                std::min(_min_conflict_version, 
cumu->_input_rowsets.front()->start_version());
+        _max_conflict_version =
+                std::max(_max_conflict_version, 
cumu->_input_rowsets.back()->end_version());
+    }

Review Comment:
   This reads `cumu->_input_rowsets.front()/back()` without guarding against an 
empty `_input_rowsets` (or concurrent mutation). If an in-flight compaction is 
registered before its inputs are populated, this will crash. Consider storing 
immutable `input_start_version/input_end_version` on the compaction object when 
inputs are picked, and have `_refresh_conflict_versions()` use those; or at 
minimum, skip/guard empty `_input_rowsets` with a check to avoid dereferencing.



##########
be/src/cloud/cloud_cumulative_compaction_policy.cpp:
##########
@@ -35,6 +35,33 @@
 
 namespace doris {
 
+int64_t CloudCumulativeCompactionPolicy::calculate_cumulative_point(
+        CloudTablet* tablet, const std::vector<RowsetSharedPtr>& rowsets,
+        const RowsetSharedPtr& output_rowset, Version& last_delete_version,
+        int64_t input_cumulative_point) {
+    DORIS_CHECK(std::find(rowsets.begin(), rowsets.end(), output_rowset) != 
rowsets.end());

Review Comment:
   This membership check relies on `shared_ptr` identity (`operator==`) instead 
of semantic identity (rowset id / version range). If a caller passes an 
`output_rowset` instance that represents the same rowset but is not the same 
`shared_ptr` object as the one stored in `rowsets`, this will abort even though 
the input is logically valid. Prefer matching by a stable identifier (e.g., 
rowset id) or by version range, and avoid fatal checks here (return 
`input_cumulative_point` or DCHECK) since this is used on a production path.



##########
be/src/cloud/cloud_cumulative_compaction.cpp:
##########
@@ -244,12 +252,56 @@ Status CloudCumulativeCompaction::execute_compact() {
 
 Status CloudCumulativeCompaction::modify_rowsets() {
     // calculate new cumulative point
-    int64_t input_cumulative_point = cloud_tablet()->cumulative_layer_point();
-    auto compaction_policy = 
cloud_tablet()->tablet_meta()->compaction_policy();
-    int64_t new_cumulative_point =
-            _engine.cumu_compaction_policy(compaction_policy)
-                    ->new_cumulative_point(cloud_tablet(), _output_rowset, 
_last_delete_version,
-                                           input_cumulative_point);
+    int64_t prepare_max_conflict_version = _max_conflict_version;
+    int64_t max_conflict_version = _refresh_conflict_versions();
+    int64_t input_cumulative_point;
+    bool output_already_passed;
+    std::vector<RowsetSharedPtr> rowsets;
+    {
+        std::shared_lock rlock(_tablet->get_header_lock());
+        input_cumulative_point = cloud_tablet()->cumulative_layer_point();
+        DORIS_CHECK(input_cumulative_point <= _output_rowset->start_version() 
||
+                    input_cumulative_point > _output_rowset->end_version());
+        output_already_passed = input_cumulative_point > 
_output_rowset->end_version();

Review Comment:
   This `DORIS_CHECK` can abort if the cumulative point advances into the 
output rowset’s version range between compaction prepare and modify (a 
plausible race under parallel compaction). Instead of fatal-checking, treat 
this as an expected concurrency outcome: either set `output_already_passed` (or 
return without advancing), or return a non-OK `Status` that causes the 
compaction to retry/resync.



##########
be/src/cloud/cloud_cumulative_compaction_policy.cpp:
##########
@@ -35,6 +35,33 @@
 
 namespace doris {
 
+int64_t CloudCumulativeCompactionPolicy::calculate_cumulative_point(
+        CloudTablet* tablet, const std::vector<RowsetSharedPtr>& rowsets,
+        const RowsetSharedPtr& output_rowset, Version& last_delete_version,
+        int64_t input_cumulative_point) {
+    DORIS_CHECK(std::find(rowsets.begin(), rowsets.end(), output_rowset) != 
rowsets.end());
+    int64_t cumulative_point = input_cumulative_point;
+    Version no_delete_version {-1, -1};
+    for (const auto& rowset : rowsets) {
+        DORIS_CHECK_EQ(rowset->start_version(), cumulative_point);
+        if (rowset->rowset_meta()->has_delete_predicate()) {
+            cumulative_point = rowset->end_version() + 1;
+            continue;
+        }

Review Comment:
   `DORIS_CHECK_EQ(rowset->start_version(), cumulative_point)` will hard-abort 
the process if there is a version gap or if the provided rowset list isn't 
perfectly continuous (which can happen due to concurrent tablet changes between 
traversal and evaluation, or due to legitimate version holes). Since the goal 
is to conservatively advance the cumulative point, consider handling 
non-continuity by returning the current `cumulative_point` (or downgrading to 
`DCHECK`/logging) instead of crashing.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to