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

morningman 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 ffef81a6ab [feature](BE)pad missed version with empty rowset (#15030)
ffef81a6ab is described below

commit ffef81a6abaafcbb696f8d90905d0e70278cb8ba
Author: AlexYue <yj976240...@qq.com>
AuthorDate: Thu Dec 29 11:20:44 2022 +0800

    [feature](BE)pad missed version with empty rowset (#15030)
    
    If all replicas of one tablet are broken, user can use this http api to pad 
the missed version with empty rowset.
---
 be/src/http/CMakeLists.txt                         |   1 +
 be/src/http/action/pad_rowset_action.cpp           | 105 +++++++++++++++++++++
 be/src/http/action/pad_rowset_action.h             |  44 +++++++++
 be/src/service/http_service.cpp                    |   4 +
 be/test/olap/tablet_test.cpp                       |  55 +++++++++++
 .../docs/admin-manual/http-actions/pad-rowset.md   |  41 ++++++++
 docs/sidebars.json                                 |   1 +
 .../docs/admin-manual/http-actions/pad_rowset.md   |  43 +++++++++
 8 files changed, 294 insertions(+)

diff --git a/be/src/http/CMakeLists.txt b/be/src/http/CMakeLists.txt
index a73a15c9ef..a2e1c3eb46 100644
--- a/be/src/http/CMakeLists.txt
+++ b/be/src/http/CMakeLists.txt
@@ -35,6 +35,7 @@ add_library(Webserver STATIC
   http_client.cpp
   action/download_action.cpp
   action/monitor_action.cpp
+  action/pad_rowset_action.cpp
   action/health_action.cpp
   action/tablet_migration_action.cpp
   action/tablets_info_action.cpp
diff --git a/be/src/http/action/pad_rowset_action.cpp 
b/be/src/http/action/pad_rowset_action.cpp
new file mode 100644
index 0000000000..df2721f50b
--- /dev/null
+++ b/be/src/http/action/pad_rowset_action.cpp
@@ -0,0 +1,105 @@
+// 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.
+
+#include "http/action/pad_rowset_action.h"
+
+#include <memory>
+#include <mutex>
+
+#include "http/http_channel.h"
+#include "olap/olap_common.h"
+#include "olap/rowset/beta_rowset_writer.h"
+#include "olap/rowset/rowset.h"
+#include "olap/storage_engine.h"
+
+namespace doris {
+
+const std::string TABLET_ID = "tablet_id";
+const std::string START_VERSION = "start_version";
+const std::string END_VERSION = "end_version";
+
+Status check_one_param(const std::string& param_val, const std::string& 
param_name) {
+    if (param_val.empty()) {
+        return Status::InternalError("paramater {} not specified in url", 
param_name);
+    }
+    return Status::OK();
+}
+
+void PadRowsetAction::handle(HttpRequest* req) {
+    LOG(INFO) << "accept one request " << req->debug_string();
+    Status status = _handle(req);
+    std::string result = status.to_json();
+    LOG(INFO) << "handle request result:" << result;
+    if (status.ok()) {
+        HttpChannel::send_reply(req, HttpStatus::OK, result);
+    } else {
+        HttpChannel::send_reply(req, HttpStatus::INTERNAL_SERVER_ERROR, 
result);
+    }
+}
+
+Status PadRowsetAction::check_param(HttpRequest* req) {
+    RETURN_IF_ERROR(check_one_param(req->param(TABLET_ID), TABLET_ID));
+    RETURN_IF_ERROR(check_one_param(req->param(START_VERSION), START_VERSION));
+    RETURN_IF_ERROR(check_one_param(req->param(END_VERSION), END_VERSION));
+    return Status::OK();
+}
+
+Status PadRowsetAction::_handle(HttpRequest* req) {
+    RETURN_IF_ERROR(check_param(req));
+
+    const std::string& tablet_id_str = req->param(TABLET_ID);
+    const std::string& start_version_str = req->param(START_VERSION);
+    const std::string& end_version_str = req->param(END_VERSION);
+
+    // valid str format
+    int64_t tablet_id = std::atol(tablet_id_str.c_str());
+    int32_t start_version = std::atoi(start_version_str.c_str());
+    int32_t end_version = std::atoi(end_version_str.c_str());
+    if (start_version < 0 || end_version < 0 || end_version < start_version) {
+        return Status::InternalError("Invalid input version");
+    }
+
+    auto tablet = 
StorageEngine::instance()->tablet_manager()->get_tablet(tablet_id);
+    if (nullptr == tablet) {
+        return Status::InternalError("Unknown tablet id {}", tablet_id);
+    }
+    return _pad_rowset(tablet, Version(start_version, end_version));
+}
+
+Status PadRowsetAction::_pad_rowset(TabletSharedPtr tablet, const Version& 
version) {
+    if (tablet->check_version_exist(version)) {
+        return Status::InternalError("Input version {} exists", 
version.to_string());
+    }
+
+    std::unique_ptr<RowsetWriter> writer;
+    RETURN_IF_ERROR(tablet->create_rowset_writer(version, VISIBLE, 
NONOVERLAPPING,
+                                                 tablet->tablet_schema(), -1, 
-1, &writer));
+    auto rowset = writer->build();
+    rowset->make_visible(version);
+
+    std::vector<RowsetSharedPtr> to_add {rowset};
+    std::vector<RowsetSharedPtr> to_delete;
+    {
+        std::unique_lock wlock(tablet->get_header_lock());
+        tablet->modify_rowsets(to_add, to_delete);
+        tablet->save_meta();
+    }
+
+    return Status::OK();
+}
+
+} // namespace doris
diff --git a/be/src/http/action/pad_rowset_action.h 
b/be/src/http/action/pad_rowset_action.h
new file mode 100644
index 0000000000..f6036dc9fa
--- /dev/null
+++ b/be/src/http/action/pad_rowset_action.h
@@ -0,0 +1,44 @@
+// 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.
+
+#pragma once
+
+#include "common/status.h"
+#include "http/http_handler.h"
+#include "http/http_request.h"
+#include "olap/tablet.h"
+
+namespace doris {
+
+class PadRowsetAction : public HttpHandler {
+public:
+    PadRowsetAction() = default;
+
+    ~PadRowsetAction() override = default;
+
+    void handle(HttpRequest* req) override;
+
+private:
+    Status _handle(HttpRequest* req);
+    Status check_param(HttpRequest* req);
+
+#ifdef BE_TEST
+public:
+#endif
+    Status _pad_rowset(TabletSharedPtr tablet, const Version& version);
+};
+} // end namespace doris
\ No newline at end of file
diff --git a/be/src/service/http_service.cpp b/be/src/service/http_service.cpp
index b82299b827..b7acb1fa6a 100644
--- a/be/src/service/http_service.cpp
+++ b/be/src/service/http_service.cpp
@@ -27,6 +27,7 @@
 #include "http/action/jeprofile_actions.h"
 #include "http/action/meta_action.h"
 #include "http/action/metrics_action.h"
+#include "http/action/pad_rowset_action.h"
 #include "http/action/pprof_actions.h"
 #include "http/action/reload_tablet_action.h"
 #include "http/action/reset_rpc_channel_action.h"
@@ -184,6 +185,9 @@ Status HttpService::start() {
     _ev_http_server->register_handler(HttpMethod::POST, 
"/api/check_tablet_segment_lost",
                                       check_tablet_segment_action);
 
+    PadRowsetAction* pad_rowset_action = _pool.add(new PadRowsetAction());
+    _ev_http_server->register_handler(HttpMethod::POST, "api/pad_rowset", 
pad_rowset_action);
+
     _ev_http_server->start();
     return Status::OK();
 }
diff --git a/be/test/olap/tablet_test.cpp b/be/test/olap/tablet_test.cpp
index b1f949489f..db3ffb02df 100644
--- a/be/test/olap/tablet_test.cpp
+++ b/be/test/olap/tablet_test.cpp
@@ -21,6 +21,7 @@
 
 #include <sstream>
 
+#include "http/action/pad_rowset_action.h"
 #include "olap/olap_define.h"
 #include "olap/rowset/beta_rowset.h"
 #include "olap/storage_engine.h"
@@ -28,6 +29,7 @@
 #include "olap/tablet_meta.h"
 #include "olap/tablet_schema_cache.h"
 #include "testutil/mock_rowset.h"
+#include "util/file_utils.h"
 #include "util/time.h"
 
 using namespace std;
@@ -38,6 +40,8 @@ using namespace ErrorCode;
 using RowsetMetaSharedContainerPtr = 
std::shared_ptr<std::vector<RowsetMetaSharedPtr>>;
 
 static StorageEngine* k_engine = nullptr;
+static const std::string kTestDir = "/data_test/data/tablet_test";
+static const uint32_t MAX_PATH_LEN = 1024;
 
 class TestTablet : public testing::Test {
 public:
@@ -65,6 +69,17 @@ public:
             },
             "creation_time": 1553765670
         })";
+        char buffer[MAX_PATH_LEN];
+        EXPECT_NE(getcwd(buffer, MAX_PATH_LEN), nullptr);
+        absolute_dir = std::string(buffer) + kTestDir;
+
+        if (FileUtils::check_exist(absolute_dir)) {
+            EXPECT_TRUE(FileUtils::remove_all(absolute_dir).ok());
+        }
+        EXPECT_TRUE(FileUtils::create_dir(absolute_dir).ok());
+        EXPECT_TRUE(FileUtils::create_dir(absolute_dir + "/tablet_path").ok());
+        _data_dir = std::make_unique<DataDir>(absolute_dir);
+        _data_dir->update_capacity();
 
         doris::EngineOptions options;
         k_engine = new StorageEngine(options);
@@ -72,6 +87,9 @@ public:
     }
 
     void TearDown() override {
+        if (FileUtils::check_exist(absolute_dir)) {
+            EXPECT_TRUE(FileUtils::remove_all(absolute_dir).ok());
+        }
         if (k_engine != nullptr) {
             k_engine->stop();
             delete k_engine;
@@ -197,6 +215,8 @@ public:
 protected:
     std::string _json_rowset_meta;
     TabletMetaSharedPtr _tablet_meta;
+    string absolute_dir;
+    std::unique_ptr<DataDir> _data_dir;
 };
 
 TEST_F(TestTablet, delete_expired_stale_rowset) {
@@ -225,6 +245,41 @@ TEST_F(TestTablet, delete_expired_stale_rowset) {
     _tablet.reset();
 }
 
+TEST_F(TestTablet, pad_rowset) {
+    std::vector<RowsetMetaSharedPtr> rs_metas;
+    auto ptr1 = std::make_shared<RowsetMeta>();
+    init_rs_meta(ptr1, 1, 2);
+    rs_metas.push_back(ptr1);
+    RowsetSharedPtr rowset1 = make_shared<BetaRowset>(nullptr, "", ptr1);
+
+    auto ptr2 = std::make_shared<RowsetMeta>();
+    init_rs_meta(ptr2, 3, 4);
+    rs_metas.push_back(ptr2);
+    RowsetSharedPtr rowset2 = make_shared<BetaRowset>(nullptr, "", ptr2);
+
+    auto ptr3 = std::make_shared<RowsetMeta>();
+    init_rs_meta(ptr3, 6, 7);
+    rs_metas.push_back(ptr3);
+    RowsetSharedPtr rowset3 = make_shared<BetaRowset>(nullptr, "", ptr3);
+
+    for (auto& rowset : rs_metas) {
+        _tablet_meta->add_rs_meta(rowset);
+    }
+
+    _data_dir->init();
+    TabletSharedPtr _tablet(new Tablet(_tablet_meta, _data_dir.get()));
+    _tablet->init();
+
+    Version version(5, 5);
+    std::vector<RowsetReaderSharedPtr> readers;
+    ASSERT_FALSE(_tablet->capture_rs_readers(version, &readers).ok());
+    readers.clear();
+
+    PadRowsetAction action;
+    action._pad_rowset(_tablet, version);
+    ASSERT_TRUE(_tablet->capture_rs_readers(version, &readers).ok());
+}
+
 TEST_F(TestTablet, cooldown_policy) {
     std::vector<RowsetMetaSharedPtr> rs_metas;
     RowsetMetaSharedPtr ptr1(new RowsetMeta());
diff --git a/docs/en/docs/admin-manual/http-actions/pad-rowset.md 
b/docs/en/docs/admin-manual/http-actions/pad-rowset.md
new file mode 100644
index 0000000000..9ff6b89053
--- /dev/null
+++ b/docs/en/docs/admin-manual/http-actions/pad-rowset.md
@@ -0,0 +1,41 @@
+---
+{
+    "title": "PAD ROWSET",
+    "language": "en"
+}
+---
+
+<!-- 
+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.
+-->
+
+# PAD ROWSET
+## description
+   
+    Pad one empty rowset as one substitute for error replica.
+
+    METHOD: POST
+    URI: 
http://be_host:be_http_port/api/pad_rowset?tablet_id=xxx&start_version=xxx&end_version=xxx
+
+## example
+
+    curl -X POST 
"http://hostname:8088/api/pad_rowset?tablet_id=123456\&start_version=1111111\$end_version=1111112";
+
+## keyword
+
+    ROWSET,TABLET,ROWSET,TABLET
diff --git a/docs/sidebars.json b/docs/sidebars.json
index 2a4ef60cb0..3318bcbd69 100644
--- a/docs/sidebars.json
+++ b/docs/sidebars.json
@@ -1119,6 +1119,7 @@
                             ]
                         },
                         "admin-manual/http-actions/restore-tablet",
+                        "admin-manual/http-actions/pad-rowset",
                         "admin-manual/http-actions/get-load-state",
                         "admin-manual/http-actions/tablet-migration-action",
                         "admin-manual/http-actions/cancel-label",
diff --git a/docs/zh-CN/docs/admin-manual/http-actions/pad_rowset.md 
b/docs/zh-CN/docs/admin-manual/http-actions/pad_rowset.md
new file mode 100644
index 0000000000..dba241fca7
--- /dev/null
+++ b/docs/zh-CN/docs/admin-manual/http-actions/pad_rowset.md
@@ -0,0 +1,43 @@
+---
+{
+    "title": "PAD ROWSET",
+    "language": "zh-CN"
+}
+---
+
+<!-- 
+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.
+-->
+
+# PAD ROWSET
+## description
+   
+    该功能用于使用一个空的rowset填充损坏的副本。
+
+    说明:这个功能暂时只在be服务中提供一个http接口。如果要使用,
+    需要向要进行数据恢复的那台be机器的http端口发送pad rowset api请求。api格式如下:
+    METHOD: POST
+    URI: 
http://be_host:be_http_port/api/pad_rowset?tablet_id=xxx&start_version=xxx&end_version=xxx
+
+## example
+
+    curl -X POST 
"http://hostname:8088/api/pad_rowset?tablet_id=123456\&start_version=1111111\&end_version=1111112";
+
+## keyword
+
+    PAD,ROWSET,PAD,ROWSET


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@doris.apache.org
For additional commands, e-mail: commits-h...@doris.apache.org

Reply via email to