Skip to main content

greptime/
greptime.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15#![recursion_limit = "256"]
16#![doc = include_str!("../../../../README.md")]
17
18use clap::{Parser, Subcommand};
19use cmd::datanode::builder::InstanceBuilder;
20use cmd::error::{InitTlsProviderSnafu, Result};
21use cmd::options::GlobalOptions;
22use cmd::{App, cli, datanode, flownode, frontend, metasrv, standalone, user};
23use common_base::Plugins;
24use common_version::{product_name, verbose_version, version};
25use servers::install_default_crypto_provider;
26
27#[derive(Parser)]
28#[command(name = product_name(), author, version, long_version = verbose_version(), about)]
29#[command(propagate_version = true)]
30pub(crate) struct Command {
31    #[clap(subcommand)]
32    pub(crate) subcmd: SubCommand,
33
34    #[clap(flatten)]
35    pub(crate) global_options: GlobalOptions,
36}
37
38#[derive(Subcommand)]
39enum SubCommand {
40    /// Start datanode service.
41    #[clap(name = "datanode")]
42    Datanode(datanode::Command),
43
44    /// Start flownode service.
45    #[clap(name = "flownode")]
46    Flownode(flownode::Command),
47
48    /// Start frontend service.
49    #[clap(name = "frontend")]
50    Frontend(frontend::Command),
51
52    /// Start metasrv service.
53    #[clap(name = "metasrv")]
54    Metasrv(metasrv::Command),
55
56    /// Start service in standalone mode.
57    #[clap(name = "standalone")]
58    Standalone(standalone::Command),
59
60    /// Execute the cli tools.
61    #[clap(name = "cli")]
62    Cli(cli::Command),
63
64    /// Manage user credentials.
65    #[clap(name = "user")]
66    User(user::Command),
67}
68
69#[cfg(not(windows))]
70#[global_allocator]
71static ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;
72
73#[cfg(debug_assertions)]
74fn main() -> Result<()> {
75    use snafu::ResultExt;
76    // Set the stack size to 8MB for the thread so it wouldn't overflow on large stack usage in debug mode
77    // see https://github.com/GreptimeTeam/greptimedb/pull/4317
78    // and https://github.com/rust-lang/rust/issues/34283
79    std::thread::Builder::new()
80        .name("main_spawn".to_string())
81        .stack_size(8 * 1024 * 1024)
82        .spawn(|| {
83            {
84                tokio::runtime::Builder::new_multi_thread()
85                    .thread_stack_size(8 * 1024 * 1024)
86                    .enable_all()
87                    .build()
88                    .expect("Failed building the Runtime")
89                    .block_on(main_body())
90            }
91        })
92        .context(cmd::error::SpawnThreadSnafu)?
93        .join()
94        .expect("Couldn't join on the associated thread")
95}
96
97#[cfg(not(debug_assertions))]
98#[tokio::main]
99async fn main() -> Result<()> {
100    main_body().await
101}
102
103async fn main_body() -> Result<()> {
104    setup_human_panic();
105    install_default_crypto_provider().map_err(|msg| InitTlsProviderSnafu { msg }.build())?;
106    start(Command::parse()).await
107}
108
109async fn start(cli: Command) -> Result<()> {
110    match cli.subcmd {
111        SubCommand::Datanode(cmd) => match cmd.subcmd {
112            datanode::SubCommand::Start(ref start) => {
113                let opts = start.load_options(&cli.global_options)?;
114                let plugins = Plugins::new();
115                let builder = InstanceBuilder::try_new_with_init(opts, plugins).await?;
116                cmd.build_with(builder).await?.run().await
117            }
118            datanode::SubCommand::Objbench(ref bench) => bench.run().await,
119            datanode::SubCommand::Scanbench(ref bench) => bench.run().await,
120            datanode::SubCommand::Parquetbench(ref bench) => bench.run().await,
121        },
122        SubCommand::Flownode(cmd) => {
123            cmd.build(cmd.load_options(&cli.global_options)?)
124                .await?
125                .run()
126                .await
127        }
128        SubCommand::Frontend(cmd) => {
129            cmd.build(cmd.load_options(&cli.global_options)?)
130                .await?
131                .run()
132                .await
133        }
134        SubCommand::Metasrv(cmd) => {
135            cmd.build(cmd.load_options(&cli.global_options)?)
136                .await?
137                .run()
138                .await
139        }
140        SubCommand::Standalone(cmd) => {
141            cmd.build(cmd.load_options(&cli.global_options)?)
142                .await?
143                .run()
144                .await
145        }
146        SubCommand::Cli(cmd) => {
147            cmd.build(cmd.load_options(&cli.global_options)?)
148                .await?
149                .run()
150                .await
151        }
152        SubCommand::User(cmd) => cmd.run(),
153    }
154}
155
156fn setup_human_panic() {
157    human_panic::setup_panic!(
158        human_panic::Metadata::new(product_name(), version())
159            .homepage("https://github.com/GreptimeTeam/greptimedb/discussions")
160    );
161
162    common_telemetry::set_panic_hook();
163}