1use std::sync::Arc;
16
17use common_config::KvBackendConfig;
18use common_error::ext::BoxedError;
19use common_meta::kv_backend::{ClosableKvBackendRef, KvBackendRef};
20use common_telemetry::{debug, info};
21use log_store::raft_engine::RaftEngineBackend;
22use snafu::{ResultExt, ensure};
23use url::Url;
24
25use crate::error::{InvalidUrlSchemeSnafu, OpenMetadataKvBackendSnafu, ParseUrlSnafu, Result};
26
27pub fn open_metadata_kvbackend(
29 dir: String,
30 config: KvBackendConfig,
31) -> Result<ClosableKvBackendRef> {
32 info!(
33 "Creating metadata kvbackend with dir: {}, config: {:?}",
34 dir, config
35 );
36 let kv_backend = RaftEngineBackend::try_open_with_cfg(dir, &config)
37 .map_err(BoxedError::new)
38 .context(OpenMetadataKvBackendSnafu)?;
39
40 Ok(Arc::new(kv_backend))
41}
42
43pub fn build_metadata_kvbackend(dir: String, config: KvBackendConfig) -> Result<KvBackendRef> {
45 open_metadata_kvbackend(dir, config).map(|kv_backend| kv_backend as KvBackendRef)
46}
47
48pub fn build_metadata_kv_from_url(url: &str) -> Result<KvBackendRef> {
50 debug!("Building metadata kvbackend from url: {}", url);
51 let url = Url::parse(url).context(ParseUrlSnafu { url })?;
52 ensure!(
53 url.scheme() == "raftengine",
54 InvalidUrlSchemeSnafu {
55 scheme: url.scheme(),
56 }
57 );
58
59 let path = normalize_raftengine_path(url.path());
60 build_metadata_kvbackend(path, Default::default())
61}
62
63fn normalize_raftengine_path(path: &str) -> String {
64 if cfg!(windows) {
65 let mut path = path.replace('\\', "/");
66 if let Some(stripped) = path.strip_prefix('/') {
67 let bytes = stripped.as_bytes();
68 if bytes.len() >= 2 && bytes[0].is_ascii_alphabetic() && bytes[1] == b':' {
69 path = stripped.to_string();
70 }
71 }
72 path
73 } else {
74 path.to_string()
75 }
76}