| // 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. |
| |
| #![allow(incomplete_features)] |
| #![allow(non_camel_case_types)] |
| #![allow(clippy::upper_case_acronyms)] |
| #![allow(clippy::result_large_err)] |
| // For prost generated struct |
| #![allow(clippy::derive_partial_eq_without_eq)] |
| // The clippy throws an error if the reference clone not wrapped into `Arc::clone` |
| // The lint makes easier for code reader/reviewer separate references clones from more heavyweight ones |
| #![deny(clippy::clone_on_ref_ptr)] |
| extern crate core; |
| |
| #[macro_use] |
| extern crate datafusion_comet_jni_bridge; |
| |
| use jni::{ |
| objects::{JClass, JString}, |
| EnvUnowned, |
| }; |
| use log::info; |
| use log4rs::{ |
| append::console::{ConsoleAppender, Target}, |
| config::{load_config_file, Appender, Deserializers, Root}, |
| encode::pattern::PatternEncoder, |
| Config, |
| }; |
| |
| #[cfg(all( |
| not(target_env = "msvc"), |
| feature = "jemalloc", |
| not(feature = "mimalloc") |
| ))] |
| use tikv_jemallocator::Jemalloc; |
| |
| #[cfg(all( |
| feature = "mimalloc", |
| not(all(not(target_env = "msvc"), feature = "jemalloc")) |
| ))] |
| use mimalloc::MiMalloc; |
| |
| // Re-export from jvm-bridge crate for internal use |
| pub use datafusion_comet_jni_bridge::errors; |
| pub use datafusion_comet_jni_bridge::JAVA_VM; |
| |
| /// Re-export jvm-bridge items under the `jvm_bridge` name for convenience. |
| pub mod jvm_bridge { |
| pub use datafusion_comet_jni_bridge::*; |
| } |
| |
| use errors::{try_unwrap_or_throw, CometError, CometResult}; |
| |
| #[macro_use] |
| pub mod common; |
| pub mod execution; |
| pub mod parquet; |
| // this module is for non release only. Intended for debugging/profiling purposes |
| #[cfg(debug_assertions)] |
| pub mod debug; |
| |
| #[cfg(all( |
| not(target_env = "msvc"), |
| feature = "jemalloc", |
| not(feature = "mimalloc") |
| ))] |
| #[global_allocator] |
| static GLOBAL: Jemalloc = Jemalloc; |
| |
| #[cfg(all( |
| feature = "mimalloc", |
| not(all(not(target_env = "msvc"), feature = "jemalloc")) |
| ))] |
| #[global_allocator] |
| static GLOBAL: MiMalloc = MiMalloc; |
| |
| #[no_mangle] |
| pub extern "system" fn Java_org_apache_comet_NativeBase_init( |
| e: EnvUnowned, |
| _: JClass, |
| log_conf_path: JString, |
| log_level: JString, |
| ) { |
| // Initialize the error handling to capture panic backtraces |
| errors::init(); |
| |
| try_unwrap_or_throw(&e, |env| { |
| let path: String = log_conf_path.try_to_string(env)?; |
| |
| // empty path means there is no custom log4rs config file provided, so fallback to use |
| // the default configuration |
| let log_config = if path.is_empty() { |
| let log_level: String = match log_level.try_to_string(env) { |
| Ok(level) => level, |
| Err(_) => "info".parse().unwrap(), |
| }; |
| default_logger_config(&log_level) |
| } else { |
| load_config_file(path, Deserializers::default()) |
| .map_err(|err| CometError::Config(err.to_string())) |
| }; |
| |
| let _ = log4rs::init_config(log_config?).map_err(|err| CometError::Config(err.to_string())); |
| |
| // Initialize the global Java VM |
| let java_vm = env.get_java_vm()?; |
| JAVA_VM.get_or_init(|| java_vm); |
| |
| let comet_version = env!("CARGO_PKG_VERSION"); |
| info!("Comet native library version {comet_version} initialized"); |
| Ok(()) |
| }) |
| } |
| |
| const LOG_PATTERN: &str = "{d(%y/%m/%d %H:%M:%S)} {l} {f}: {m}{n}"; |
| |
| /// JNI method to check if a specific feature is enabled in the native Rust code. |
| /// # Arguments |
| /// * `feature_name` - The name of the feature to check. Supported features: |
| /// - "jemalloc" - tikv-jemallocator memory allocator |
| /// - "hdfs" - HDFS object store support |
| /// - "hdfs-opendal" - HDFS support via OpenDAL |
| /// # Returns |
| /// * `1` (true) if the feature is enabled |
| /// * `0` (false) if the feature is disabled or unknown |
| #[no_mangle] |
| pub extern "system" fn Java_org_apache_comet_NativeBase_isFeatureEnabled( |
| env: EnvUnowned, |
| _: JClass, |
| feature_name: JString, |
| ) -> jni::sys::jboolean { |
| try_unwrap_or_throw(&env, |env| { |
| let feature: String = feature_name.try_to_string(env)?; |
| |
| let enabled = match feature.as_str() { |
| "jemalloc" => cfg!(feature = "jemalloc"), |
| "hdfs" => cfg!(feature = "hdfs"), |
| "hdfs-opendal" => cfg!(feature = "hdfs-opendal"), |
| _ => false, // Unknown features return false |
| }; |
| |
| Ok(enabled) |
| }) |
| } |
| |
| // Creates a default log4rs config, which logs to console with log level. |
| fn default_logger_config(log_level: &str) -> CometResult<Config> { |
| let console_append = ConsoleAppender::builder() |
| .target(Target::Stderr) |
| .encoder(Box::new(PatternEncoder::new(LOG_PATTERN))) |
| .build(); |
| let appender = Appender::builder().build("console", Box::new(console_append)); |
| let root = Root::builder().appender("console").build( |
| log_level |
| .parse() |
| .map_err(|err| CometError::Config(format!("{err}")))?, |
| ); |
| Config::builder() |
| .appender(appender) |
| .build(root) |
| .map_err(|err| CometError::Config(err.to_string())) |
| } |