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

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


The following commit(s) were added to refs/heads/branch-3.0 by this push:
     new bb09971965c branch-3.0: [enhancement](cloud) Prohibit changing 
deployment mode #40764 (#43891)
bb09971965c is described below

commit bb09971965c03161b06295f5d1d11b8c9302c7c5
Author: github-actions[bot] 
<41898282+github-actions[bot]@users.noreply.github.com>
AuthorDate: Thu Nov 14 14:01:51 2024 +0800

    branch-3.0: [enhancement](cloud) Prohibit changing deployment mode #40764 
(#43891)
    
    Cherry-picked from #40764
    
    Co-authored-by: yagagagaga <[email protected]>
    Co-authored-by: yagagagaga <[email protected]>
---
 be/src/olap/olap_define.h                          |  1 +
 be/src/runtime/exec_env.h                          |  1 +
 be/src/runtime/exec_env_init.cpp                   | 45 ++++++++++++++++++++++
 .../src/main/java/org/apache/doris/DorisFE.java    |  4 +-
 .../main/java/org/apache/doris/catalog/Env.java    | 31 +++++++++++++++
 .../java/org/apache/doris/persist/Storage.java     | 31 +++++++++++++++
 .../apache/doris/service/FrontendServiceImpl.java  | 13 +++++++
 .../java/org/apache/doris/system/HeartbeatMgr.java |  1 +
 gensrc/thrift/FrontendService.thrift               |  1 +
 9 files changed, 127 insertions(+), 1 deletion(-)

diff --git a/be/src/olap/olap_define.h b/be/src/olap/olap_define.h
index 0e6d0155d60..5131c51ca01 100644
--- a/be/src/olap/olap_define.h
+++ b/be/src/olap/olap_define.h
@@ -87,6 +87,7 @@ enum OLAPDataVersion {
 // Different types of folder names under storage_root_path
 static const std::string MINI_PREFIX = "mini_download";
 static const std::string CLUSTER_ID_PREFIX = "cluster_id";
+static const std::string DEPLOY_MODE_PREFIX = "deploy_mode";
 static const std::string DATA_PREFIX = "data";
 static const std::string DPP_PREFIX = "dpp_download";
 static const std::string SNAPSHOT_PREFIX = "snapshot";
diff --git a/be/src/runtime/exec_env.h b/be/src/runtime/exec_env.h
index 4a0000fa19f..031595a9c41 100644
--- a/be/src/runtime/exec_env.h
+++ b/be/src/runtime/exec_env.h
@@ -344,6 +344,7 @@ private:
     void _destroy();
 
     Status _init_mem_env();
+    Status _check_deploy_mode();
 
     void _register_metrics();
     void _deregister_metrics();
diff --git a/be/src/runtime/exec_env_init.cpp b/be/src/runtime/exec_env_init.cpp
index 9d761786611..51714c7deb2 100644
--- a/be/src/runtime/exec_env_init.cpp
+++ b/be/src/runtime/exec_env_init.cpp
@@ -346,6 +346,8 @@ Status ExecEnv::_init(const std::vector<StorePath>& 
store_paths,
     options.store_paths = store_paths;
     options.broken_paths = broken_paths;
     options.backend_uid = doris::UniqueId::gen_uid();
+    // Check if the startup mode has been modified
+    RETURN_IF_ERROR(_check_deploy_mode());
     if (config::is_cloud_mode()) {
         std::cout << "start BE in cloud mode, cloud_unique_id: " << 
config::cloud_unique_id
                   << ", meta_service_endpoint: " << 
config::meta_service_endpoint << std::endl;
@@ -622,6 +624,49 @@ void ExecEnv::init_mem_tracker() {
             MemTrackerLimiter::create_shared(MemTrackerLimiter::Type::LOAD, 
"StreamLoadPipe");
 }
 
+Status ExecEnv::_check_deploy_mode() {
+    for (auto _path : _store_paths) {
+        auto deploy_mode_path = fmt::format("{}/{}", _path.path, 
DEPLOY_MODE_PREFIX);
+        std::string expected_mode = doris::config::is_cloud_mode() ? "cloud" : 
"local";
+        bool exists = false;
+        
RETURN_IF_ERROR(io::global_local_filesystem()->exists(deploy_mode_path, 
&exists));
+        if (exists) {
+            // check if is ok
+            io::FileReaderSPtr reader;
+            
RETURN_IF_ERROR(io::global_local_filesystem()->open_file(deploy_mode_path, 
&reader));
+            size_t fsize = reader->size();
+            if (fsize > 0) {
+                std::string actual_mode;
+                actual_mode.resize(fsize, '\0');
+                size_t bytes_read = 0;
+                RETURN_IF_ERROR(reader->read_at(0, {actual_mode.data(), 
fsize}, &bytes_read));
+                DCHECK_EQ(fsize, bytes_read);
+                if (expected_mode != actual_mode) {
+                    return Status::InternalError(
+                            "You can't switch deploy mode from {} to {}, "
+                            "maybe you need to check be.conf\n",
+                            actual_mode.c_str(), expected_mode.c_str());
+                }
+                LOG(INFO) << "The current deployment mode is " << 
expected_mode << ".";
+            }
+        } else {
+            io::FileWriterPtr file_writer;
+            RETURN_IF_ERROR(
+                    
io::global_local_filesystem()->create_file(deploy_mode_path, &file_writer));
+            RETURN_IF_ERROR(file_writer->append(expected_mode));
+            RETURN_IF_ERROR(file_writer->close());
+            LOG(INFO) << "The file deploy_mode doesn't exist, create it.";
+            auto cluster_id_path = fmt::format("{}/{}", _path.path, 
CLUSTER_ID_PREFIX);
+            
RETURN_IF_ERROR(io::global_local_filesystem()->exists(cluster_id_path, 
&exists));
+            if (exists) {
+                LOG(WARNING) << "This may be an upgrade from old version,"
+                             << "or the deploy_mode file has been manually 
deleted";
+            }
+        }
+    }
+    return Status::OK();
+}
+
 void ExecEnv::_register_metrics() {
     REGISTER_HOOK_METRIC(send_batch_thread_pool_thread_num,
                          [this]() { return 
_send_batch_thread_pool->num_threads(); });
diff --git a/fe/fe-core/src/main/java/org/apache/doris/DorisFE.java 
b/fe/fe-core/src/main/java/org/apache/doris/DorisFE.java
index d028f3aeae1..d5b7cd7354e 100755
--- a/fe/fe-core/src/main/java/org/apache/doris/DorisFE.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/DorisFE.java
@@ -231,7 +231,9 @@ public class DorisFE {
             // Some exception may thrown before LOG is inited.
             // So need to print to stdout
             e.printStackTrace();
-            LOG.warn("", e);
+            LOG.error("", e);
+            // to avoid nonDaemon Thread block main Thread, we need to force 
exit
+            System.exit(-1);
         }
     }
 
diff --git a/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java 
b/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java
index 3fd20bc6a8d..e4272472587 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/catalog/Env.java
@@ -1081,6 +1081,7 @@ public class Env {
 
         // 2. get cluster id and role (Observer or Follower)
         if (!Config.enable_check_compatibility_mode) {
+            checkDeployMode();
             getClusterIdAndRole();
         } else {
             isElectable = true;
@@ -1370,6 +1371,31 @@ public class Env {
                 clusterId, isElectable, role.name(), nodeName);
     }
 
+    /**
+     * write cloud/local to MODE_FILE.
+     */
+    protected void checkDeployMode() throws IOException {
+        File modeFile = new File(this.imageDir, Storage.DEPLOY_MODE_FILE);
+        Storage storage = new Storage(this.imageDir);
+        String expectedMode = getDeployMode();
+        if (modeFile.exists()) {
+            String actualMode = storage.getDeployMode();
+            Preconditions.checkArgument(expectedMode.equals(actualMode),
+                    "You can't switch deploy mode from %s to %s, maybe you 
need to check fe.conf",
+                    actualMode, expectedMode);
+            LOG.info("The current deployment mode is " + expectedMode + ".");
+        } else {
+            storage.setDeployMode(expectedMode);
+            storage.writeClusterMode();
+            LOG.info("The file DEPLOY_MODE doesn't exist, create it.");
+            File versionFile = new File(this.imageDir, Storage.VERSION_FILE);
+            if (versionFile.exists()) {
+                LOG.warn("This may be an upgrade from old version, "
+                        + "or the DEPLOY_MODE file has been manually deleted");
+            }
+        }
+    }
+
     public static String genFeNodeName(String host, int port, boolean 
isOldStyle) {
         if (isOldStyle) {
             return host + "_" + port;
@@ -4201,6 +4227,10 @@ public class Env {
         return this.clusterId;
     }
 
+    public String getDeployMode() {
+        return Config.isCloudMode() ? Storage.CLOUD_MODE : Storage.LOCAL_MODE;
+    }
+
     public String getToken() {
         return token;
     }
@@ -6708,3 +6738,4 @@ public class Env {
         System.exit(0);
     }
 }
+
diff --git a/fe/fe-core/src/main/java/org/apache/doris/persist/Storage.java 
b/fe/fe-core/src/main/java/org/apache/doris/persist/Storage.java
index 910a42ab761..9f8cd558a57 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/persist/Storage.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/persist/Storage.java
@@ -55,11 +55,16 @@ public class Storage {
     public static final String IMAGE_NEW = "image.ckpt";
     public static final String VERSION_FILE = "VERSION";
     public static final String ROLE_FILE = "ROLE";
+    public static final String DEPLOY_MODE_FILE = "DEPLOY_MODE";
+    public static final String DEPLOY_MODE = "deploy_mode";
+    public static final String CLOUD_MODE = "cloud";
+    public static final String LOCAL_MODE = "local";
 
     private int clusterID = 0;
     private String token;
     private FrontendNodeType role = FrontendNodeType.UNKNOWN;
     private String nodeName;
+    private String deployMode;
     private long editsSeq;
     private long latestImageSeq = 0;
     private long latestValidatedImageSeq = 0;
@@ -116,6 +121,14 @@ public class Storage {
             nodeName = prop.getProperty(NODE_NAME, null);
         }
 
+        File modeFile = getModeFile();
+        if (modeFile.isFile()) {
+            try (FileInputStream in = new FileInputStream(modeFile)) {
+                prop.load(in);
+            }
+            deployMode = prop.getProperty(DEPLOY_MODE);
+        }
+
         // Find the latest two images
         File dir = new File(metaDir);
         File[] children = dir.listFiles();
@@ -165,6 +178,14 @@ public class Storage {
         return role;
     }
 
+    public String getDeployMode() {
+        return deployMode;
+    }
+
+    public void setDeployMode(String deployMode) {
+        this.deployMode = deployMode;
+    }
+
     public String getNodeName() {
         return nodeName;
     }
@@ -224,6 +245,12 @@ public class Storage {
         writePropertiesToFile(properties, ROLE_FILE);
     }
 
+    public void writeClusterMode() throws IOException {
+        Properties properties = new Properties();
+        properties.setProperty(DEPLOY_MODE, deployMode);
+        writePropertiesToFile(properties, DEPLOY_MODE_FILE);
+    }
+
     private void writePropertiesToFile(Properties properties, String fileName) 
throws IOException {
         RandomAccessFile file = new RandomAccessFile(new File(metaDir, 
fileName), "rws");
         FileOutputStream out = null;
@@ -287,6 +314,10 @@ public class Storage {
         return new File(metaDir, ROLE_FILE);
     }
 
+    public final File getModeFile() {
+        return new File(metaDir, DEPLOY_MODE_FILE);
+    }
+
     public File getCurrentEditsFile() {
         return new File(metaDir, EDITS);
     }
diff --git 
a/fe/fe-core/src/main/java/org/apache/doris/service/FrontendServiceImpl.java 
b/fe/fe-core/src/main/java/org/apache/doris/service/FrontendServiceImpl.java
index 8b57732dadc..2e7980d80d4 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/service/FrontendServiceImpl.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/service/FrontendServiceImpl.java
@@ -2263,6 +2263,19 @@ public class FrontendServiceImpl implements 
FrontendService.Iface {
                 result.setMsg("invalid cluster id: " + 
Env.getCurrentEnv().getClusterId());
             }
 
+            if (result.getStatus() == TFrontendPingFrontendStatusCode.OK) {
+                // If the version of FE is too old, we need to ensure 
compatibility.
+                if (request.getDeployMode() == null) {
+                    LOG.warn("Couldn't find deployMode in heartbeat info, "
+                            + "maybe you need upgrade FE master.");
+                } else if 
(!request.getDeployMode().equals(Env.getCurrentEnv().getDeployMode())) {
+                    result.setStatus(TFrontendPingFrontendStatusCode.FAILED);
+                    result.setMsg("expected deployMode: "
+                            + request.getDeployMode()
+                            + ", but found deployMode: "
+                            + Env.getCurrentEnv().getDeployMode());
+                }
+            }
             if (result.getStatus() == TFrontendPingFrontendStatusCode.OK) {
                 if 
(!request.getToken().equals(Env.getCurrentEnv().getToken())) {
                     result.setStatus(TFrontendPingFrontendStatusCode.FAILED);
diff --git a/fe/fe-core/src/main/java/org/apache/doris/system/HeartbeatMgr.java 
b/fe/fe-core/src/main/java/org/apache/doris/system/HeartbeatMgr.java
index d7eff484c6a..f8e75633a0d 100644
--- a/fe/fe-core/src/main/java/org/apache/doris/system/HeartbeatMgr.java
+++ b/fe/fe-core/src/main/java/org/apache/doris/system/HeartbeatMgr.java
@@ -376,6 +376,7 @@ public class HeartbeatMgr extends MasterDaemon {
             try {
                 client = ClientPool.frontendHeartbeatPool.borrowObject(addr);
                 TFrontendPingFrontendRequest request = new 
TFrontendPingFrontendRequest(clusterId, token);
+                request.setDeployMode(Env.getCurrentEnv().getDeployMode());
                 TFrontendPingFrontendResult result = client.ping(request);
                 ok = true;
                 if (result.getStatus() == TFrontendPingFrontendStatusCode.OK) {
diff --git a/gensrc/thrift/FrontendService.thrift 
b/gensrc/thrift/FrontendService.thrift
index f45e64c3103..181b632e43f 100644
--- a/gensrc/thrift/FrontendService.thrift
+++ b/gensrc/thrift/FrontendService.thrift
@@ -949,6 +949,7 @@ enum TFrontendPingFrontendStatusCode {
 struct TFrontendPingFrontendRequest {
    1: required i32 clusterId
    2: required string token
+   3: optional string deployMode
 }
 
 struct TDiskInfo {


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

Reply via email to