Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Standalone 12/N: Implement and test ZarrV3ArrayWriter #304

Merged
merged 93 commits into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
93 commits
Select commit Hold shift + click to select a range
c7832d7
Move driver source files and tests to a separate directory.
aliddell Sep 17, 2024
a811e22
Define the Zarr streaming API.
aliddell Sep 17, 2024
cf89e13
Define the Zarr logger.
aliddell Sep 17, 2024
fff86c6
Rename zarr.h to acquire.zarr.h.
aliddell Sep 17, 2024
61a53bc
Merge branch 'standalone-sequence-3' into standalone-sequence-4
aliddell Sep 17, 2024
bdd0c51
Instantiate the logger's mutex.
aliddell Sep 17, 2024
d23fe1a
Implement and test stream settings, with API setters and getters.
aliddell Sep 17, 2024
3cd2bb3
Wrap C API functions in extern "C" {}
aliddell Sep 17, 2024
d099795
Document the StreamSettings getters.
aliddell Sep 17, 2024
cfd412e
Merge remote-tracking branch 'upstream/standalone-sequence-3' into st…
aliddell Sep 17, 2024
4e3b470
Merge remote-tracking branch 'upstream/standalone-sequence-4' into st…
aliddell Sep 17, 2024
da98e57
call it 'type'
aliddell Sep 17, 2024
aa3489e
Merge branch 'standalone-sequence-3' into standalone-sequence-4
aliddell Sep 17, 2024
c3e419b
Merge branch 'standalone-sequence-3' into standalone-sequence-4b
aliddell Sep 17, 2024
fdf5b08
No need to double CHECK the settings pointer.
aliddell Sep 17, 2024
cbbc87d
Implement ZarrStream_s.
aliddell Sep 17, 2024
0f28cfc
Test ZarrStream_s.
aliddell Sep 17, 2024
1ca2a1d
Implement the rest of the Zarr API functions.
aliddell Sep 17, 2024
d370e17
Implement and test Zarr common functions.
aliddell Sep 17, 2024
caf295b
Implement and test ThreadPool, S3Connection{Pool}. Also implement Blo…
aliddell Sep 17, 2024
e9102dc
Implement and test Sink and SinkCreator types.
aliddell Sep 17, 2024
9522296
Implement and test base ArrayWriter.
aliddell Sep 17, 2024
d291c53
Implement and test ZarrV2ArrayWriter.
aliddell Sep 17, 2024
082dcd0
Implement and test ZarrV3ArrayWriter.
aliddell Sep 17, 2024
996d22e
Document that ZarrStream_append will block for compression and flushing
aliddell Sep 18, 2024
d6ea43e
Merge branch 'standalone-sequence-3' into standalone-sequence-4
aliddell Sep 18, 2024
46eb93d
Merge branch 'standalone-sequence-4' into standalone-sequence-4b
aliddell Sep 18, 2024
95973d4
Merge branch 'standalone-sequence-4b' into standalone-sequence-5
aliddell Sep 18, 2024
a8b30e1
Merge branch 'standalone-sequence-5' into standalone-sequence-6
aliddell Sep 18, 2024
51f820d
Merge branch 'standalone-sequence-6' into standalone-sequence-7
aliddell Sep 18, 2024
57bc287
Merge branch 'standalone-sequence-7' into standalone-sequence-8
aliddell Sep 18, 2024
46f6cbb
Merge branch 'standalone-sequence-8' into standalone-sequence-9
aliddell Sep 18, 2024
558bbc7
Merge branch 'standalone-sequence-9' into standalone-sequence-10
aliddell Sep 18, 2024
6ae570c
Merge branch 'standalone-sequence-10' into standalone-sequence-11
aliddell Sep 18, 2024
606db8e
Merge branch 'standalone-sequence-11' into standalone-sequence-12
aliddell Sep 18, 2024
e546f7d
Respond to PR comments.
aliddell Sep 18, 2024
2d6aae1
Merge branch 'standalone-sequence-2' into standalone-sequence-3
aliddell Sep 18, 2024
a1b0034
Merge remote-tracking branch 'upstream/main' into standalone-sequence-3
aliddell Sep 18, 2024
cb5414f
Merge remote-tracking branch 'upstream/main' into standalone-sequence-4
aliddell Sep 18, 2024
a4868e8
Merge branch 'standalone-sequence-4' into standalone-sequence-4b
aliddell Sep 18, 2024
784aae6
Merge branch 'standalone-sequence-4b' into standalone-sequence-5
aliddell Sep 18, 2024
eb5b0fa
Merge branch 'standalone-sequence-5' into standalone-sequence-6
aliddell Sep 18, 2024
a25a239
Merge branch 'standalone-sequence-6' into standalone-sequence-7
aliddell Sep 18, 2024
8ce6f8f
Merge branch 'standalone-sequence-7' into standalone-sequence-8
aliddell Sep 18, 2024
c1f5207
Merge branch 'standalone-sequence-8' into standalone-sequence-9
aliddell Sep 18, 2024
c0f1fd1
Merge branch 'standalone-sequence-9' into standalone-sequence-10
aliddell Sep 18, 2024
d272794
Merge branch 'standalone-sequence-10' into standalone-sequence-11
aliddell Sep 18, 2024
82938a3
Merge branch 'standalone-sequence-11' into standalone-sequence-12
aliddell Sep 18, 2024
42a4940
Respond to PR comments.
aliddell Sep 20, 2024
9a6212f
Merge branch 'standalone-sequence-3' into standalone-sequence-4
aliddell Sep 20, 2024
e5f54ec
Merge branch 'standalone-sequence-4' into standalone-sequence-5
aliddell Sep 20, 2024
5076311
Merge branch 'standalone-sequence-6' into standalone-sequence-5
aliddell Sep 20, 2024
2853ad1
wip
aliddell Sep 20, 2024
25bfb8b
Reorder and document settings fields
aliddell Sep 20, 2024
e65f889
Merge branch 'standalone-sequence-3' into standalone-sequence-5
aliddell Sep 20, 2024
b7aeda7
wip
aliddell Sep 20, 2024
e3e6e3f
Remove version specifier from ZarrStream_create.
aliddell Sep 20, 2024
44fe333
Merge branch 'standalone-sequence-3' into standalone-sequence-5
aliddell Sep 20, 2024
401231b
wip
aliddell Sep 20, 2024
d15f431
Document the settings struct a bit.
aliddell Sep 20, 2024
10a6318
Merge branch 'standalone-sequence-3' into standalone-sequence-5
aliddell Sep 20, 2024
e6ad827
wip
aliddell Sep 20, 2024
59bea6c
Fix up some parameters.
aliddell Sep 20, 2024
e984c90
Merge branch 'standalone-sequence-3' into standalone-sequence-5
aliddell Sep 20, 2024
3a0b63a
Update ZarrStream implementation to use settings struct.
aliddell Sep 20, 2024
68dcb03
Remove some redundant code
aliddell Sep 20, 2024
78f9344
Merge branch 'standalone-sequence-5' into standalone-sequence-7
aliddell Sep 20, 2024
3c265da
Merge branch 'standalone-sequence-7' into standalone-sequence-8
aliddell Sep 20, 2024
689f1fe
Merge branch 'standalone-sequence-8' into standalone-sequence-9
aliddell Sep 20, 2024
053e238
Merge branch 'standalone-sequence-9' into standalone-sequence-10
aliddell Sep 20, 2024
4a02046
Merge branch 'standalone-sequence-10' into standalone-sequence-11
aliddell Sep 20, 2024
7fc19e2
Merge branch 'standalone-sequence-11' into standalone-sequence-12
aliddell Sep 20, 2024
87b318a
Merge branch 'standalone-sequence-8' into standalone-sequence-9
aliddell Sep 20, 2024
e76199d
Merge branch 'standalone-sequence-9' into standalone-sequence-10
aliddell Sep 20, 2024
d934260
Use string_view
aliddell Sep 23, 2024
697ef21
Merge branch 'standalone-sequence-10' into standalone-sequence-11
aliddell Sep 23, 2024
7141919
Merge branch 'standalone-sequence-11' into standalone-sequence-12
aliddell Sep 23, 2024
f342aeb
Merge remote-tracking branch 'upstream/main' into standalone-sequence-9
aliddell Sep 27, 2024
9c19086
Merge branch 'standalone-sequence-9' into standalone-sequence-10
aliddell Sep 27, 2024
0dadfa6
Merge branch 'standalone-sequence-10' into standalone-sequence-11
aliddell Sep 27, 2024
9873832
Merge branch 'standalone-sequence-11' into standalone-sequence-12
aliddell Sep 27, 2024
6bf9234
Merge remote-tracking branch 'upstream/main' into standalone-sequence-11
aliddell Oct 3, 2024
38c033f
Merge remote-tracking branch 'upstream/main' into standalone-sequence-11
aliddell Oct 3, 2024
7a61ded
Respond to PR comments
aliddell Oct 3, 2024
c35d0c4
Merge branch 'standalone-sequence-11' into standalone-sequence-12
aliddell Oct 3, 2024
c455ad7
Put #include <string> back
aliddell Oct 3, 2024
6b2e79f
Merge branch 'standalone-sequence-11' into standalone-sequence-12
aliddell Oct 3, 2024
e3ea0d3
Respond to PR comments.
aliddell Oct 3, 2024
0e1482a
Remove dead files
aliddell Oct 3, 2024
1a662c5
Merge branch 'standalone-sequence-11' into standalone-sequence-12
aliddell Oct 3, 2024
a61be1c
Some cleanup.
aliddell Oct 3, 2024
073657b
Merge remote-tracking branch 'upstream/main' into standalone-sequence-12
aliddell Oct 4, 2024
9b53bb8
Respond to PR comments.
aliddell Oct 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/streaming/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@ add_library(${tgt}
array.writer.cpp
zarrv2.array.writer.hh
zarrv2.array.writer.cpp
zarrv3.array.writer.hh
zarrv3.array.writer.cpp
)

target_include_directories(${tgt}
Expand Down
2 changes: 0 additions & 2 deletions src/streaming/array.writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -381,8 +381,6 @@ zarr::ArrayWriter::compress_buffers_()
} catch (const std::exception& exc) {
err = "Failed to compress chunk: " +
std::string(exc.what());
} catch (...) {
err = "Failed to compress chunk (unknown)";
}
latch.count_down();

Expand Down
6 changes: 0 additions & 6 deletions src/streaming/sink.creator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -342,9 +342,6 @@ zarr::SinkCreator::make_files_(std::queue<std::string>& file_paths,
} catch (const std::exception& exc) {
err = "Failed to create file '" + filename +
"': " + exc.what();
} catch (...) {
err = "Failed to create file '" + filename +
"': (unknown).";
}

latch.count_down();
Expand Down Expand Up @@ -396,9 +393,6 @@ zarr::SinkCreator::make_files_(
} catch (const std::exception& exc) {
err = "Failed to create file '" + filename +
"': " + exc.what();
} catch (...) {
err = "Failed to create file '" + filename +
"': (unknown).";
}

latch.count_down();
Expand Down
8 changes: 1 addition & 7 deletions src/streaming/zarr.stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -421,9 +421,7 @@ ZarrStream_s::create_writers_()
void
ZarrStream_s::create_scaled_frames_()
{
if (multiscale_) {
// TODO (aliddell): implement this
}
// TODO (aliddell): implement this
}

bool
Expand Down Expand Up @@ -465,9 +463,5 @@ void
ZarrStream_s::write_multiscale_frames_(const uint8_t* data,
size_t bytes_of_data)
{
if (multiscale_) {
return;
}

// TODO (aliddell): implement this
}
2 changes: 0 additions & 2 deletions src/streaming/zarrv2.array.writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,6 @@ zarr::ZarrV2ArrayWriter::flush_impl_()
} catch (const std::exception& exc) {
err = "Failed to write chunk: " +
std::string(exc.what());
} catch (...) {
err = "Failed to write chunk: (unknown)";
}

latch.count_down();
Expand Down
254 changes: 254 additions & 0 deletions src/streaming/zarrv3.array.writer.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,254 @@
#include "macros.hh"
#include "zarrv3.array.writer.hh"
#include "sink.creator.hh"
#include "zarr.common.hh"

#include <nlohmann/json.hpp>

#include <algorithm> // std::fill
#include <latch>
#include <stdexcept>

#ifdef max
#undef max
#endif
Comment on lines +12 to +14
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is max defined?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Somewhere in minio, which is included in s3.connection.hh which is included in sink.creator.hh which is included here. I have an issue here to address it.


namespace {
std::string
sample_type_to_dtype(ZarrDataType t)
{
switch (t) {
case ZarrDataType_uint8:
return "uint8";
case ZarrDataType_uint16:
return "uint16";
case ZarrDataType_uint32:
return "uint32";
case ZarrDataType_uint64:
return "uint64";
case ZarrDataType_int8:
return "int8";
case ZarrDataType_int16:
return "int16";
case ZarrDataType_int32:
return "int32";
case ZarrDataType_int64:
return "int64";
case ZarrDataType_float32:
return "float32";
case ZarrDataType_float64:
return "float64";
default:
throw std::runtime_error("Invalid ZarrDataType: " +
std::to_string(static_cast<int>(t)));
}
}
} // namespace

zarr::ZarrV3ArrayWriter::ZarrV3ArrayWriter(
ArrayWriterConfig&& config,
std::shared_ptr<ThreadPool> thread_pool)
: ZarrV3ArrayWriter(std::move(config), thread_pool, nullptr)
{
}

zarr::ZarrV3ArrayWriter::ZarrV3ArrayWriter(
ArrayWriterConfig&& config,
std::shared_ptr<ThreadPool> thread_pool,
std::shared_ptr<S3ConnectionPool> s3_connection_pool)
: ArrayWriter(std::move(config), thread_pool, s3_connection_pool)
{
const auto number_of_shards = config_.dimensions->number_of_shards();
const auto chunks_per_shard = config_.dimensions->chunks_per_shard();

shard_file_offsets_.resize(number_of_shards, 0);
shard_tables_.resize(number_of_shards);

for (auto& table : shard_tables_) {
table.resize(2 * chunks_per_shard);
std::fill(
table.begin(), table.end(), std::numeric_limits<uint64_t>::max());
}
}

bool
zarr::ZarrV3ArrayWriter::flush_impl_()
{
// create shard files if they don't exist
if (data_sinks_.empty() && !make_data_sinks_()) {
return false;
}
Comment on lines +77 to +80
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've mentioned this before in a more general context, but explicit APIs are always preferable. In this specific instance, it would be better to raise an error and notify the client that sinks need to be created first, rather than creating them implicitly. The rationale is simple: if you return false here, the caller doesn't know why—did you fail to create a sink or did you fail to flush the data? Being explicit lets the caller decide how to handle it. This is just one example. There are other reasons why implicit operations should be discouraged.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't love the idea of throwing an exception if the sinks aren't created and letting the caller (i.e., another method within the class) catch it, make the decision to create them, and then try to flush again. An empty sink vector is a signal that sinks need to be created, and that decision can be made right as they're needed.

Copy link
Collaborator

@shlomnissan shlomnissan Oct 4, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I consider this approach bad API design, but I'm not going to make the case here. Ultimately, it's up to you as the owner of this codebase.


const auto n_shards = config_.dimensions->number_of_shards();
aliddell marked this conversation as resolved.
Show resolved Hide resolved
CHECK(data_sinks_.size() == n_shards);

// get shard indices for each chunk
std::vector<std::vector<size_t>> chunk_in_shards(n_shards);
for (auto i = 0; i < chunk_buffers_.size(); ++i) {
const auto index = config_.dimensions->shard_index_for_chunk(i);
chunk_in_shards.at(index).push_back(i);
}

// write out chunks to shards
auto write_table = is_finalizing_ || should_rollover_();
std::latch latch(n_shards);
for (auto i = 0; i < n_shards; ++i) {
const auto& chunks = chunk_in_shards.at(i);
auto& chunk_table = shard_tables_.at(i);
auto* file_offset = &shard_file_offsets_.at(i);

EXPECT(thread_pool_->push_job([&sink = data_sinks_.at(i),
&chunks,
&chunk_table,
file_offset,
write_table,
&latch,
this](std::string& err) {
bool success = false;

try {
for (const auto& chunk_idx : chunks) {
auto& chunk = chunk_buffers_.at(chunk_idx);
std::span data{ reinterpret_cast<std::byte*>(chunk.data()),
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

chunk.size() };
success = sink->write(*file_offset, data);
if (!success) {
break;
}

const auto internal_idx =
config_.dimensions->shard_internal_index(chunk_idx);
chunk_table.at(2 * internal_idx) = *file_offset;
chunk_table.at(2 * internal_idx + 1) = chunk.size();

*file_offset += chunk.size();
}

if (success && write_table) {
auto* table =
reinterpret_cast<std::byte*>(chunk_table.data());
std::span data{ table,
chunk_table.size() * sizeof(uint64_t) };
success = sink->write(*file_offset, data);
}
} catch (const std::exception& exc) {
err = "Failed to write chunk: " + std::string(exc.what());
}

latch.count_down();
return success;
}),
"Failed to push job to thread pool");
}

// wait for all threads to finish
latch.wait();

// reset shard tables and file offsets
if (write_table) {
for (auto& table : shard_tables_) {
std::fill(
table.begin(), table.end(), std::numeric_limits<uint64_t>::max());
}

std::fill(shard_file_offsets_.begin(), shard_file_offsets_.end(), 0);
}

return true;
}

bool
zarr::ZarrV3ArrayWriter::write_array_metadata_()
{
if (!make_metadata_sink_()) {
return false;
}

using json = nlohmann::json;

std::vector<size_t> array_shape, chunk_shape, shard_shape;

size_t append_size = frames_written_;
for (auto i = config_.dimensions->ndims() - 3; i > 0; --i) {
const auto& dim = config_.dimensions->at(i);
const auto& array_size_px = dim.array_size_px;
CHECK(array_size_px);
append_size = (append_size + array_size_px - 1) / array_size_px;
}
array_shape.push_back(append_size);

const auto& final_dim = config_.dimensions->final_dim();
chunk_shape.push_back(final_dim.chunk_size_px);
shard_shape.push_back(final_dim.shard_size_chunks);
for (auto i = 1; i < config_.dimensions->ndims(); ++i) {
const auto& dim = config_.dimensions->at(i);
array_shape.push_back(dim.array_size_px);
chunk_shape.push_back(dim.chunk_size_px);
shard_shape.push_back(dim.shard_size_chunks);
}

json metadata;
metadata["attributes"] = json::object();
metadata["chunk_grid"] = json::object({
{ "chunk_shape", chunk_shape },
{ "separator", "/" },
{ "type", "regular" },
});

metadata["chunk_memory_layout"] = "C";
metadata["data_type"] = sample_type_to_dtype(config_.dtype);
metadata["extensions"] = json::array();
metadata["fill_value"] = 0;
metadata["shape"] = array_shape;

if (config_.compression_params) {
const auto params = *config_.compression_params;
metadata["compressor"] = json::object({
{ "codec", "https://purl.org/zarr/spec/codec/blosc/1.0" },
{ "configuration",
json::object({
{ "blocksize", 0 },
{ "clevel", params.clevel },
{ "cname", params.codec_id },
{ "shuffle", params.shuffle },
}) },
});
} else {
metadata["compressor"] = nullptr;
}

// sharding storage transformer
// TODO (aliddell):
// https://github.com/zarr-developers/zarr-python/issues/877
metadata["storage_transformers"] = json::array();
metadata["storage_transformers"][0] = json::object({
{ "type", "indexed" },
{ "extension",
"https://purl.org/zarr/spec/storage_transformers/sharding/1.0" },
{ "configuration",
json::object({
{ "chunks_per_shard", shard_shape },
}) },
});

std::string metadata_str = metadata.dump(4);
std::span data = { reinterpret_cast<std::byte*>(metadata_str.data()),
metadata_str.size() };

return metadata_sink_->write(0, data);
}

bool
zarr::ZarrV3ArrayWriter::should_rollover_() const
{
const auto& dims = config_.dimensions;
const auto& append_dim = dims->final_dim();
size_t frames_before_flush =
append_dim.chunk_size_px * append_dim.shard_size_chunks;
for (auto i = 1; i < dims->ndims() - 2; ++i) {
frames_before_flush *= dims->at(i).array_size_px;
}

CHECK(frames_before_flush > 0);
return frames_written_ % frames_before_flush == 0;
}
25 changes: 25 additions & 0 deletions src/streaming/zarrv3.array.writer.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

#include "array.writer.hh"

namespace zarr {
struct ZarrV3ArrayWriter : public ArrayWriter
{
public:
ZarrV3ArrayWriter(ArrayWriterConfig&& config,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is an r-value reference necessary in this context? I assume you want to enforce a move operation, but I'm unsure why the config should be moved rather than passed as a pointer, which is one alternative.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ArrayWriterConfig has a std::unique_ptr<ArrayDimensions> member, though the next PR reveals this does need to be a shared pointer after all, because the Stream object needs to hold on to them as well for metadata purposes.

std::shared_ptr<ThreadPool> thread_pool);
ZarrV3ArrayWriter(
ArrayWriterConfig&& config,
std::shared_ptr<ThreadPool> thread_pool,
std::shared_ptr<S3ConnectionPool> s3_connection_pool);

private:
std::vector<size_t> shard_file_offsets_;
std::vector<std::vector<uint64_t>> shard_tables_;

ZarrVersion version_() const override { return ZarrVersion_3; }
bool flush_impl_() override;
bool write_array_metadata_() override;
bool should_rollover_() const override;
};
} // namespace zarr
3 changes: 3 additions & 0 deletions tests/unit-tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ set(tests
zarrv2-writer-write-even
zarrv2-writer-write-ragged-append-dim
zarrv2-writer-write-ragged-internal-dim
zarrv3-writer-write-even
zarrv3-writer-write-ragged-append-dim
zarrv3-writer-write-ragged-internal-dim
)

foreach (name ${tests})
Expand Down
2 changes: 0 additions & 2 deletions tests/unit-tests/array-dimensions-chunk-internal-offset.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,6 @@ main()
retval = 0;
} catch (const std::exception& exc) {
LOG_ERROR("Exception: ", exc.what());
} catch (...) {
LOG_ERROR("Exception: (unknown)");
}

return retval;
Expand Down
2 changes: 0 additions & 2 deletions tests/unit-tests/array-dimensions-chunk-lattice-index.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,6 @@ main()
retval = 0;
} catch (const std::exception& exc) {
LOG_ERROR("Exception: ", exc.what());
} catch (...) {
LOG_ERROR("Exception: (unknown)");
}

return retval;
Expand Down
2 changes: 0 additions & 2 deletions tests/unit-tests/array-dimensions-shard-index-for-chunk.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,6 @@ main()
retval = 0;
} catch (const std::exception& exc) {
LOG_ERROR("Exception: ", exc.what());
} catch (...) {
LOG_ERROR("Exception: (unknown)");
}

return retval;
Expand Down
2 changes: 0 additions & 2 deletions tests/unit-tests/array-dimensions-shard-internal-index.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,6 @@ main()
retval = 0;
} catch (const std::exception& exc) {
LOG_ERROR("Exception: ", exc.what());
} catch (...) {
LOG_ERROR("Exception: (unknown)");
}

return retval;
Expand Down
Loading
Loading