|
32 | 32 |
|
33 | 33 | #include "tiledb/sm/consolidator/consolidator.h" |
34 | 34 | #include "tiledb/common/logger.h" |
| 35 | +#include "tiledb/common/stdx_string.h" |
35 | 36 | #include "tiledb/sm/consolidator/array_meta_consolidator.h" |
36 | 37 | #include "tiledb/sm/consolidator/commits_consolidator.h" |
37 | 38 | #include "tiledb/sm/consolidator/fragment_consolidator.h" |
38 | 39 | #include "tiledb/sm/consolidator/fragment_meta_consolidator.h" |
39 | 40 | #include "tiledb/sm/consolidator/group_meta_consolidator.h" |
| 41 | +#include "tiledb/sm/enums/encryption_type.h" |
| 42 | +#include "tiledb/sm/rest/rest_client.h" |
40 | 43 | #include "tiledb/sm/storage_manager/storage_manager.h" |
| 44 | +#include "tiledb/storage_format/uri/generate_uri.h" |
41 | 45 |
|
42 | 46 | using namespace tiledb::common; |
43 | 47 |
|
@@ -121,12 +125,207 @@ Status Consolidator::consolidate( |
121 | 125 | } |
122 | 126 |
|
123 | 127 | void Consolidator::vacuum([[maybe_unused]] const char* array_name) { |
124 | | - throw Status_ConsolidatorError("Cannot vacuum; Invalid object"); |
| 128 | + throw ConsolidatorException("Cannot vacuum; Invalid object"); |
| 129 | +} |
| 130 | + |
| 131 | +void Consolidator::array_consolidate( |
| 132 | + const char* array_name, |
| 133 | + EncryptionType encryption_type, |
| 134 | + const void* encryption_key, |
| 135 | + uint32_t key_length, |
| 136 | + const Config& config, |
| 137 | + StorageManager* storage_manager) { |
| 138 | + // Check array URI |
| 139 | + URI array_uri(array_name); |
| 140 | + if (array_uri.is_invalid()) { |
| 141 | + throw ConsolidatorException("Cannot consolidate array; Invalid URI"); |
| 142 | + } |
| 143 | + |
| 144 | + // Check if array exists |
| 145 | + ObjectType obj_type; |
| 146 | + throw_if_not_ok(storage_manager->object_type(array_uri, &obj_type)); |
| 147 | + |
| 148 | + if (obj_type != ObjectType::ARRAY) { |
| 149 | + throw ConsolidatorException( |
| 150 | + "Cannot consolidate array; Array does not exist"); |
| 151 | + } |
| 152 | + |
| 153 | + if (array_uri.is_tiledb()) { |
| 154 | + throw_if_not_ok(storage_manager->rest_client()->post_consolidation_to_rest( |
| 155 | + array_uri, config)); |
| 156 | + } else { |
| 157 | + // Get encryption key from config |
| 158 | + std::string encryption_key_from_cfg; |
| 159 | + if (!encryption_key) { |
| 160 | + bool found = false; |
| 161 | + encryption_key_from_cfg = config.get("sm.encryption_key", &found); |
| 162 | + assert(found); |
| 163 | + } |
| 164 | + |
| 165 | + if (!encryption_key_from_cfg.empty()) { |
| 166 | + encryption_key = encryption_key_from_cfg.c_str(); |
| 167 | + key_length = static_cast<uint32_t>(encryption_key_from_cfg.size()); |
| 168 | + std::string encryption_type_from_cfg; |
| 169 | + bool found = false; |
| 170 | + encryption_type_from_cfg = config.get("sm.encryption_type", &found); |
| 171 | + assert(found); |
| 172 | + auto [st, et] = encryption_type_enum(encryption_type_from_cfg); |
| 173 | + throw_if_not_ok(st); |
| 174 | + encryption_type = et.value(); |
| 175 | + |
| 176 | + if (!EncryptionKey::is_valid_key_length( |
| 177 | + encryption_type, |
| 178 | + static_cast<uint32_t>(encryption_key_from_cfg.size()))) { |
| 179 | + encryption_key = nullptr; |
| 180 | + key_length = 0; |
| 181 | + } |
| 182 | + } |
| 183 | + |
| 184 | + // Consolidate |
| 185 | + auto mode = Consolidator::mode_from_config(config); |
| 186 | + auto consolidator = Consolidator::create(mode, config, storage_manager); |
| 187 | + throw_if_not_ok(consolidator->consolidate( |
| 188 | + array_name, encryption_type, encryption_key, key_length)); |
| 189 | + } |
| 190 | +} |
| 191 | + |
| 192 | +void Consolidator::fragments_consolidate( |
| 193 | + const char* array_name, |
| 194 | + EncryptionType encryption_type, |
| 195 | + const void* encryption_key, |
| 196 | + uint32_t key_length, |
| 197 | + const std::vector<std::string> fragment_uris, |
| 198 | + const Config& config, |
| 199 | + StorageManager* storage_manager) { |
| 200 | + // Check array URI |
| 201 | + URI array_uri(array_name); |
| 202 | + if (array_uri.is_invalid()) { |
| 203 | + throw ConsolidatorException("Cannot consolidate array; Invalid URI"); |
| 204 | + } |
| 205 | + |
| 206 | + // Check if array exists |
| 207 | + ObjectType obj_type; |
| 208 | + throw_if_not_ok(storage_manager->object_type(array_uri, &obj_type)); |
| 209 | + |
| 210 | + if (obj_type != ObjectType::ARRAY) { |
| 211 | + throw ConsolidatorException( |
| 212 | + "Cannot consolidate array; Array does not exist"); |
| 213 | + } |
| 214 | + |
| 215 | + // Get encryption key from config |
| 216 | + std::string encryption_key_from_cfg; |
| 217 | + if (!encryption_key) { |
| 218 | + bool found = false; |
| 219 | + encryption_key_from_cfg = config.get("sm.encryption_key", &found); |
| 220 | + assert(found); |
| 221 | + } |
| 222 | + |
| 223 | + if (!encryption_key_from_cfg.empty()) { |
| 224 | + encryption_key = encryption_key_from_cfg.c_str(); |
| 225 | + key_length = static_cast<uint32_t>(encryption_key_from_cfg.size()); |
| 226 | + std::string encryption_type_from_cfg; |
| 227 | + bool found = false; |
| 228 | + encryption_type_from_cfg = config.get("sm.encryption_type", &found); |
| 229 | + assert(found); |
| 230 | + auto [st, et] = encryption_type_enum(encryption_type_from_cfg); |
| 231 | + throw_if_not_ok(st); |
| 232 | + encryption_type = et.value(); |
| 233 | + |
| 234 | + if (!EncryptionKey::is_valid_key_length( |
| 235 | + encryption_type, |
| 236 | + static_cast<uint32_t>(encryption_key_from_cfg.size()))) { |
| 237 | + encryption_key = nullptr; |
| 238 | + key_length = 0; |
| 239 | + } |
| 240 | + } |
| 241 | + |
| 242 | + // Consolidate |
| 243 | + auto consolidator = Consolidator::create( |
| 244 | + ConsolidationMode::FRAGMENT, config, storage_manager); |
| 245 | + auto fragment_consolidator = |
| 246 | + dynamic_cast<FragmentConsolidator*>(consolidator.get()); |
| 247 | + throw_if_not_ok(fragment_consolidator->consolidate_fragments( |
| 248 | + array_name, encryption_type, encryption_key, key_length, fragment_uris)); |
| 249 | +} |
| 250 | + |
| 251 | +void Consolidator::write_consolidated_commits_file( |
| 252 | + format_version_t write_version, |
| 253 | + ArrayDirectory array_dir, |
| 254 | + const std::vector<URI>& commit_uris, |
| 255 | + StorageManager* storage_manager) { |
| 256 | + // Compute the file name. |
| 257 | + auto name = storage_format::generate_consolidated_fragment_name( |
| 258 | + commit_uris.front(), commit_uris.back(), write_version); |
| 259 | + |
| 260 | + // Compute size of consolidated file. Save the sizes of the files to re-use |
| 261 | + // below. |
| 262 | + storage_size_t total_size = 0; |
| 263 | + const auto base_uri_size = array_dir.uri().to_string().size(); |
| 264 | + std::vector<storage_size_t> file_sizes(commit_uris.size()); |
| 265 | + for (uint64_t i = 0; i < commit_uris.size(); i++) { |
| 266 | + const auto& uri = commit_uris[i]; |
| 267 | + total_size += uri.to_string().size() - base_uri_size + 1; |
| 268 | + |
| 269 | + // If the file is a delete, add the file size to the count and the size of |
| 270 | + // the size variable. |
| 271 | + if (stdx::string::ends_with( |
| 272 | + uri.to_string(), constants::delete_file_suffix)) { |
| 273 | + throw_if_not_ok(storage_manager->vfs()->file_size(uri, &file_sizes[i])); |
| 274 | + total_size += file_sizes[i]; |
| 275 | + total_size += sizeof(storage_size_t); |
| 276 | + } |
| 277 | + } |
| 278 | + |
| 279 | + // Write consolidated file, URIs are relative to the array URI. |
| 280 | + std::vector<uint8_t> data(total_size); |
| 281 | + storage_size_t file_index = 0; |
| 282 | + for (uint64_t i = 0; i < commit_uris.size(); i++) { |
| 283 | + // Add the uri. |
| 284 | + const auto& uri = commit_uris[i]; |
| 285 | + std::string relative_uri = uri.to_string().substr(base_uri_size) + "\n"; |
| 286 | + memcpy(&data[file_index], relative_uri.data(), relative_uri.size()); |
| 287 | + file_index += relative_uri.size(); |
| 288 | + |
| 289 | + // For deletes, read the delete condition to the output file. |
| 290 | + if (stdx::string::ends_with( |
| 291 | + uri.to_string(), constants::delete_file_suffix)) { |
| 292 | + memcpy(&data[file_index], &file_sizes[i], sizeof(storage_size_t)); |
| 293 | + file_index += sizeof(storage_size_t); |
| 294 | + throw_if_not_ok(storage_manager->vfs()->read( |
| 295 | + uri, 0, &data[file_index], file_sizes[i])); |
| 296 | + file_index += file_sizes[i]; |
| 297 | + } |
| 298 | + } |
| 299 | + |
| 300 | + // Write the file to storage. |
| 301 | + URI consolidated_commits_uri = |
| 302 | + array_dir.get_commits_dir(write_version) |
| 303 | + .join_path(name + constants::con_commits_file_suffix); |
| 304 | + throw_if_not_ok(storage_manager->vfs()->write( |
| 305 | + consolidated_commits_uri, data.data(), data.size())); |
| 306 | + throw_if_not_ok(storage_manager->vfs()->close_file(consolidated_commits_uri)); |
| 307 | +} |
| 308 | + |
| 309 | +void Consolidator::array_vacuum( |
| 310 | + const char* array_name, |
| 311 | + const Config& config, |
| 312 | + StorageManager* storage_manager) { |
| 313 | + URI array_uri(array_name); |
| 314 | + if (array_uri.is_tiledb()) { |
| 315 | + throw_if_not_ok( |
| 316 | + storage_manager->rest_client()->post_vacuum_to_rest(array_uri, config)); |
| 317 | + return; |
| 318 | + } |
| 319 | + |
| 320 | + auto mode = Consolidator::mode_from_config(config, true); |
| 321 | + auto consolidator = Consolidator::create(mode, config, storage_manager); |
| 322 | + consolidator->vacuum(array_name); |
125 | 323 | } |
126 | 324 |
|
127 | 325 | void Consolidator::check_array_uri(const char* array_name) { |
128 | 326 | if (URI(array_name).is_tiledb()) { |
129 | | - throw std::logic_error("Consolidation is not supported for remote arrays."); |
| 327 | + throw ConsolidatorException( |
| 328 | + "Consolidation is not supported for remote arrays."); |
130 | 329 | } |
131 | 330 | } |
132 | 331 |
|
|
0 commit comments