This is an automated email from the ASF dual-hosted git repository.

dataroaring pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git


The following commit(s) were added to refs/heads/master by this push:
     new b3c00561118 [fix](clone) fix calculate merge missing version (#35627)
b3c00561118 is described below

commit b3c00561118c1e025da0d93786b871feceeaa1e3
Author: yujun <[email protected]>
AuthorDate: Thu May 30 23:30:57 2024 +0800

    [fix](clone) fix calculate merge missing version (#35627)
    
    BUG: when calculate missing version, the snapshot need single versions.
    For example, if missing version 4 ~ 6, the missing version should be [4,
    4], [5, 5], [6, 6]. But pr #30128 merge missing versions, it will give
    [4, 6], then clone will be fail.
    
    FIX:  don't merge missing versions.
---
 be/src/cloud/cloud_tablet.cpp                      | 30 ++++++++
 be/src/cloud/cloud_tablet.h                        |  7 ++
 be/src/olap/base_tablet.cpp                        | 30 --------
 be/src/olap/base_tablet.h                          |  6 +-
 be/src/olap/tablet.cpp                             | 33 ++++++++
 be/src/olap/tablet.h                               |  7 ++
 .../clone_p0/test_clone_missing_version.groovy     | 88 ++++++++++++++++++++++
 7 files changed, 169 insertions(+), 32 deletions(-)

diff --git a/be/src/cloud/cloud_tablet.cpp b/be/src/cloud/cloud_tablet.cpp
index 3d9f31d78f6..3505a12a50d 100644
--- a/be/src/cloud/cloud_tablet.cpp
+++ b/be/src/cloud/cloud_tablet.cpp
@@ -627,6 +627,36 @@ Status CloudTablet::save_delete_bitmap(const 
TabletTxnInfo* txn_info, int64_t tx
     return Status::OK();
 }
 
+Versions CloudTablet::calc_missed_versions(int64_t spec_version, Versions 
existing_versions) const {
+    DCHECK(spec_version > 0) << "invalid spec_version: " << spec_version;
+
+    // sort the existing versions in ascending order
+    std::sort(existing_versions.begin(), existing_versions.end(),
+              [](const Version& a, const Version& b) {
+                  // simple because 2 versions are certainly not overlapping
+                  return a.first < b.first;
+              });
+
+    // From the first version(=0), find the missing version until spec_version
+    int64_t last_version = -1;
+    Versions missed_versions;
+    for (const Version& version : existing_versions) {
+        if (version.first > last_version + 1) {
+            // there is a hole between versions
+            missed_versions.emplace_back(last_version + 1, 
std::min(version.first, spec_version));
+        }
+        last_version = version.second;
+        if (last_version >= spec_version) {
+            break;
+        }
+    }
+    if (last_version < spec_version) {
+        // there is a hole between the last version and the specificed version.
+        missed_versions.emplace_back(last_version + 1, spec_version);
+    }
+    return missed_versions;
+}
+
 Status CloudTablet::calc_delete_bitmap_for_compaction(
         const std::vector<RowsetSharedPtr>& input_rowsets, const 
RowsetSharedPtr& output_rowset,
         const RowIdConversion& rowid_conversion, ReaderType compaction_type, 
int64_t merged_rows,
diff --git a/be/src/cloud/cloud_tablet.h b/be/src/cloud/cloud_tablet.h
index e0ab3519787..ca05759cdbf 100644
--- a/be/src/cloud/cloud_tablet.h
+++ b/be/src/cloud/cloud_tablet.h
@@ -189,6 +189,13 @@ public:
                                              DeleteBitmapPtr& 
output_rowset_delete_bitmap,
                                              bool 
allow_delete_in_cumu_compaction);
 
+    // Find the missed versions until the spec_version.
+    //
+    // for example:
+    //     [0-4][5-5][8-8][9-9][14-14]
+    // if spec_version = 12, it will return [6-7],[10-12]
+    Versions calc_missed_versions(int64_t spec_version, Versions 
existing_versions) const override;
+
     std::mutex& get_rowset_update_lock() { return _rowset_update_lock; }
 
     const auto& rowset_map() const { return _rs_version_map; }
diff --git a/be/src/olap/base_tablet.cpp b/be/src/olap/base_tablet.cpp
index 9494ce5fd94..12352058f8a 100644
--- a/be/src/olap/base_tablet.cpp
+++ b/be/src/olap/base_tablet.cpp
@@ -340,36 +340,6 @@ Versions BaseTablet::get_missed_versions_unlocked(int64_t 
spec_version) const {
     return calc_missed_versions(spec_version, std::move(existing_versions));
 }
 
-Versions BaseTablet::calc_missed_versions(int64_t spec_version, Versions 
existing_versions) {
-    DCHECK(spec_version > 0) << "invalid spec_version: " << spec_version;
-
-    // sort the existing versions in ascending order
-    std::sort(existing_versions.begin(), existing_versions.end(),
-              [](const Version& a, const Version& b) {
-                  // simple because 2 versions are certainly not overlapping
-                  return a.first < b.first;
-              });
-
-    // From the first version(=0), find the missing version until spec_version
-    int64_t last_version = -1;
-    Versions missed_versions;
-    for (const Version& version : existing_versions) {
-        if (version.first > last_version + 1) {
-            // there is a hole between versions
-            missed_versions.emplace_back(last_version + 1, 
std::min(version.first, spec_version));
-        }
-        last_version = version.second;
-        if (last_version >= spec_version) {
-            break;
-        }
-    }
-    if (last_version < spec_version) {
-        // there is a hole between the last version and the specificed version.
-        missed_versions.emplace_back(last_version + 1, spec_version);
-    }
-    return missed_versions;
-}
-
 void BaseTablet::_print_missed_versions(const Versions& missed_versions) const 
{
     std::stringstream ss;
     ss << tablet_id() << " has " << missed_versions.size() << " missed 
version:";
diff --git a/be/src/olap/base_tablet.h b/be/src/olap/base_tablet.h
index 10ef2f52db8..7043df6a25a 100644
--- a/be/src/olap/base_tablet.h
+++ b/be/src/olap/base_tablet.h
@@ -254,8 +254,10 @@ protected:
     //
     // for example:
     //     [0-4][5-5][8-8][9-9][14-14]
-    // if spec_version = 12, it will return [6-7],[10-12]
-    static Versions calc_missed_versions(int64_t spec_version, Versions 
existing_versions);
+    // for cloud, if spec_version = 12, it will return [6-7],[10-12]
+    // for local, if spec_version = 12, it will return [6, 6], [7, 7], [10, 
10], [11, 11], [12, 12]
+    virtual Versions calc_missed_versions(int64_t spec_version,
+                                          Versions existing_versions) const = 
0;
 
     void _print_missed_versions(const Versions& missed_versions) const;
     bool _reconstruct_version_tracker_if_necessary();
diff --git a/be/src/olap/tablet.cpp b/be/src/olap/tablet.cpp
index ec4b6a26013..d8b1021302f 100644
--- a/be/src/olap/tablet.cpp
+++ b/be/src/olap/tablet.cpp
@@ -909,6 +909,39 @@ Status Tablet::capture_rs_readers(const Version& 
spec_version, std::vector<RowSe
     return Status::OK();
 }
 
+Versions Tablet::calc_missed_versions(int64_t spec_version, Versions 
existing_versions) const {
+    DCHECK(spec_version > 0) << "invalid spec_version: " << spec_version;
+
+    // sort the existing versions in ascending order
+    std::sort(existing_versions.begin(), existing_versions.end(),
+              [](const Version& a, const Version& b) {
+                  // simple because 2 versions are certainly not overlapping
+                  return a.first < b.first;
+              });
+
+    // From the first version(=0),  find the missing version until spec_version
+    int64_t last_version = -1;
+    Versions missed_versions;
+    for (const Version& version : existing_versions) {
+        if (version.first > last_version + 1) {
+            for (int64_t i = last_version + 1; i < version.first && i <= 
spec_version; ++i) {
+                // Don't merge missed_versions because clone & snapshot use 
single version.
+                // For example, if miss 4 ~ 6, clone need [4, 4], [5, 5], [6, 
6], but not [4, 6].
+                missed_versions.emplace_back(i, i);
+            }
+        }
+        last_version = version.second;
+        if (last_version >= spec_version) {
+            break;
+        }
+    }
+    for (int64_t i = last_version + 1; i <= spec_version; ++i) {
+        missed_versions.emplace_back(i, i);
+    }
+
+    return missed_versions;
+}
+
 bool Tablet::can_do_compaction(size_t path_hash, CompactionType 
compaction_type) {
     if (compaction_type == CompactionType::BASE_COMPACTION && tablet_state() 
!= TABLET_RUNNING) {
         // base compaction can only be done for tablet in TABLET_RUNNING state.
diff --git a/be/src/olap/tablet.h b/be/src/olap/tablet.h
index 8735b07653c..3fe48c32349 100644
--- a/be/src/olap/tablet.h
+++ b/be/src/olap/tablet.h
@@ -190,6 +190,13 @@ public:
     Status capture_rs_readers(const Version& spec_version, 
std::vector<RowSetSplits>* rs_splits,
                               bool skip_missing_version) override;
 
+    // Find the missed versions until the spec_version.
+    //
+    // for example:
+    //     [0-4][5-5][8-8][9-9][14-14]
+    // if spec_version = 12, it will return [6, 6], [7, 7], [10, 10], [11, 
11], [12, 12]
+    Versions calc_missed_versions(int64_t spec_version, Versions 
existing_versions) const override;
+
     // meta lock
     std::shared_mutex& get_header_lock() { return _meta_lock; }
     std::mutex& get_rowset_update_lock() { return _rowset_update_lock; }
diff --git a/regression-test/suites/clone_p0/test_clone_missing_version.groovy 
b/regression-test/suites/clone_p0/test_clone_missing_version.groovy
new file mode 100644
index 00000000000..144d45bc5f9
--- /dev/null
+++ b/regression-test/suites/clone_p0/test_clone_missing_version.groovy
@@ -0,0 +1,88 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+import org.apache.doris.regression.suite.ClusterOptions
+import org.apache.doris.regression.util.NodeType
+
+suite('test_clone_missing_version') {
+    def options = new ClusterOptions()
+    options.feConfigs += [
+        'disable_tablet_scheduler=true',
+        'tablet_checker_interval_ms=500',
+        'schedule_batch_size=1000',
+        'schedule_slot_num_per_hdd_path=1000',
+    ]
+    options.beConfigs += [
+        'disable_auto_compaction=true',
+        'report_tablet_interval_seconds=1',
+    ]
+
+    options.enableDebugPoints()
+    options.cloudMode = false
+    docker(options) {
+        def injectName = 'TxnManager.prepare_txn.random_failed'
+        def be = sql_return_maparray('show backends').get(0)
+        def addInject = { ->
+            GetDebugPoint().enableDebugPoint(be.Host, be.HttpPort as int, 
NodeType.BE, injectName, [percent:1.0])
+        }
+        def deleteInject = { ->
+            GetDebugPoint().disableDebugPoint(be.Host, be.HttpPort as int, 
NodeType.BE, injectName)
+        }
+
+        sql 'CREATE TABLE t (k INT) DISTRIBUTED BY HASH(k) BUCKETS 1'
+
+        sql 'INSERT INTO t VALUES(2)'
+
+        addInject()
+
+        sql 'INSERT INTO t VALUES(3)'
+        sql 'INSERT INTO t VALUES(4)'
+        sql 'INSERT INTO t VALUES(5)'
+
+        deleteInject()
+
+        sql 'INSERT INTO t VALUES(6)'
+
+        addInject()
+
+        sql 'INSERT INTO t VALUES(7)'
+        sql 'INSERT INTO t VALUES(8)'
+        sql 'INSERT INTO t VALUES(9)'
+
+        deleteInject()
+
+        sql 'INSERT INTO t VALUES(10)'
+
+        sleep 5000
+
+        def replica = sql_return_maparray('show tablets from t').find { 
it.BackendId.toLong().equals(be.BackendId.toLong()) }
+        assertNotNull(replica)
+        assertEquals(4, replica.VersionCount.toInteger())
+        assertEquals(2, replica.Version.toInteger())
+        assertEquals(9, replica.LstFailedVersion.toInteger())
+
+        setFeConfig('disable_tablet_scheduler', false)
+
+        sleep 10000
+
+        replica = sql_return_maparray('show tablets from t').find { 
it.BackendId.toLong().equals(be.BackendId.toLong()) }
+        assertNotNull(replica)
+        assertEquals(10, replica.VersionCount.toInteger())
+        assertEquals(10, replica.Version.toInteger())
+        assertEquals(-1, replica.LstFailedVersion.toInteger())
+    }
+}


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

Reply via email to