public void initialize(String[] args) throws Exception {
        // set meta dir first.
        // we already set these variables in constructor. but GlobalStateMgr is a singleton class.
        // so they may be set before Config is initialized.
        // set them here again to make sure these variables use values in fe.conf.
        setMetaDir();

        // must judge whether it is first time start here before initializing GlobalStateMgr.
        // Possibly remove clusterId and role to ensure that the system is not left in a half-initialized state.
        boolean isFirstTimeStart = nodeMgr.isVersionAndRoleFilesNotExist();
        try {
            // 0. get local node and helper node info
            nodeMgr.initialize(args);

            // 1. create dirs and files
            if (Config.edit_log_type.equalsIgnoreCase("bdb")) {
                File imageDir = new File(this.imageDir);
                if (!imageDir.exists()) {
                    imageDir.mkdirs();
                }
                File imageV2Dir = new File(this.imageDir + "/v2");
                if (!imageV2Dir.exists()) {
                    imageV2Dir.mkdirs();
                }
            } else {
                LOG.error("Invalid edit log type: {}", Config.edit_log_type);
                System.exit(-1);
            }

            // init plugin manager
            pluginMgr.init();
            auditEventProcessor.start();

            // 2. get cluster id and role (Observer or Follower)
            nodeMgr.getClusterIdAndRoleOnStartup();

            // 3. Load image first and replay edits
            initJournal();
            loadImage(this.imageDir); // load image file

            // 4. create load and export job label cleaner thread
            createLabelCleaner();

            // 5. create txn timeout checker thread
            createTxnTimeoutChecker();

            // 6. start task cleaner thread
            createTaskCleaner();
            createTableKeeper();

            // 7. init starosAgent
            if (RunMode.isSharedDataMode() && !starOSAgent.init(null)) {
                LOG.error("init starOSAgent failed");
                System.exit(-1);
            }
        } catch (Exception e) {
            try {
                if (isFirstTimeStart) {
                    // If it is the first time we start, we remove the cluster ID and role
                    // to prevent leaving the system in an inconsistent state.
                    nodeMgr.removeClusterIdAndRole();
                }
            } catch (Throwable t) {
                e.addSuppressed(t);
            }
            throw e;
        }
    }
@Test
    public void testErrorOccursWhileRemovingClusterIdAndRoleWhenStartAtFirstTime() {
        final String removeFileErrorMessage = "Failed to delete role and version files.";

        NodeMgr nodeMgr = Mockito.spy(new NodeMgr());
        Mockito.doThrow(new RuntimeException(removeFileErrorMessage)).when(nodeMgr).removeClusterIdAndRole();

        GlobalStateMgr globalStateMgr = new MyGlobalStateMgr(true, nodeMgr);
        Assert.assertTrue(nodeMgr.isVersionAndRoleFilesNotExist());
        try {
            globalStateMgr.initialize(new String[0]);
        } catch (Exception e) {
            Assert.assertTrue(e instanceof UnsupportedOperationException);
            Assert.assertEquals(MyGlobalStateMgr.ERROR_MESSAGE, e.getMessage());

            Throwable[] suppressedExceptions = e.getSuppressed();
            Assert.assertEquals(1, suppressedExceptions.length);
            Assert.assertTrue(suppressedExceptions[0] instanceof RuntimeException);
            Assert.assertEquals(removeFileErrorMessage, suppressedExceptions[0].getMessage());
        }
    }