object_store/
manager.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
15use std::collections::HashMap;
16use std::sync::Arc;
17
18use crate::ObjectStore;
19
20pub type ObjectStoreManagerRef = Arc<ObjectStoreManager>;
21
22/// Manages multiple object stores so that users can configure a storage for each table.
23/// This struct certainly have one default object store, and can have zero or more custom object stores.
24#[derive(Debug)]
25pub struct ObjectStoreManager {
26    stores: HashMap<String, ObjectStore>,
27    default_object_store: ObjectStore,
28}
29
30impl ObjectStoreManager {
31    /// Creates a new manager from the object store used as a default one.
32    pub fn new(name: &str, object_store: ObjectStore) -> Self {
33        ObjectStoreManager {
34            stores: [(name.to_lowercase(), object_store.clone())].into(),
35            default_object_store: object_store,
36        }
37    }
38
39    /// Adds an object store to the manager.
40    /// # Safety
41    ///      Panic when the name already exists
42    pub fn add(&mut self, name: &str, object_store: ObjectStore) {
43        let name = name.to_lowercase();
44        if self.stores.insert(name.clone(), object_store).is_some() {
45            panic!("Object storage provider name conflicts, the `{name}` already exists");
46        }
47    }
48
49    /// Finds an object store corresponding to the name.
50    pub fn find(&self, name: &str) -> Option<&ObjectStore> {
51        self.stores.get(&name.to_lowercase())
52    }
53
54    /// Returns the default object storage
55    pub fn default_object_store(&self) -> &ObjectStore {
56        &self.default_object_store
57    }
58}
59
60#[cfg(test)]
61mod tests {
62    use common_test_util::temp_dir::{create_temp_dir, TempDir};
63
64    use super::ObjectStoreManager;
65    use crate::services::Fs as Builder;
66    use crate::ObjectStore;
67
68    fn new_object_store(dir: &TempDir) -> ObjectStore {
69        let store_dir = dir.path().to_str().unwrap();
70        let builder = Builder::default().root(store_dir);
71        ObjectStore::new(builder).unwrap().finish()
72    }
73
74    #[test]
75    fn test_manager_behavior() {
76        let dir = create_temp_dir("default");
77        let mut manager = ObjectStoreManager::new("Default", new_object_store(&dir));
78
79        assert!(manager.find("default").is_some());
80        assert!(manager.find("Default").is_some());
81        assert!(manager.find("Gcs").is_none());
82        assert!(manager.find("gcs").is_none());
83
84        let dir = create_temp_dir("default");
85        manager.add("Gcs", new_object_store(&dir));
86
87        // Should not overwrite the default object store with the new one.
88        assert!(manager.find("default").is_some());
89        assert!(manager.find("Gcs").is_some());
90        assert!(manager.find("gcs").is_some());
91    }
92}