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            #[cfg(feature = "dev-tools")]
121            datanode::SubCommand::Parquetbench(ref bench) => bench.run().await,
122        },
123        SubCommand::Flownode(cmd) => {
124            cmd.build(cmd.load_options(&cli.global_options)?)
125                .await?
126                .run()
127                .await
128        }
129        SubCommand::Frontend(cmd) => {
130            cmd.build(cmd.load_options(&cli.global_options)?)
131                .await?
132                .run()
133                .await
134        }
135        SubCommand::Metasrv(cmd) => {
136            cmd.build(cmd.load_options(&cli.global_options)?)
137                .await?
138                .run()
139                .await
140        }
141        SubCommand::Standalone(cmd) => {
142            cmd.build(cmd.load_options(&cli.global_options)?)
143                .await?
144                .run()
145                .await
146        }
147        SubCommand::Cli(cmd) => {
148            cmd.build(cmd.load_options(&cli.global_options)?)
149                .await?
150                .run()
151                .await
152        }
153        SubCommand::User(cmd) => cmd.run(),
154    }
155}
156
157fn setup_human_panic() {
158    human_panic::setup_panic!(
159        human_panic::Metadata::new(product_name(), version())
160            .homepage("https://github.com/GreptimeTeam/greptimedb/discussions")
161    );
162
163    common_telemetry::set_panic_hook();
164}