Skip to content

Commit 60d39dd

Browse files
committed
Skip partially written metadata files.
1 parent bdd19e8 commit 60d39dd

File tree

8 files changed

+51
-33
lines changed

8 files changed

+51
-33
lines changed

format_spec/metadata.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@ my_array # array folder
1717
```
1818

1919
The metadata folder can contain any number of [timestamped](./timestamped_name.md):
20-
* [metadata files](#array-metadata-file)
20+
* [metadata files](#metadata-file)
2121
* [vacuum files](./vacuum_file.md)
2222
* **Note**: the timestamped names do _not_ include the format version.
2323

2424
## Metadata File
2525

26+
Metadata files with the `.tmp` extension are used for local filesystems only, indicating the metadata is still being flushed to disk.
27+
2628
The metadata file consists of a single [generic tile](./generic_tile.md), containing multiple entries with the following data:
2729

2830
| **Field** | **Type** | **Description** |

tiledb/sm/array/array_directory.cc

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -366,19 +366,7 @@ Status ArrayDirectory::load() {
366366

367367
// Load (in parallel) the array metadata URIs
368368
tasks.emplace_back(resources_.get().compute_tp().execute([&]() {
369-
int delay = 250, max_retries = 25;
370-
for (int retry = 0; retry <= max_retries; ++retry) {
371-
if (load_array_meta_uris()) {
372-
break;
373-
}
374-
// Retry is triggered if metadata files were still flushing to disk.
375-
std::this_thread::sleep_for(std::chrono::milliseconds(delay));
376-
resources_.get().logger()->info(
377-
"Encountered partially written array metadata while opening the "
378-
"array. Waiting {}ms and retrying.", delay);
379-
// Apply (default REST) backoff and retry up to 25 times.
380-
delay *= 1.25;
381-
}
369+
load_array_meta_uris();
382370
return Status::Ok();
383371
}));
384372
}
@@ -606,7 +594,7 @@ std::vector<URI> ArrayDirectory::ls(const URI& uri) const {
606594
std::vector<URI> uris;
607595
uris.reserve(dir_entries.size());
608596

609-
for (auto entry : dir_entries) {
597+
for (const auto& entry : dir_entries) {
610598
auto entry_uri = URI(entry.path().native());
611599

612600
// Always list directories
@@ -844,17 +832,20 @@ ArrayDirectory::load_consolidated_commit_uris(
844832
return {Status::Ok(), uris, uris_set};
845833
}
846834

847-
bool ArrayDirectory::load_array_meta_uris() {
835+
void ArrayDirectory::load_array_meta_uris() {
848836
// Load the URIs in the array metadata directory
849837
std::vector<URI> array_meta_dir_uris;
850838
{
851839
auto timer_se = stats_->start_timer("list_array_meta_uris");
852-
array_meta_dir_uris =
853-
ls(uri_.join_path(constants::array_metadata_dir_name));
854-
}
855-
auto pred = [](const URI& uri) { return uri.to_string().ends_with(".tmp"); };
856-
if (uri_.is_file() && std::ranges::any_of(array_meta_dir_uris, pred)) {
857-
return false;
840+
std::vector<URI> unfiltered_uris;
841+
throw_if_not_ok(resources_.get().vfs().ls(
842+
uri_.join_path(constants::array_metadata_dir_name), &unfiltered_uris));
843+
for (const auto& unfiltered_uri : unfiltered_uris) {
844+
const auto& uri = unfiltered_uri.to_string();
845+
if (!uri.ends_with(constants::temp_file_suffix)) {
846+
array_meta_dir_uris.emplace_back(uri);
847+
}
848+
}
858849
}
859850

860851
// Compute array metadata URIs and vacuum URIs to vacuum. */
@@ -871,7 +862,6 @@ bool ArrayDirectory::load_array_meta_uris() {
871862
throw_if_not_ok(st2);
872863
array_meta_uris_ = std::move(array_meta_filtered_uris.value());
873864
array_meta_dir_uris.clear();
874-
return true;
875865
}
876866

877867
void ArrayDirectory::load_array_schema_uris() {

tiledb/sm/array/array_directory.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -726,7 +726,7 @@ class ArrayDirectory {
726726
load_consolidated_commit_uris(const std::vector<URI>& commits_dir_uris);
727727

728728
/** Loads the array metadata URIs. */
729-
bool load_array_meta_uris();
729+
void load_array_meta_uris();
730730

731731
/** Loads the array schema URIs. */
732732
void load_array_schema_uris();

tiledb/sm/filesystem/posix.cc

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -375,6 +375,15 @@ std::vector<directory_entry> Posix::ls_with_sizes(const URI& uri) const {
375375
if (!strcmp(next_path->d_name, ".") || !strcmp(next_path->d_name, ".."))
376376
continue;
377377
std::string abspath = path + "/" + next_path->d_name;
378+
// Do not attempt to retrieve file size for temporary metadata files that
379+
// are still flushing to disk.
380+
const bool temp_metadata =
381+
URI(abspath)
382+
.parent_path()
383+
.remove_trailing_slash()
384+
.to_string()
385+
.ends_with(constants::array_metadata_dir_name) &&
386+
abspath.ends_with(constants::temp_file_suffix);
378387

379388
// Getting the file size here incurs an additional system call
380389
// via file_size() and ls() calls will feel this too.
@@ -383,7 +392,7 @@ std::vector<directory_entry> Posix::ls_with_sizes(const URI& uri) const {
383392
if (next_path->d_type == DT_DIR) {
384393
entries.emplace_back(abspath, 0, true);
385394
} else {
386-
uint64_t size = file_size(URI(abspath));
395+
uint64_t size = temp_metadata ? 0 : file_size(URI(abspath));
387396
entries.emplace_back(abspath, size, false);
388397
}
389398
}

tiledb/sm/filesystem/win.cc

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -383,13 +383,25 @@ std::vector<directory_entry> Win::ls_with_sizes(const URI& uri) const {
383383
strcmp(find_data.cFileName, "..") != 0) {
384384
std::string file_path =
385385
path + (ends_with_slash ? "" : "\\") + find_data.cFileName;
386+
387+
// Do not attempt to retrieve file size for temporary metadata files that
388+
// are still flushing to disk.
389+
const bool temp_metadata =
390+
URI(file_path)
391+
.parent_path()
392+
.remove_trailing_slash()
393+
.to_string()
394+
.ends_with(constants::array_metadata_dir_name) &&
395+
file_path.ends_with(constants::temp_file_suffix);
396+
386397
if (find_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
387398
entries.emplace_back(file_path, 0, true);
388399
} else {
389400
ULARGE_INTEGER size;
390401
size.LowPart = find_data.nFileSizeLow;
391402
size.HighPart = find_data.nFileSizeHigh;
392-
entries.emplace_back(file_path, size.QuadPart, false);
403+
entries.emplace_back(
404+
file_path, temp_metadata ? 0 : size.QuadPart, false);
393405
}
394406
}
395407

tiledb/sm/metadata/metadata.cc

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -210,15 +210,14 @@ void Metadata::store(
210210
resources.stats().add_counter(
211211
"write_meta_size", size_computation_serializer.size());
212212

213-
// For LocalFS use a .tmp extension until write is flushed.
214-
URI metadata_uri = get_uri(uri);
215-
if (uri.is_file()) {
216-
metadata_uri = URI(metadata_uri.to_string() + ".tmp");
217-
}
218-
// Create a metadata file name
219-
GenericTileIO::store_data(resources, metadata_uri, tile, encryption_key);
220213
if (uri.is_file()) {
214+
// For LocalFS use a .tmp extension until write is flushed.
215+
URI metadata_uri(get_uri(uri).to_string() + ".tmp");
216+
GenericTileIO::store_data(resources, metadata_uri, tile, encryption_key);
221217
resources.vfs().move_file(metadata_uri, get_uri(uri));
218+
} else {
219+
// Create a metadata file name
220+
GenericTileIO::store_data(resources, get_uri(uri), tile, encryption_key);
222221
}
223222
}
224223

tiledb/sm/misc/constants.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,9 @@ const std::string con_commits_file_suffix = ".con";
261261
/** Suffix for the special ignore files used in TileDB. */
262262
const std::string ignore_file_suffix = ".ign";
263263

264+
/** Suffix for temporary array metadata files used in TileDB for LocalFS. */
265+
const std::string temp_file_suffix = ".tmp";
266+
264267
/** Default datatype for a generic tile. */
265268
const Datatype generic_tile_datatype = Datatype::CHAR;
266269

tiledb/sm/misc/constants.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,9 @@ extern const std::string con_commits_file_suffix;
260260
/** Suffix for the special ignore files used in TileDB. */
261261
extern const std::string ignore_file_suffix;
262262

263+
/** Suffix for temporary array metadata files used in TileDB for LocalFS. */
264+
extern const std::string temp_file_suffix;
265+
263266
/** The fragment metadata file name. */
264267
extern const std::string fragment_metadata_filename;
265268

0 commit comments

Comments
 (0)