Line data Source code
1 : /* 2 : Copyright 2018-2024, Barcelona Supercomputing Center (BSC), Spain 3 : Copyright 2015-2024, Johannes Gutenberg Universitaet Mainz, Germany 4 : 5 : This software was partially supported by the 6 : EC H2020 funded project NEXTGenIO (Project ID: 671951, www.nextgenio.eu). 7 : 8 : This software was partially supported by the 9 : ADA-FS project under the SPPEXA project funded by the DFG. 10 : 11 : This file is part of GekkoFS. 12 : 13 : GekkoFS is free software: you can redistribute it and/or modify 14 : it under the terms of the GNU General Public License as published by 15 : the Free Software Foundation, either version 3 of the License, or 16 : (at your option) any later version. 17 : 18 : GekkoFS is distributed in the hope that it will be useful, 19 : but WITHOUT ANY WARRANTY; without even the implied warranty of 20 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 : GNU General Public License for more details. 22 : 23 : You should have received a copy of the GNU General Public License 24 : along with GekkoFS. If not, see <https://www.gnu.org/licenses/>. 25 : 26 : SPDX-License-Identifier: GPL-3.0-or-later 27 : */ 28 : 29 : #include <daemon/backend/metadata/db.hpp> 30 : #include <daemon/backend/metadata/merge.hpp> 31 : #include <daemon/backend/exceptions.hpp> 32 : #include <daemon/backend/metadata/metadata_module.hpp> 33 : 34 : #include <common/metadata.hpp> 35 : #include <common/path_util.hpp> 36 : #include <filesystem> 37 : 38 : extern "C" { 39 : #include <sys/stat.h> 40 : } 41 : namespace fs = std::filesystem; 42 : 43 : namespace gkfs::metadata { 44 : 45 : /** 46 : * Factory to create DB instances 47 : * @param path where KV store data is stored 48 : * @param id parallax or rocksdb (default) backend 49 : */ 50 : struct MetadataDBFactory { 51 : static std::unique_ptr<AbstractMetadataBackend> 52 33 : create(const std::string& path, const std::string_view id) { 53 : 54 33 : if(id == gkfs::metadata::parallax_backend) { 55 : #ifdef GKFS_ENABLE_PARALLAX 56 : auto metadata_path = fmt::format("{}/{}", path, 57 : gkfs::metadata::parallax_backend); 58 : GKFS_METADATA_MOD->log()->trace("Using Parallax file '{}'", 59 : metadata_path); 60 : return std::make_unique<ParallaxBackend>(metadata_path); 61 : #endif 62 33 : } else if(id == gkfs::metadata::rocksdb_backend) { 63 : #ifdef GKFS_ENABLE_ROCKSDB 64 33 : auto metadata_path = 65 33 : fmt::format("{}/{}", path, gkfs::metadata::rocksdb_backend); 66 33 : fs::create_directories(metadata_path); 67 33 : GKFS_METADATA_MOD->log()->trace("Using RocksDB directory '{}'", 68 33 : metadata_path); 69 33 : return std::make_unique<RocksDBBackend>(metadata_path); 70 : #endif 71 : } 72 0 : GKFS_METADATA_MOD->log()->error("No valid metadata backend selected"); 73 0 : exit(EXIT_FAILURE); 74 : } 75 : }; 76 : 77 : /** 78 : * @internal 79 : * Called when RocksDB connection is established. 80 : * Used for setting KV store settings 81 : * see here: https://github.com/facebook/rocksdb/wiki/RocksDB-Tuning-Guide 82 : * @endinternal 83 : */ 84 33 : MetadataDB::MetadataDB(const std::string& path, const std::string_view database) 85 33 : : path_(path) { 86 : 87 : /* Get logger instance and set it for data module and chunk storage */ 88 66 : GKFS_METADATA_MOD->log(spdlog::get(GKFS_METADATA_MOD->LOGGER_NAME)); 89 33 : assert(GKFS_METADATA_MOD->log()); 90 33 : log_ = spdlog::get(GKFS_METADATA_MOD->LOGGER_NAME); 91 33 : assert(log_); 92 : 93 33 : backend_ = MetadataDBFactory::create(path, database); 94 33 : } 95 : 96 66 : MetadataDB::~MetadataDB() { 97 66 : backend_.reset(); 98 33 : } 99 : 100 : std::string 101 1403 : MetadataDB::get(const std::string& key) const { 102 1403 : return backend_->get(key); 103 : } 104 : 105 : void 106 0 : MetadataDB::put(const std::string& key, const std::string& val) { 107 0 : assert(gkfs::path::is_absolute(key)); 108 0 : assert(key == "/" || !gkfs::path::has_trailing_slash(key)); 109 : 110 0 : backend_->put(key, val); 111 0 : } 112 : 113 : /** 114 : * @internal 115 : * This function does not use a mutex. 116 : * @endinternal 117 : */ 118 : void 119 1100 : MetadataDB::put_no_exist(const std::string& key, const std::string& val) { 120 1100 : backend_->put_no_exist(key, val); 121 1097 : } 122 : 123 : void 124 8 : MetadataDB::remove(const std::string& key) { 125 8 : backend_->remove(key); 126 8 : } 127 : 128 : bool 129 0 : MetadataDB::exists(const std::string& key) { 130 0 : return backend_->exists(key); 131 : } 132 : 133 : void 134 31 : MetadataDB::update(const std::string& old_key, const std::string& new_key, 135 : const std::string& val) { 136 31 : backend_->update(old_key, new_key, val); 137 31 : } 138 : 139 : off_t 140 41 : MetadataDB::increase_size(const std::string& key, size_t io_size, off_t offset, 141 : bool append) { 142 41 : return backend_->increase_size(key, io_size, offset, append); 143 : } 144 : 145 : void 146 3 : MetadataDB::decrease_size(const std::string& key, size_t size) { 147 3 : backend_->decrease_size(key, size); 148 3 : } 149 : 150 : std::vector<std::pair<std::string, bool>> 151 25 : MetadataDB::get_dirents(const std::string& dir) const { 152 25 : auto root_path = dir; 153 25 : assert(gkfs::path::is_absolute(root_path)); 154 : // add trailing slash if missing 155 25 : if(!gkfs::path::has_trailing_slash(root_path) && root_path.size() != 1) { 156 : // add trailing slash only if missing and is not the root_folder "/" 157 19 : root_path.push_back('/'); 158 : } 159 : 160 50 : return backend_->get_dirents(root_path); 161 : } 162 : 163 : std::vector<std::tuple<std::string, bool, size_t, time_t>> 164 4 : MetadataDB::get_dirents_extended(const std::string& dir) const { 165 4 : auto root_path = dir; 166 4 : assert(gkfs::path::is_absolute(root_path)); 167 : // add trailing slash if missing 168 4 : if(!gkfs::path::has_trailing_slash(root_path) && root_path.size() != 1) { 169 : // add trailing slash only if missing and is not the root_folder "/" 170 4 : root_path.push_back('/'); 171 : } 172 : 173 8 : return backend_->get_dirents_extended(root_path); 174 : } 175 : 176 : 177 : /** 178 : * @internal 179 : * Code example for iterating all entries in KV store. This is for debug only as 180 : * it is too expensive. 181 : * @endinternal 182 : */ 183 : void 184 0 : MetadataDB::iterate_all() const { 185 0 : backend_->iterate_all(); 186 0 : } 187 : 188 : } // namespace gkfs::metadata